[Scummvm-git-logs] scummvm master -> b7a8242b9b453d3e965f3d1d085c7456025ac8f8

sev- sev at scummvm.org
Sat Sep 10 17:08:37 CEST 2016


This automated email contains information about 330 new commits which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .

Summary:
d0225f7532 XEEN: Initial commit
977a25ec35 XEEN: Implemented resource manager
a8da12bbe4 XEEN: Added skeletons for Clouds, Dark Side, and World of Xeen engines
a933e661a9 XEEN: Added skeleton events manager and screen class
4e05f36abd XEEN: Add XSurface base class and Screen dirty rect code
42afa00392 XEEN: Initial implementation of sprite resource class
1249bc03fd XEEN: Implemented horizontal and vertical page merging
4f423c74b7 XEEN: Implement beginnings of Dark Side intro and supporting methods
d213db3dc1 XEEN: Converted SpriteResource to decoding sprite frames on the fly
1a6dd88713 XEEN: Fix error in vertMerge
cadb7176bc XEEN: Fix error in vertMerge
a93177e0b3 XEEN: Fix for correct line offsets in sprite drawing
1d62e224b9 XEEN: Implement button handlng and rest of Dark Side title screen
537da8b7b9 XEEN: Second Dark Side title screen, beginnings of starting sequence
676e7583f2 XEEN: Temporary processing of Window list data to produce formatted output
6a71a9f4d4 XEEN: Proper setup of window list
9d6de4da65 XEEN: Implemented cursor display
fb47ec9627 XEEN: In progress implementing options/main menu
9506635bad XEEN: Implemented Window functionality
5c88d2cc42 XEEN: Implement window framing code and dialog event handling
d21c47e019 XEEN: Lot of font code implemented
c6a2f539d4 XEEN: Split the font code into it's own file
6e587578c6 XEEN: Implemented writeChar
9eb2292736 XEEN: Compilation fixes
4a953b0661 XEEN: Startup fixes; options menu buttons now showing
fb6e8054f7 XEEN: Fixes for text display
4dd8c68df2 XEEN: Fix background animation for Options menu
def7e9f098 XEEN: Fix clicking to have Options menu appear
64ccc21cef XEEN: Fix options menu to show correct buttons
fe48af7de5 XEEN: Split up menus file into dialogs and dialogs_options
aa3965cd5d XEEN: Beginnings of credits screen
b2f1282aeb XEEN: Credits screen now working
5135439bbd XEEN: Reorganisation of resource, sprite, and cc file class files
971a70a2b3 XEEN: Implemented party and condition classes
feacce66b9 XEEN: Implemented dynamic data loading for new games
bef5dbdc0a XEEN: Replaced conditions array with named field structure
27e020cbf9 XEEN: Split char/party logic into it's own file
9a8cb48a9e XEEN: Cleanup of party code split, moved roster and party to engine
21d981f8e8 XEEN: Fix compiler warnings
e1404f127d XEEN: Simplified SpriteResource class, char faces loading in main engine
9b40bd5c6a XEEN: More UI loading code, refactored Dialog base to ButtonContainer
7d4fcfd5af XEEN: Added checkSkill and animating indicators to assembleBorder
1a999e3ceb XEEN: Refactored checkSkill into Party class
166676462a XEEN: Completed assembleGameBorder method
97cd5a7e69 XEEN: Split game interface code into it's own class
f9316bf141 XEEN: Implemented charIconsPrint
ce96094c9b XEEN: In progress implementing map loading
86cdb68f4d XEEN: Properly implemented map loading first loading loop
42165d21bb XEEN: Implement more map loading
eb0c292aaf XEEN: Start of in-game display implementation
31f4f5b843 XEEN: More interface setup and UI button definitions
fa0d7722f1 XEEN: Work on loading sprites for monsters and objects in Map::load
be53adbefc XEEN: Implemented map loading of wall item sprites
cd7c00ca8c XEEN: Minor standardisation on monster/object Ids
96d086ab9c XEEN: Add prefix support to CC files, initial save state fixes
f9414fe525 XEEN: Further fix for savegame initialization
03952cd9d3 XEEN: Fix to load correct default savegame
00ef21e2a2 XEEN: Fixed monster/object data merging and sprite loading
08e64d0a61 XEEN: Added indoor/outdoor draw structure lists
8f0c5543fb XEEN: Beginning to implement setIndoorObjects
49787629ff XEEN: Various renamings
0b5f79afb7 XEEN: Added loading of event data for maps
3b1edcdf36 XEEN: Implemented code for 'saving' resources to the loaded savefile
edccbe63f2 XEEN: Added saving of maze monster/object data
4745bfe182 XEEN: Implemented setIndoorObjects
892a504009 XEEN: Implemented loading of object animation data
1b3473d343 XEEN: Implement frame update loop of draw3d
d8e23aa558 XEEN: Split up SCREEN_POSITIONING array and fix data
230c4f52ea XEEN: Implemented map getCell method
488847006c XEEN: Implemented setMazeBits
07f37cedf5 XEEN: Change _currentWall to be MazeWallLayers union
747ca9eb2f XEEN: Implemented indoor drawing code in draw3d
1a0a597ff8 XEEN: Add indoor terrain loading and indoor list sprite setting to Map::load
a856e58ee4 XEEN: Added Combat class and further map loading sprite setting
2b78d5190b XEEN: Implementing drawIndoors
5f2e145580 XEEN: Remainder of drawIndoors implemented
e6383519a1 XEEN: Split in-game scene draw code into a separate file
17f946305c XEEN: Formatting fixes
7bfbda627a XEEN: Initial bugfixes for map loading and fix draw list positions
7e4580a220 XEEN: Add cropping support to sprite drawing
3e7163769d XEEN: Beginnings of setIndoorMonsters implementation
ce3cb6f1db XEEN: Finished setIndoorsMonsters
d6497f78f0 XEEN: Implement setIndoorsWallPics
0ceefedce5 XEEN: Fix frame calculations for low part of _indoorList
b83b63b0cf XEEN: Fix _wp switch statements
484901e7a2 XEEN: Fixes and cleanup for setIndoorsObjects
6bfd599535 XEEN: Fixes for map loading cells and indoor sprite list references
d37e3d6e74 XEEN: Minor cleanup and renamings
e0305aa9d9 XEEN: Fix loading correct monster sprites
b860745a8e XEEN: Add support for horizontally flipped sprites
258ab02096 XEEN: Load sprites from the correct archive
ceeda17ab1 XEEN: Remove old test sprite from being displayed
9925453774 XEEN: Fix loading of MonsterData array
f18a8c364b XEEN: Convert default values for monsters flying flags from int to bool
07a10855be XEEN: In progress work on sprite scaling
ecdf6412a6 XEEN: Fix drawing the game window border
e4c4736306 XEEN: Renaming of flags and surface display
130bd58e2c XEEN: Load correct surface sprites for the maze
b12e26836a XEEN: Disable initial fade out for now
f46b9d77dd XEEN: Compilation fixes for gcc
83442b9586 XEEN: Fix Valgrind warnings
687423b361 XEEN: Beginnings of main game loop and waiting
ec294d662e XEEN: Add extra ending code for pausing turns
e559a99c27 XEEN: Initial implementation of drawMiniMap
1f312098ad XEEN: Minor minimap fixes
e966feff5e XEEN: Implemented movement code
ebc155ac0a XEEN: Replaced UI button values with KeyCode constants
dc8592a912 XEEN: Fix loading of wall types
a1fb631fe3 XEEN: Fix resetting sprites on ground tiles when drawing
8cd2e5ad92 XEEN: Further work on sprite scaling
d32c90eee9 XEEN: Some minimap drawing fixes
aab62d606e XEEN: More minimap fixes
2427f203ee XEEN: Implemented handleLight
8b4d25d415 XEEN: Implemented doStepCode
5cc3afab72 XEEN: Implemented getNewMaze
397a10eae5 XEEN: Moved setMazeBits to InterfaceMap and fixed some incorrect code in it
adce5f9c20 XEEN: Convert map _skySprites into a 2 element array
69ca508e8f XEEN: Fix settig stepped on tiles
932222de7d XEEN: Skeleton beginnings of script handling
1b264ed299 XEEN: Implemented the first few script commands
16a5a99c3a XEEN: Fix strings used by newly added script commands
4c0c40c25d XEEN: Shifted more logic for 3d view drawing from Interface to InterfaceMap
b597d71bcd XEEN: Implemented animate3d
2b51d324f3 XEEN: Implemented dialogs for Who Will and YesNo
749372e456 XEEN: More script code and string input dialog
c08e54fde1 XEEN: Implement further script opcodes
fac1d0642f XEEN: Implement script opcodes for cmdCallEvent and cmdReturn
7bfc034421 XEEN: Implement cmdJumpRnd script opcode
06b7eb220e XEEN: Implemented If script opcode
3ec43ce1cc XEEN: Implement the cmdRemove and cmdMakeNothingHere script opcodes
b533822c06 XEEN: Implement lots of stubbed PlayerStruct methods
1f8a5ea24a XEEN: Changed PlayerStruct to Character
2b5167cafc XEEN: Fix side loading bug in Map::load
de1341ddb5 XEEN: Add special case block to Map::load
f69fd28fe0 XEEN: Fixes for hit points calculations
82010fb5ef XEEN: Formatting fixes
c17c2aead5 XEEN: Implemented outdoors drawing code in draw3d
a04daf3820 XEEN: Implemented drawOutdoorsMonsters
409edeb1e8 XEEN: Implemented drawOutdoorsObjects
177f47a535 XEEN: Implement drawOutdoors
339dfcb2cc XEEN: Restrict drawing in windows to drawing within their bounds
c01120aedd XEEN: Extra comments to sprite resource class
41f7664fa8 XEEN: Implemented cmdIf opcode
f742dc8d33 XEEN: Fixes to ifProc
0d8d66cb82 XEEN: Fix center aligning text in writeString
fe6b580ff1 XEEN: Implement cmdCheckProtection and cmdAlterEvent opcodes
2a9c00cb96 XEEN: Fix to cmdSpawn, and implemented cmdSetValue
b695934a1e XEEN: Implemented cmdTeleport opcode
51dba2606e XEEN: Simplify _currentWall back to int for now
482c2b2ac8 XEEN: Fix immediate crash in outdoors rendering
3135d1e0a7 XEEN: Fix rendering in drawOutdoors
7b387dbd89 XEEN: Fix clearing Please Wait window after changing maps
ef283252b3 XEEN: Fix keyboard keys in YesNo dialog
50d3d79d7f XEEN: Revert window restriction, since all window draws use absolute x,y
94ce2c1e6f XEEN: Fix display of outdoors objects
84741d73a0 XEEN: Properly clear previous MazeData when loading a new map
2abce62b8f XEEN: Add skeleton for spells class
f11e11006b XEEN: Beginnings of Town class, implemented handleAction
81e1bd2930 XEEN: Implemented createTownText
88382b2d8f XEEN: Added NumericInput class and refactored existing string input
5030d0046f XEEN: Implemented depositWithdrawl and subtract
689776d922 XEEN: Implemented doTownOptions
a755ce6e92 XEEN: Implement hilight/unhilightChar, bufixes for Tavern display
8a324eb755 XEEN: Implemented drawTownAnim
5228879a1d XEEN: Fix for entering/exiting tavern display
16b8382d6e XEEN: Fix display of buy message for buying tavern food
1f28332b20 XEEN: Add saving/restoring of background when opening/closing windows
60c462bfdc XEEN: Fixes for tavern options
e34429207c XEEN: Add missing c_str to a Common::String::format call
be327cb767 XEEN: Implemented setSpellText for spells dialog
29753a29a4 XEEN: Implemented SpellsDialog and ConfirmDialog classes
4b364c50d6 XEEN: Fix glitch in indoor walls drawing
2472cc0917 XEEN: Initial implementation of map dialog
b22418de08 XEEN: Bugfixes for the automap dialog
d67b8d364d XEEN: More automap dialog fixes
73a522150f XEEN: Yet more bugfixes for automap dialog
40b2f886c3 XEEN: Implement the Info dialog
d3e3093b03 XEEN: Add missing moveMonsters flag setting for automap and info dialogs
d855aa0dab XEEN: Implemented Character Info dialog
3ae4958f0b XEEN: Implemented Exchange character dialog
d57c9f2021 XEEN: Fixes to the Character Info dialog
2b2ce19012 XEEN: Fixes for Character Info dialog stat details display
78234db2c0 XEEN: Add Quick Reference dialog
7febe77300 XEEN: Beginnings of Items dialog
2b8303c0d8 XEEN: Implemented assembleItemName method
3767f31619 XEEN: Implemented calcItemCost
38df23ace0 XEEN: Implemented passRestrictions
f34c5ad9b6 XEEN: Finished Items dailog loading block for weapons
4953b7954a XEEN: Partial implementation of doItemOptions
8eb9ad50f8 XEEN: Split Character class into it's own file
7ea32f3333 XEEN: Moved passRestrictions to the InventoryItems class
a983d9abce XEEN: Implemented weapon variation of equipItem
fc04fe6da8 XEEN: equipItem methods for armor and accessories
85c2dd5f68 XEEN: Split up assembleItemName and renamed to getFullDescription
6595abcf14 XEEN: Moved _maeNames to a new Resources class
b39f4179ce XEEN: Merged confirmation and yes/no dialogs into single source file
d40c62532a XEEN: Implemented makeItem
5ffbe2de87 XEEN: Implemented getIdentifiedDetails and getAttributes
4bd128be7f XEEN: Finished doItemOptions
b633704847 XEEN: Implemented remainder of ItemsDialog
90db7872f1 XEEN: Implement Quests dialog
528fce5ac4 XEEN: Fix headers and key handling in Quests dialog
c313113f6b XEEN: Fix for switching modes and loading auto notes in Quests dialog
996ce24083 XEEN: Fix writeString to constrain text to window
54ae7eb22a XEEN: Fix incorrect variable usage in makeItem
65ecc9b721 XEEN: Another fix for makeItem variable usage
d6e760552e XEEN: Implemented resting
a381c49c4d XEEN: Implemented bashing
ccb224d89a XEEN: In progress Dismiss dialog
62eb39515b XEEN: Some refactoring needed for resources the party dialog will need
c798a55510 XEEN: More refactoring needed for party dialog setup
a612dd686c XEEN: Further refactoring for party dialog setup
8256f7c8df XEEN: Refacored face sprites loading into Roster and Character classes
e596178345 XEEN: Refactored drawing the party icons into a separate class
50ae4f9522 XEEN: Refactored _partyCount and _partyMembers into the _activeParty array
2f39bd5cd2 XEEN: Fixes for display of party dialog
6548dd05e3 XEEN: Fix removing and adding chars to party in Party dialog
a39b0b24a1 XEEN: Fix changing selected character with mouse in various dialogs
2772cd33c1 XEEN: Implemented code for deleting characters in Party dialog
e16ecd110b XEEN: Implementing create chracter dialog
d225bc4cb3 XEEN: Implemented saveCharacter
9b0b0cd9e7 XEEN: Implemented exchangeAttribute
b79d552c06 XEEN: Implemented drawDice
cad435d9a0 XEEN: Fix default display of doors
dae789369e XEEN: Fix _buttonValue check for moving through doorways
cc9f62fcb9 XEEN: Split up draw3d between Interface and InterfaceMap, start of fall code
6605a0c505 XEEN: Implemented more code from end of draw3d
a90ad5b4c1 XEEN: Move drawMiniMap to Interface class
74b4d91f4a XEEN: Implemented startFalling
adde24a338 XEEN: Move more code from InterfaceMap that should be in Interface class
93e5fd7c20 XEEN: Moved more variables out of InterfaceMap that belong in Interface
bdc8e73c1b XEEN: Fix walking through walls
ef2a4595c2 XEEN: Moved _openDoor into InterfaceMap
75a070de17 XEEN: Implementing combat methods
e7ffed76b4 XEEN: Implemented giveCharDamage
30d94950be XEEN: Starting of combat UI, moved _combatParty into Combat class
c045adae76 XEEN: Implementing more combat logic
7b3c10b09c XEEN: Implemented Cast Spell dialog
1d5d98e898 XEEN: Fix display of buttons in Cast Spell window
6a7fd1952d XEEN: Fixes for display of Spells dialog
0f78fb9373 XEEN: Implement extra code for passing active character to castSpell
da368f5e00 XEEN: Add special case spell handling during combat
aa89e602a2 XEEN: Spell dialogs fixes for non-casters
cd5bc0ec7e XEEN: Simplify use of addButton when setting up button lists
4c420a70be XEEN: Fix drawing buttons in Spells dialog when switching character
e17d258217 XEEN: Fix display of spell names in Spells dialog
7c3f373b9b XEEN: Fix selecting spells to cast in spells dialog
b66bf1a838 XEEN: Implemented stopAttack
caf7f376b3 XEEN: Implemented monsterAttack
ebc134a267 XEEN: Implement attackMonster and breakAllItems
917b143ec9 XEEN: Implement attack method
b790e9bac1 XEEN: Implemented attack2
c5a98b0093 XEEN: Implement more combat methods
f49b1f9b43 XEEN: Implemented giveTreasure
c99a901f65 XEEN: More code for dismiss dialog
458bf83097 XEEN: Restrict sprite drawing to window bounds
6126d45b0b XEEN: Remove redundant comment from drawList method
3f27fd8bb7 XEEN: Fix horizontal positioning for flipped images
c15ca5ca50 XEEN: Fix compiler warning
3e05d9008e XEEN: Merge scaling code from XSurface into sprite drawing code
2d2fc3f9ed XEEN: Add horizontal placement fix for scaled sprites
ddf7171001 XEEN: Fix placement of objects in setIndoorsObjects
9725fc5725 XEEN: Renaming and move flags used for UI indicators
cba25ea458 XEEN: Fix placement of enemies
20bdb154f6 XEEN: Fix _newDay initialization
5bb494fff1 XEEN: Fix mosnters moving towards party
0e1bd4951b XEEN: Prevent double call to moveMonsters
ad33b8bb82 XEEN: Fixed display of attacking monster names
9a8c4c55a3 XEEN: Add a MonsterStruct pointer to the MazeMonster class
9b6749cab8 XEEN: Fix display of combat action buttons
b4c8c81a83 XEEN: Properly reimplement nextChar
4191335dfa XEEN: Method rename and compilation warning fixes
68e30b2967 XEEN: Fix monster/party taking turns in combat
19007bac40 XEEN: Fix hang calling checkEvents when in combat mode
c069a7f805 XEEN: Fix mode change across display of CastSpell dialog
dc7e4153d4 XEEN: Fixes for attacking monsters
349ad82f93 XEEN: Fix moving backwards
b46561ef29 XEEN: Implemented openGrate
b9539c6cb1 XEEN: Fixes for marking grates as unlocked
302b3cdc63 XEEN: Fix updating cell flag that grate is unlocked
973c5a0df5 XEEN: Implemented multiAttack
b378709478 XEEN: Implement shoot action
99aa64bda4 XEEN: Fix crash on shooting
93cc299eaf XEEN: Implement addHitPoints and spellFX methods
810619072a XEEN: gcc compilation fixes
b414ff26f2 XEEN: Implement some of the spells
9789962605 XEEN: Implemented protection from elements spell
07f504fe16 XEEN: Fix ordering of spell list and methods
b243768887 XEEN: Implementing spells
c6506b567c XEEN: Implemented more spells
ee5b8ed59f XEEN: Implement remaining spells
8e6708e600 XEEN: Hook up debugger properly and implement spell command
02c046941b XEEN: Fixes for text entry
7bbbfd2ad0 XEEN: Implementing more script opcodes
de5aedcb0c XEEN: Implemented cmNPC and TownMessage dialog class
66dc9ac746 XEEN: Implement give/take script opcodes
8101f8d03b XEEN: More script opcodes
15d375bc44 XEEN: Implement remaining missing code in checkEvents
652a662315 XEEN: Implement cmdChooseNumeric script opcode
b0016071ec Merge branch 'msvc_2015' into xeen
76ba9185dd XEEN: Change sprite drawing to use the same algorithm as original
80fcbaf441 XEEN: Restore dirty rect handling in sprite drawing
c2c00894f2 XEEN: Implement SPRFLAG_SCENE_CLIPPED drawing flag
0bb223cd3a XEEN: Fix graphic corruption on images with skipped pixels
43e16714df XEEN: Implement sprite enlargement drawing
e06c879a47 XEEN: Fix displaying sky when outdoors
569f3c65b7 XEEN: Beginnings of work on copy protection check method
619a165f35 XEEN: Merge Clouds and DarkSide engines into WorldOfXeenEngine
b6e39dbf79 XEEN: Some initial work on better sound manager
0ade2da5f1 XEEN: Further work on VOC sound method prototypes
8211727285 XEEN: Remove duplicate methods
9c92f9fa47 XEEN: Moved in-progress Dark Side intro to it's own file
5b0f460581 XEEN: Implementing more of Dark Side intro
d8c28d15ae XEEN: Create stub files for other Clouds/DarkSide cutscenes
504cf6ecb6 Merge branch 'master' into xeen
873d555add XEEN: Add detection for German World of Xeen
f5ab3d1cd9 Merge branch 'master' into xeen
552f0cce8e XEEN: Move game cutscene methods into their own classes
0c199f079b XEEN: Beginnings of sound effects support
ef6253fb19 XEEN: gcc compilation fixes
dffa696b7b XEEN: gcc compilation fixes
fd2d462296 XEEN: Moved method comments from CPP to header files
6dc1551d7d XEEN: gcc compilation fixes
63a4201541 XEEN: Change a strncpy use to Common::strlcpy
0c948b6bd0 XEEN: Fix Travis identified warnings
12d57ad5fe XEEN: Beginnings of Darkside endgame and music
94e1b960c4 XEEN: Converted XSurface to derive from ManagedSurface
1a99d8ee8d XEEN: Fix compiler warnings
a520a18a01 XEEN: Further fix identified warnings
b7a8242b9b Merge pull request #818 from dreammaster/xeen


Commit: d0225f753274d9a04045a14dfe9a1b1b8aeae371
    https://github.com/scummvm/scummvm/commit/d0225f753274d9a04045a14dfe9a1b1b8aeae371
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2014-12-23T15:49:35+11:00

Commit Message:
XEEN: Initial commit

Changed paths:
  A engines/xeen/configure.engine
  A engines/xeen/debugger.cpp
  A engines/xeen/debugger.h
  A engines/xeen/detection.cpp
  A engines/xeen/detection_tables.h
  A engines/xeen/module.mk
  A engines/xeen/xeen.cpp
  A engines/xeen/xeen.h



diff --git a/engines/xeen/configure.engine b/engines/xeen/configure.engine
new file mode 100644
index 0000000..489254f
--- /dev/null
+++ b/engines/xeen/configure.engine
@@ -0,0 +1,3 @@
+# This file is included from the main "configure" script
+# add_engine [name] [desc] [build-by-default] [subengines] [base games] [deps]
+add_engine xeen "World of Xeen" no
diff --git a/engines/xeen/debugger.cpp b/engines/xeen/debugger.cpp
new file mode 100644
index 0000000..0642498
--- /dev/null
+++ b/engines/xeen/debugger.cpp
@@ -0,0 +1,56 @@
+/* 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 "xeen/xeen.h"
+#include "xeen/debugger.h"
+
+namespace Xeen {
+
+static int strToInt(const char *s) {
+	if (!*s)
+		// No string at all
+		return 0;
+	else if (toupper(s[strlen(s) - 1]) != 'H')
+		// Standard decimal string
+		return atoi(s);
+
+	// Hexadecimal string
+	uint tmp = 0;
+	int read = sscanf(s, "%xh", &tmp);
+	if (read < 1)
+		error("strToInt failed on string \"%s\"", s);
+	return (int)tmp;
+}
+
+/*------------------------------------------------------------------------*/
+
+Debugger::Debugger(XeenEngine *vm) : GUI::Debugger(), _vm(vm) {
+	registerCmd("continue", WRAP_METHOD(Debugger, cmdExit));
+	registerCmd("scene", WRAP_METHOD(Debugger, Cmd_LoadScene));
+}
+
+bool Debugger::Cmd_LoadScene(int argc, const char **argv) {
+	return true;
+}
+
+} // End of namespace Access
diff --git a/engines/xeen/debugger.h b/engines/xeen/debugger.h
new file mode 100644
index 0000000..6a1ec12
--- /dev/null
+++ b/engines/xeen/debugger.h
@@ -0,0 +1,44 @@
+/* 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_DEBUGGER_H
+#define XEEN_DEBUGGER_H
+
+#include "common/scummsys.h"
+#include "gui/debugger.h"
+
+namespace Xeen {
+
+class XeenEngine;
+
+class Debugger : public GUI::Debugger {
+protected:
+	XeenEngine *_vm;
+
+	bool Cmd_LoadScene(int argc, const char **argv);
+public:
+	Debugger(XeenEngine *vm);
+};
+
+} // End of namespace Xeen
+
+#endif	/* XEEN_DEBUGGER_H */
diff --git a/engines/xeen/detection.cpp b/engines/xeen/detection.cpp
new file mode 100644
index 0000000..2b30478
--- /dev/null
+++ b/engines/xeen/detection.cpp
@@ -0,0 +1,183 @@
+/* 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 "xeen/xeen.h"
+
+#include "base/plugins.h"
+#include "common/savefile.h"
+#include "engines/advancedDetector.h"
+#include "common/system.h"
+
+#define MAX_SAVES 99
+
+namespace Xeen {
+
+struct XeenGameDescription {
+	ADGameDescription desc;
+
+	int gameID;
+	uint32 features;
+};
+
+uint32 XeenEngine::getGameID() const {
+	return _gameDescription->gameID;
+}
+
+uint32 XeenEngine::getGameFeatures() const {
+	return _gameDescription->features;
+}
+
+uint32 XeenEngine::getFeatures() const {
+	return _gameDescription->desc.flags;
+}
+
+Common::Language XeenEngine::getLanguage() const {
+	return _gameDescription->desc.language;
+}
+
+Common::Platform XeenEngine::getPlatform() const {
+	return _gameDescription->desc.platform;
+}
+
+} // End of namespace Xeen
+
+static const PlainGameDescriptor XeenGames[] = {
+	{ "xeen", "Xeen" },
+	{ "worldofxeen", "World of Xeen" },
+	{0, 0}
+};
+
+#include "xeen/detection_tables.h"
+
+class XeenMetaEngine : public AdvancedMetaEngine {
+public:
+	XeenMetaEngine() : AdvancedMetaEngine(Xeen::gameDescriptions, sizeof(Xeen::XeenGameDescription), XeenGames) {
+		_maxScanDepth = 3;
+	}
+
+	virtual const char *getName() const {
+		return "Xeen Engine";
+	}
+
+	virtual const char *getOriginalCopyright() const {
+		return "Xeen Engine (c) ???";
+	}
+
+	virtual bool hasFeature(MetaEngineFeature f) const;
+	virtual bool createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const;
+	virtual SaveStateList listSaves(const char *target) const;
+	virtual int getMaximumSaveSlot() const;
+	virtual void removeSaveState(const char *target, int slot) const;
+	SaveStateDescriptor querySaveMetaInfos(const char *target, int slot) const;
+};
+
+bool XeenMetaEngine::hasFeature(MetaEngineFeature f) const {
+	return
+	    (f == kSupportsListSaves) ||
+		(f == kSupportsLoadingDuringStartup) ||
+		(f == kSupportsDeleteSave) ||
+		(f == kSavesSupportMetaInfo) ||
+		(f == kSavesSupportThumbnail);
+}
+
+bool Xeen::XeenEngine::hasFeature(EngineFeature f) const {
+	return
+		(f == kSupportsRTL) ||
+		(f == kSupportsLoadingDuringRuntime) ||
+		(f == kSupportsSavingDuringRuntime);
+}
+
+bool XeenMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const {
+	const Xeen::XeenGameDescription *gd = (const Xeen::XeenGameDescription *)desc;
+	*engine = new Xeen::XeenEngine(syst, gd);
+	return gd != 0;
+}
+
+SaveStateList XeenMetaEngine::listSaves(const char *target) const {
+	Common::SaveFileManager *saveFileMan = g_system->getSavefileManager();
+	Common::StringArray filenames;
+	Common::String saveDesc;
+	Common::String pattern = Common::String::format("%s.0??", target);
+	Xeen::XeenSavegameHeader header;
+
+	filenames = saveFileMan->listSavefiles(pattern);
+	sort(filenames.begin(), filenames.end());   // Sort to get the files in numerical order
+
+	SaveStateList saveList;
+	for (Common::StringArray::const_iterator file = filenames.begin(); file != filenames.end(); ++file) {
+		const char *ext = strrchr(file->c_str(), '.');
+		int slot = ext ? atoi(ext + 1) : -1;
+
+		if (slot >= 0 && slot < MAX_SAVES) {
+			Common::InSaveFile *in = g_system->getSavefileManager()->openForLoading(*file);
+
+			if (in) {
+				Xeen::XeenEngine::readSavegameHeader(in, header);
+				saveList.push_back(SaveStateDescriptor(slot, header._saveName));
+
+				header._thumbnail->free();
+				delete header._thumbnail;
+				delete in;
+			}
+		}
+	}
+
+	return saveList;
+}
+
+int XeenMetaEngine::getMaximumSaveSlot() const {
+	return MAX_SAVES;
+}
+
+void XeenMetaEngine::removeSaveState(const char *target, int slot) const {
+	Common::String filename = Common::String::format("%s.%03d", target, slot);
+	g_system->getSavefileManager()->removeSavefile(filename);
+}
+
+SaveStateDescriptor XeenMetaEngine::querySaveMetaInfos(const char *target, int slot) const {
+	Common::String filename = Common::String::format("%s.%03d", target, slot);
+	Common::InSaveFile *f = g_system->getSavefileManager()->openForLoading(filename);
+
+	if (f) {
+		Xeen::XeenSavegameHeader header;
+		Xeen::XeenEngine::readSavegameHeader(f, header);
+		delete f;
+
+		// Create the return descriptor
+		SaveStateDescriptor desc(slot, header._saveName);
+		desc.setThumbnail(header._thumbnail);
+		desc.setSaveDate(header._year, header._month, header._day);
+		desc.setSaveTime(header._hour, header._minute);
+		desc.setPlayTime(header._totalFrames * GAME_FRAME_TIME);
+
+		return desc;
+	}
+
+	return SaveStateDescriptor();
+}
+
+
+#if PLUGIN_ENABLED_DYNAMIC(XEEN)
+	REGISTER_PLUGIN_DYNAMIC(XEEN, PLUGIN_TYPE_ENGINE, XeenMetaEngine);
+#else
+	REGISTER_PLUGIN_STATIC(XEEN, PLUGIN_TYPE_ENGINE, XeenMetaEngine);
+#endif
diff --git a/engines/xeen/detection_tables.h b/engines/xeen/detection_tables.h
new file mode 100644
index 0000000..e106abf
--- /dev/null
+++ b/engines/xeen/detection_tables.h
@@ -0,0 +1,48 @@
+/* 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.
+ *
+ */
+
+namespace Xeen {
+
+static const XeenGameDescription gameDescriptions[] = {
+	{
+		// World of Xeen
+		{
+			"worldofxeen",
+			nullptr,
+			{
+				{ "xeen.cc", 0, "0cffbab533d9afe140e69ec93096f43e", 13435646 },
+				{ "dark.cc", 0, "df194483ecea6abc0511637d712ced7c", 11217676 },
+				AD_LISTEND
+			},
+			Common::EN_ANY,
+			Common::kPlatformDOS,
+			ADGF_NO_FLAGS,
+			GUIO1(GUIO_NONE)
+		},
+		GType_World,
+		0
+	},
+
+	{ AD_TABLE_END_MARKER, 0, 0 }
+};
+
+} // End of namespace Xeen
diff --git a/engines/xeen/module.mk b/engines/xeen/module.mk
new file mode 100644
index 0000000..a33b26a
--- /dev/null
+++ b/engines/xeen/module.mk
@@ -0,0 +1,13 @@
+MODULE := engines/xeen
+
+MODULE_OBJS := \
+	detection.o \
+	xeen.o
+
+# This module can be built as a plugin
+ifeq ($(ENABLE_XEEN), DYNAMIC_PLUGIN)
+PLUGIN := 1
+endif
+
+# Include common rules
+include $(srcdir)/rules.mk
diff --git a/engines/xeen/xeen.cpp b/engines/xeen/xeen.cpp
new file mode 100644
index 0000000..3fe75e1
--- /dev/null
+++ b/engines/xeen/xeen.cpp
@@ -0,0 +1,209 @@
+/* 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 "common/config-manager.h"
+#include "common/debug-channels.h"
+#include "common/events.h"
+#include "engines/util.h"
+#include "graphics/scaler.h"
+#include "graphics/thumbnail.h"
+#include "xeen/xeen.h"
+
+namespace Xeen {
+
+XeenEngine::XeenEngine(OSystem *syst, const XeenGameDescription *gameDesc)
+		: _gameDescription(gameDesc), Engine(syst), _randomSource("Xeen") {
+	_debugger = nullptr;
+}
+
+XeenEngine::~XeenEngine() {
+	delete _debugger;
+}
+
+void XeenEngine::initialize() {
+	// Set up debug channels
+	DebugMan.addDebugChannel(kDebugPath, "Path", "Pathfinding debug level");
+	DebugMan.addDebugChannel(kDebugScripts, "scripts", "Game scripts");
+	DebugMan.addDebugChannel(kDebugGraphics, "graphics", "Graphics handling");
+	DebugMan.addDebugChannel(kDebugSound, "sound", "Sound and Music handling");
+
+	// Create sub-objects of the engine
+	_debugger = new Debugger(this);
+
+	// Set graphics mode
+	initGraphics(320, 200, false);
+
+	// If requested, load a savegame instead of showing the intro
+	if (ConfMan.hasKey("save_slot")) {
+		int saveSlot = ConfMan.getInt("save_slot");
+		if (saveSlot >= 0 && saveSlot <= 999)
+			_loadSaveSlot = saveSlot;
+	}
+}
+
+Common::Error XeenEngine::run() {
+	initialize();
+
+	playGame();
+
+	return Common::kNoError;
+}
+
+int XeenEngine::getRandomNumber(int maxNumber) {
+	return _randomSource.getRandomNumber(maxNumber);
+}
+
+Common::Error XeenEngine::saveGameState(int slot, const Common::String &desc) {
+	Common::OutSaveFile *out = g_system->getSavefileManager()->openForSaving(
+		generateSaveName(slot));
+	if (!out)
+		return Common::kCreatingFileFailed;
+
+	XeenSavegameHeader header;
+	header._saveName = desc;
+	writeSavegameHeader(out, header);
+
+	Common::Serializer s(nullptr, out);
+	synchronize(s);
+
+	out->finalize();
+	delete out;
+
+	return Common::kNoError;
+}
+
+Common::Error XeenEngine::loadGameState(int slot) {
+	Common::InSaveFile *saveFile = g_system->getSavefileManager()->openForLoading(
+		generateSaveName(slot));
+	if (!saveFile)
+		return Common::kReadingFailed;
+
+	Common::Serializer s(saveFile, nullptr);
+
+	// Load the savaegame header
+	XeenSavegameHeader header;
+	if (!readSavegameHeader(saveFile, header))
+		error("Invalid savegame");
+
+	if (header._thumbnail) {
+		header._thumbnail->free();
+		delete header._thumbnail;
+	}
+
+	// Load most of the savegame data
+	synchronize(s);
+	delete saveFile;
+
+	return Common::kNoError;
+}
+
+Common::String XeenEngine::generateSaveName(int slot) {
+	return Common::String::format("%s.%03d", _targetName.c_str(), slot);
+}
+
+bool XeenEngine::canLoadGameStateCurrently() {
+	return true;
+}
+
+bool XeenEngine::canSaveGameStateCurrently() {
+	return true;
+}
+
+void XeenEngine::synchronize(Common::Serializer &s) {
+	// TODO
+}
+
+const char *const SAVEGAME_STR = "XEEN";
+#define SAVEGAME_STR_SIZE 6
+
+bool XeenEngine::readSavegameHeader(Common::InSaveFile *in, XeenSavegameHeader &header) {
+	char saveIdentBuffer[SAVEGAME_STR_SIZE + 1];
+	header._thumbnail = nullptr;
+
+	// Validate the header Id
+	in->read(saveIdentBuffer, SAVEGAME_STR_SIZE + 1);
+	if (strncmp(saveIdentBuffer, SAVEGAME_STR, SAVEGAME_STR_SIZE))
+		return false;
+
+	header._version = in->readByte();
+	if (header._version > XEEN_SAVEGAME_VERSION)
+		return false;
+
+	// Read in the string
+	header._saveName.clear();
+	char ch;
+	while ((ch = (char)in->readByte()) != '\0')
+		header._saveName += ch;
+
+	// Get the thumbnail
+	header._thumbnail = Graphics::loadThumbnail(*in);
+	if (!header._thumbnail)
+		return false;
+
+	// Read in save date/time
+	header._year = in->readSint16LE();
+	header._month = in->readSint16LE();
+	header._day = in->readSint16LE();
+	header._hour = in->readSint16LE();
+	header._minute = in->readSint16LE();
+	header._totalFrames = in->readUint32LE();
+
+	return true;
+}
+
+void XeenEngine::writeSavegameHeader(Common::OutSaveFile *out, XeenSavegameHeader &header) {
+	// Write out a savegame header
+	out->write(SAVEGAME_STR, SAVEGAME_STR_SIZE + 1);
+
+	out->writeByte(XEEN_SAVEGAME_VERSION);
+
+	// Write savegame name
+	out->writeString(header._saveName);
+	out->writeByte('\0');
+
+	// Write a thumbnail of the screen
+/*
+	uint8 thumbPalette[768];
+	_screen->getPalette(thumbPalette);
+	Graphics::Surface saveThumb;
+	::createThumbnail(&saveThumb, (const byte *)_screen->getPixels(),
+		_screen->w, _screen->h, thumbPalette);
+	Graphics::saveThumbnail(*out, saveThumb);
+	saveThumb.free();
+*/
+	// Write out the save date/time
+	TimeDate td;
+	g_system->getTimeAndDate(td);
+	out->writeSint16LE(td.tm_year + 1900);
+	out->writeSint16LE(td.tm_mon + 1);
+	out->writeSint16LE(td.tm_mday);
+	out->writeSint16LE(td.tm_hour);
+	out->writeSint16LE(td.tm_min);
+//	out->writeUint32LE(_events->getFrameCounter());
+}
+
+void XeenEngine::playGame() {
+	// TODO
+}
+
+} // End of namespace Xeen
diff --git a/engines/xeen/xeen.h b/engines/xeen/xeen.h
new file mode 100644
index 0000000..2566c1b
--- /dev/null
+++ b/engines/xeen/xeen.h
@@ -0,0 +1,153 @@
+/* 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_XEEN_H
+#define XEEN_XEEN_H
+
+#include "common/scummsys.h"
+#include "common/system.h"
+#include "common/error.h"
+#include "common/random.h"
+#include "common/savefile.h"
+#include "common/serializer.h"
+#include "common/util.h"
+#include "engines/engine.h"
+#include "graphics/surface.h"
+#include "xeen/debugger.h"
+
+/**
+ * This is the namespace of the Xeen engine.
+ *
+ * Status of this engine: In Development
+ *
+ * Games using this engine:
+ * - Might & Magic 4: Clouds of Xeen
+ * - Might & Magic 5: Dark Side of Xeen
+ * - Might & Magic: World of Xeen
+ * - Might & Magic: Swords of Xeen
+ */
+namespace Xeen {
+
+enum {
+	GType_Clouds = 1,
+	GType_Dark = 2,
+	GType_World = 3,
+	GType_Swords = 4
+};
+
+enum XeenDebugChannels {
+	kDebugPath      = 1 << 0,
+	kDebugScripts	= 1 << 1,
+	kDebugGraphics	= 1 << 2,
+	kDebugSound     = 1 << 3
+};
+
+struct XeenGameDescription;
+
+#define XEEN_SAVEGAME_VERSION 1
+#define GAME_FRAME_TIME 50
+
+struct XeenSavegameHeader {
+	uint8 _version;
+	Common::String _saveName;
+	Graphics::Surface *_thumbnail;
+	int _year, _month, _day;
+	int _hour, _minute;
+	int _totalFrames;
+};
+
+class XeenEngine : public Engine {
+private:
+	const XeenGameDescription *_gameDescription;
+	Common::RandomSource _randomSource;
+	int _loadSaveSlot;
+private:
+	void initialize();
+
+	/**
+	* Play the game
+	*/
+	void playGame();
+
+	/**
+	* Synchronize savegame data
+	*/
+	void synchronize(Common::Serializer &s);
+
+	/**
+	* Support method that generates a savegame name
+	* @param slot		Slot number
+	*/
+	Common::String generateSaveName(int slot);
+
+	// Engine APIs
+	virtual Common::Error run();
+	virtual bool hasFeature(EngineFeature f) const;
+public:
+	Debugger *_debugger;
+public:
+	XeenEngine(OSystem *syst, const XeenGameDescription *gameDesc);
+	virtual ~XeenEngine();
+
+	uint32 getFeatures() const;
+	Common::Language getLanguage() const;
+	Common::Platform getPlatform() const;
+	uint16 getVersion() const;
+	uint32 getGameID() const;
+	uint32 getGameFeatures() const;
+
+	int getRandomNumber(int maxNumber);
+
+	/**
+	 * Load a savegame
+	 */
+	virtual Common::Error loadGameState(int slot);
+
+	/**
+	 * Save the game
+	 */
+	virtual Common::Error saveGameState(int slot, const Common::String &desc);
+
+	/**
+	 * Returns true if a savegame can currently be loaded
+	 */
+	bool canLoadGameStateCurrently();
+
+	/**
+	* Returns true if the game can currently be saved
+	*/
+	bool canSaveGameStateCurrently();
+
+	/**
+	 * Read in a savegame header
+	 */
+	static bool readSavegameHeader(Common::InSaveFile *in, XeenSavegameHeader &header);
+
+	/**
+	 * Write out a savegame header
+	 */
+	void writeSavegameHeader(Common::OutSaveFile *out, XeenSavegameHeader &header);
+};
+
+} // End of namespace Xeen
+
+#endif /* XEEN_XEEN_H */


Commit: 977a25ec35d63fab0db315b35a69a4a508f587e9
    https://github.com/scummvm/scummvm/commit/977a25ec35d63fab0db315b35a69a4a508f587e9
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2014-12-24T09:58:47+11:00

Commit Message:
XEEN: Implemented resource manager

Changed paths:
  A engines/xeen/resources.cpp
  A engines/xeen/resources.h
    engines/xeen/module.mk
    engines/xeen/xeen.cpp



diff --git a/engines/xeen/module.mk b/engines/xeen/module.mk
index a33b26a..d129d10 100644
--- a/engines/xeen/module.mk
+++ b/engines/xeen/module.mk
@@ -1,7 +1,9 @@
 MODULE := engines/xeen
 
 MODULE_OBJS := \
+	debugger.o \
 	detection.o \
+	resources.o \
 	xeen.o
 
 # This module can be built as a plugin
diff --git a/engines/xeen/resources.cpp b/engines/xeen/resources.cpp
new file mode 100644
index 0000000..f99be12
--- /dev/null
+++ b/engines/xeen/resources.cpp
@@ -0,0 +1,214 @@
+/* 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 "common/archive.h"
+#include "common/memstream.h"
+#include "common/textconsole.h"
+#include "xeen/xeen.h"
+#include "xeen/resources.h"
+
+namespace Xeen {
+
+/**
+ * Xeen CC file implementation
+ */
+class CCArchive : public Common::Archive {
+private:
+	/**
+	 * Details of a single entry in a CC file index
+	 */
+	struct CCEntry {
+		uint16 _id;
+		uint32 _offset;
+		uint16 _size;
+
+		CCEntry() : _id(0), _offset(0), _size(0) {}
+		CCEntry(uint16 id, uint32 offset, uint32 size)
+			: _id(id), _offset(offset), _size(size) {
+		}
+	};
+
+	Common::Array<CCEntry> _index;
+	Common::String _filename;
+
+	uint16 convertNameToId(const Common::String &resourceName) const;
+
+	void loadIndex(Common::SeekableReadStream *stream);
+
+	bool getHeaderEntry(const Common::String &resourceName, CCEntry &ccEntry) const;
+public:
+	CCArchive(const Common::String &filename);
+	virtual ~CCArchive();
+
+	// Archive implementation
+	virtual bool hasFile(const Common::String &name) const;
+	virtual int listMembers(Common::ArchiveMemberList &list) const;
+	virtual const Common::ArchiveMemberPtr getMember(const Common::String &name) const;
+	virtual Common::SeekableReadStream *createReadStreamForMember(const Common::String &name) const;
+};
+
+CCArchive::CCArchive(const Common::String &filename): _filename(filename) {
+	File f(filename);
+	loadIndex(&f);
+}
+
+CCArchive::~CCArchive() {
+}
+
+// Archive implementation
+bool CCArchive::hasFile(const Common::String &name) const {
+	CCEntry ccEntry;
+	return getHeaderEntry(name, ccEntry);
+}
+
+int CCArchive::listMembers(Common::ArchiveMemberList &list) const {
+	// CC files don't maintain the original filenames, so we can't list it
+	return 0;
+}
+
+const Common::ArchiveMemberPtr CCArchive::getMember(const Common::String &name) const {
+	if (!hasFile(name))
+		return Common::ArchiveMemberPtr();
+
+	return Common::ArchiveMemberPtr(new Common::GenericArchiveMember(name, this));
+}
+
+Common::SeekableReadStream *CCArchive::createReadStreamForMember(const Common::String &name) const {
+	CCEntry ccEntry;
+
+	if (getHeaderEntry(name, ccEntry)) {
+		// Open the correct CC file
+		Common::File f;
+		if (!f.open(_filename))
+			error("Could not open CC file");
+
+		// Read in the data for the specific resource
+		f.seek(ccEntry._offset);
+		byte *data = new byte[ccEntry._size];
+		f.read(data, ccEntry._size);
+
+		// Decrypt the data
+		for (int i = 0; i < ccEntry._size; ++i)
+			data[i] ^= 0x35;
+
+		// Return the data as a stream
+		return new Common::MemoryReadStream(data, ccEntry._size, DisposeAfterUse::YES);
+	}
+
+	return nullptr;
+}
+
+/**
+ * Hash a given filename to produce the Id that represents it
+ */
+uint16 CCArchive::convertNameToId(const Common::String &resourceName) const {
+	if (resourceName.empty())
+		return 0xffff;
+
+	Common::String name = resourceName;
+	name.toUppercase();
+
+	const byte *msgP = (const byte *)name.c_str();
+	int total = *msgP++;
+	for (; *msgP; total += *msgP++) {
+		// Rotate the bits in 'total' right 7 places
+		total = (total & 0x007F) << 9 | (total & 0xFF80) >> 7;
+	}
+
+	return total;
+}
+
+/**
+ * Load the index of a given CC file
+ */
+void CCArchive::loadIndex(Common::SeekableReadStream *stream) {
+	int count = stream->readUint16LE();
+
+	// Read in the data for the archive's index
+	byte *rawIndex = new byte[count * 8];
+	stream->read(rawIndex, count * 8);
+
+	// Decrypt the index
+	int ah = 0xac;
+	for (int i = 0; i < count * 8; ++i) {
+		rawIndex[i] = (byte)(((rawIndex[i] << 2 | rawIndex[i] >> 6) + ah) & 0xff);
+		ah += 0x67;
+	}
+
+	// Extract the index data into entry structures
+	_index.reserve(count);
+	const byte *entryP = &rawIndex[0];
+	for (int i = 0; i < count; ++i, entryP += 8) {
+		CCEntry entry;
+		entry._id = READ_LE_UINT16(entryP);
+		entry._offset = READ_LE_UINT32(entryP + 2) & 0xffffff;
+		entry._size = READ_LE_UINT16(entryP + 5);
+		assert(!entryP[7]);
+
+		_index.push_back(entry);
+	}
+
+	delete[] rawIndex;
+}
+
+/**
+* Given a resource name, returns whether an entry exists, and returns
+* the header index data for that entry
+*/
+bool CCArchive::getHeaderEntry(const Common::String &resourceName, CCEntry &ccEntry) const {
+	uint16 id = convertNameToId(resourceName);
+
+	// Loop through the index
+	for (uint i = 0; i < _index.size(); ++i) {
+		if (_index[i]._id == id) {
+			ccEntry = _index[i];
+			return true;
+		}
+	}
+
+	// Could not find an entry
+	return false;
+}
+
+/*------------------------------------------------------------------------*/
+
+void Resources::init(XeenEngine *vm) {
+	Common::File f;
+
+	const char *ARCHIVES[3] = { "xeen", "dark", "intro" };
+	for (int i = 0; i < 3; ++i) {
+		Common::String filename = Common::String::format("%s.cc", ARCHIVES[i]);
+		if (f.exists(filename)) {
+			SearchMan.add(ARCHIVES[i], new CCArchive(filename));
+		}
+	}
+}
+
+/*------------------------------------------------------------------------*/
+
+void File::openFile(const Common::String &filename) {
+	if (!Common::File::open(filename))
+		error("Could not open file - %s", filename.c_str());
+}
+
+} // End of namespace Xeen
diff --git a/engines/xeen/resources.h b/engines/xeen/resources.h
new file mode 100644
index 0000000..61b6310
--- /dev/null
+++ b/engines/xeen/resources.h
@@ -0,0 +1,64 @@
+/* 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_RESOURCES_H
+#define XEEN_RESOURCES_H
+
+#include "common/scummsys.h"
+#include "common/file.h"
+
+namespace Xeen {
+
+class XeenEngine;
+
+class Resources {
+public:
+	/**
+	 * Instantiates the resource manager
+	 */
+	static void init(XeenEngine *vm);
+};
+
+/**
+ * Derived file class
+ */
+class File : public Common::File {
+public:
+	/**
+	 * Constructor
+	 */
+	File() : Common::File() {}
+
+	/**
+	 * Constructor
+	 */
+	File(const Common::String &filename) { openFile(filename); }
+
+	/**
+	 * Opens the given file, throwing an error if it can't be opened
+	 */
+	void openFile(const Common::String &filename);
+};
+
+} // End of namespace MADS
+
+#endif /* MADS_RESOURCES_H */
diff --git a/engines/xeen/xeen.cpp b/engines/xeen/xeen.cpp
index 3fe75e1..12871fd 100644
--- a/engines/xeen/xeen.cpp
+++ b/engines/xeen/xeen.cpp
@@ -28,6 +28,7 @@
 #include "graphics/scaler.h"
 #include "graphics/thumbnail.h"
 #include "xeen/xeen.h"
+#include "xeen/resources.h"
 
 namespace Xeen {
 
@@ -49,6 +50,7 @@ void XeenEngine::initialize() {
 
 	// Create sub-objects of the engine
 	_debugger = new Debugger(this);
+	Resources::init(this);
 
 	// Set graphics mode
 	initGraphics(320, 200, false);
@@ -204,6 +206,8 @@ void XeenEngine::writeSavegameHeader(Common::OutSaveFile *out, XeenSavegameHeade
 
 void XeenEngine::playGame() {
 	// TODO
+	// Test resource manager
+	File f("FNT");
 }
 
 } // End of namespace Xeen


Commit: a8da12bbe4684183cbe4d5c6ac480af2515d07cf
    https://github.com/scummvm/scummvm/commit/a8da12bbe4684183cbe4d5c6ac480af2515d07cf
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2014-12-25T17:02:51+11:00

Commit Message:
XEEN: Added skeletons for Clouds, Dark Side, and World of Xeen engines

Changed paths:
  A engines/xeen/clouds/clouds_game.cpp
  A engines/xeen/clouds/clouds_game.h
  A engines/xeen/darkside/darkside_game.cpp
  A engines/xeen/darkside/darkside_game.h
  A engines/xeen/worldofxeen/worldofxeen_game.cpp
  A engines/xeen/worldofxeen/worldofxeen_game.h
    engines/xeen/detection.cpp
    engines/xeen/detection_tables.h
    engines/xeen/module.mk
    engines/xeen/xeen.cpp
    engines/xeen/xeen.h



diff --git a/engines/xeen/clouds/clouds_game.cpp b/engines/xeen/clouds/clouds_game.cpp
new file mode 100644
index 0000000..4987ce0
--- /dev/null
+++ b/engines/xeen/clouds/clouds_game.cpp
@@ -0,0 +1,38 @@
+/* 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 "xeen/clouds/clouds_game.h"
+
+namespace Xeen {
+
+CloudsEngine::CloudsEngine(OSystem *syst, const XeenGameDescription *gameDesc)
+		: XeenEngine(syst, gameDesc) {
+}
+
+void CloudsEngine::playGame() {
+	cloudsIntro();
+}
+
+void CloudsEngine::cloudsIntro() {
+}
+
+} // End of namespace Xeen
diff --git a/engines/xeen/clouds/clouds_game.h b/engines/xeen/clouds/clouds_game.h
new file mode 100644
index 0000000..a8c4fbe
--- /dev/null
+++ b/engines/xeen/clouds/clouds_game.h
@@ -0,0 +1,42 @@
+/* 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_CLOUDS_GAME_H
+#define XEEN_CLOUDS_GAME_H
+
+#include "xeen/xeen.h"
+
+namespace Xeen {
+
+class CloudsEngine : virtual public XeenEngine {
+protected:
+	void cloudsIntro();
+
+	virtual void playGame();
+public:
+	CloudsEngine(OSystem *syst, const XeenGameDescription *gameDesc);
+	virtual ~CloudsEngine() {}
+};
+
+} // End of namespace Xeen
+
+#endif /* XEEN_CLOUDS_GAME_H */
diff --git a/engines/xeen/darkside/darkside_game.cpp b/engines/xeen/darkside/darkside_game.cpp
new file mode 100644
index 0000000..bc0d156
--- /dev/null
+++ b/engines/xeen/darkside/darkside_game.cpp
@@ -0,0 +1,38 @@
+/* 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 "xeen/darkside/darkside_game.h"
+
+namespace Xeen {
+
+DarkSideEngine::DarkSideEngine(OSystem *syst, const XeenGameDescription *gameDesc)
+		: XeenEngine(syst, gameDesc) {
+}
+
+void DarkSideEngine::playGame() {
+	playGame();
+}
+
+void DarkSideEngine::darkSideIntro() {
+}
+
+} // End of namespace Xeen
diff --git a/engines/xeen/darkside/darkside_game.h b/engines/xeen/darkside/darkside_game.h
new file mode 100644
index 0000000..827ba20
--- /dev/null
+++ b/engines/xeen/darkside/darkside_game.h
@@ -0,0 +1,42 @@
+/* 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_DARKSIDE_GAME_H
+#define XEEN_DARKSIDE_GAME_H
+
+#include "xeen/xeen.h"
+
+namespace Xeen {
+
+class DarkSideEngine : virtual public XeenEngine {
+protected:
+	void darkSideIntro();
+
+	virtual void playGame();
+public:
+	DarkSideEngine(OSystem *syst, const XeenGameDescription *gameDesc);
+	virtual ~DarkSideEngine() {}
+};
+
+} // End of namespace Xeen
+
+#endif /* XEEN_DARKSIDE_GAME_H */
diff --git a/engines/xeen/detection.cpp b/engines/xeen/detection.cpp
index 2b30478..3bd4c22 100644
--- a/engines/xeen/detection.cpp
+++ b/engines/xeen/detection.cpp
@@ -21,6 +21,9 @@
  */
 
 #include "xeen/xeen.h"
+#include "xeen/clouds/clouds_game.h"
+#include "xeen/darkside/darkside_game.h"
+#include "xeen/worldofxeen/worldofxeen_game.h"
 
 #include "base/plugins.h"
 #include "common/savefile.h"
@@ -62,6 +65,8 @@ Common::Platform XeenEngine::getPlatform() const {
 
 static const PlainGameDescriptor XeenGames[] = {
 	{ "xeen", "Xeen" },
+	{ "clouds", "Clouds of Xeen" },
+	{ "darkside", "Dark Side of Xeen" },
 	{ "worldofxeen", "World of Xeen" },
 	{0, 0}
 };
@@ -108,7 +113,21 @@ bool Xeen::XeenEngine::hasFeature(EngineFeature f) const {
 
 bool XeenMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const {
 	const Xeen::XeenGameDescription *gd = (const Xeen::XeenGameDescription *)desc;
-	*engine = new Xeen::XeenEngine(syst, gd);
+
+	switch (gd->gameID) {
+	case Xeen::GType_Clouds:
+		*engine = new Xeen::CloudsEngine(syst, gd);
+		break;
+	case Xeen::GType_DarkSide:
+		*engine = new Xeen::DarkSideEngine(syst, gd);
+		break;
+	case Xeen::GType_WorldOfXeen:
+		*engine = new Xeen::WorldOfXeenEngine(syst, gd);
+		break;
+	default:
+		break;
+	}
+
 	return gd != 0;
 }
 
diff --git a/engines/xeen/detection_tables.h b/engines/xeen/detection_tables.h
index e106abf..0735daa 100644
--- a/engines/xeen/detection_tables.h
+++ b/engines/xeen/detection_tables.h
@@ -38,7 +38,7 @@ static const XeenGameDescription gameDescriptions[] = {
 			ADGF_NO_FLAGS,
 			GUIO1(GUIO_NONE)
 		},
-		GType_World,
+		GType_WorldOfXeen,
 		0
 	},
 
diff --git a/engines/xeen/module.mk b/engines/xeen/module.mk
index d129d10..b02d26d 100644
--- a/engines/xeen/module.mk
+++ b/engines/xeen/module.mk
@@ -1,6 +1,9 @@
 MODULE := engines/xeen
 
 MODULE_OBJS := \
+	clouds\clouds_game.o \
+	darkside\darkside_game.o \
+	worldofxeen\worldofxeen_game.o \
 	debugger.o \
 	detection.o \
 	resources.o \
diff --git a/engines/xeen/worldofxeen/worldofxeen_game.cpp b/engines/xeen/worldofxeen/worldofxeen_game.cpp
new file mode 100644
index 0000000..f27b8b9
--- /dev/null
+++ b/engines/xeen/worldofxeen/worldofxeen_game.cpp
@@ -0,0 +1,36 @@
+/* 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 "xeen/worldofxeen/worldofxeen_game.h"
+
+namespace Xeen {
+
+WorldOfXeenEngine::WorldOfXeenEngine(OSystem *syst, const XeenGameDescription *gameDesc)
+		: CloudsEngine(syst, gameDesc), DarkSideEngine(syst, gameDesc), 
+		XeenEngine(syst, gameDesc) {
+}
+
+void WorldOfXeenEngine::playGame () {
+	darkSideIntro();
+}
+
+} // End of namespace Xeen
diff --git a/engines/xeen/worldofxeen/worldofxeen_game.h b/engines/xeen/worldofxeen/worldofxeen_game.h
new file mode 100644
index 0000000..7227e11
--- /dev/null
+++ b/engines/xeen/worldofxeen/worldofxeen_game.h
@@ -0,0 +1,41 @@
+/* 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_WORLDOFXEEN_GAME_H
+#define XEEN_WORLDOFXEEN_GAME_H
+
+#include "xeen/clouds/clouds_game.h"
+#include "xeen/darkside/darkside_game.h"
+
+namespace Xeen {
+
+class WorldOfXeenEngine : public DarkSideEngine, CloudsEngine {
+protected:
+	virtual void playGame();
+public:
+	WorldOfXeenEngine(OSystem *syst, const XeenGameDescription *gameDesc);
+	virtual ~WorldOfXeenEngine() {}
+};
+
+} // End of namespace Xeen
+
+#endif /* XEEN_WORLDOFXEEN_GAME_H */
diff --git a/engines/xeen/xeen.cpp b/engines/xeen/xeen.cpp
index 12871fd..73f0c24 100644
--- a/engines/xeen/xeen.cpp
+++ b/engines/xeen/xeen.cpp
@@ -205,9 +205,6 @@ void XeenEngine::writeSavegameHeader(Common::OutSaveFile *out, XeenSavegameHeade
 }
 
 void XeenEngine::playGame() {
-	// TODO
-	// Test resource manager
-	File f("FNT");
 }
 
 } // End of namespace Xeen
diff --git a/engines/xeen/xeen.h b/engines/xeen/xeen.h
index 2566c1b..e5122ce 100644
--- a/engines/xeen/xeen.h
+++ b/engines/xeen/xeen.h
@@ -49,8 +49,8 @@ namespace Xeen {
 
 enum {
 	GType_Clouds = 1,
-	GType_Dark = 2,
-	GType_World = 3,
+	GType_DarkSide = 2,
+	GType_WorldOfXeen = 3,
 	GType_Swords = 4
 };
 
@@ -80,13 +80,13 @@ private:
 	const XeenGameDescription *_gameDescription;
 	Common::RandomSource _randomSource;
 	int _loadSaveSlot;
-private:
-	void initialize();
-
+protected:
 	/**
 	* Play the game
 	*/
-	void playGame();
+	virtual void playGame();
+private:
+	void initialize();
 
 	/**
 	* Synchronize savegame data


Commit: a933e661a93a0bf3466ba2dabc2f8d36e3587c5d
    https://github.com/scummvm/scummvm/commit/a933e661a93a0bf3466ba2dabc2f8d36e3587c5d
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2014-12-25T19:29:38+11:00

Commit Message:
XEEN: Added skeleton events manager and screen class

Changed paths:
  A engines/xeen/events.cpp
  A engines/xeen/events.h
  A engines/xeen/screen.cpp
  A engines/xeen/screen.h
    engines/xeen/debugger.cpp
    engines/xeen/module.mk
    engines/xeen/xeen.cpp
    engines/xeen/xeen.h



diff --git a/engines/xeen/debugger.cpp b/engines/xeen/debugger.cpp
index 0642498..aa4516e 100644
--- a/engines/xeen/debugger.cpp
+++ b/engines/xeen/debugger.cpp
@@ -53,4 +53,4 @@ bool Debugger::Cmd_LoadScene(int argc, const char **argv) {
 	return true;
 }
 
-} // End of namespace Access
+} // End of namespace Xeen
diff --git a/engines/xeen/events.cpp b/engines/xeen/events.cpp
new file mode 100644
index 0000000..e75744e
--- /dev/null
+++ b/engines/xeen/events.cpp
@@ -0,0 +1,113 @@
+/* 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 "graphics/cursorman.h"
+#include "common/events.h"
+#include "common/endian.h"
+#include "engines/util.h"
+#include "xeen/xeen.h"
+#include "xeen/events.h"
+#include "xeen/screen.h"
+
+namespace Xeen {
+
+/**
+ * Constructor
+ */
+EventsManager::EventsManager(XeenEngine *vm) : _vm(vm) {
+	_frameCounter = 0;
+	_priorFrameCounterTime = 0;
+	_gameCounter = 0;
+	_priorGameCounterTime = 0;
+}
+
+/**
+ * Destructor
+ */
+EventsManager::~EventsManager() {
+}
+
+/**
+ * Show the mouse cursor
+ */
+void EventsManager::showCursor() {
+	CursorMan.showMouse(true);
+}
+
+/**
+ * Hide the mouse cursor
+ */
+void EventsManager::hideCursor() {
+	CursorMan.showMouse(false);
+}
+
+/**
+ * Returns if the mouse cursor is visible
+ */
+bool EventsManager::isCursorVisible() {
+	return CursorMan.isVisible();
+}
+
+void EventsManager::pollEvents() {
+	uint32 timer = g_system->getMillis();
+	if (timer >= (_priorFrameCounterTime + GAME_FRAME_TIME)) {
+		_priorFrameCounterTime = timer;
+		nextFrame();
+	}
+
+	Common::Event event;
+	while (g_system->getEventManager()->pollEvent(event)) {
+		switch (event.type) {
+		case Common::EVENT_QUIT:
+		case Common::EVENT_RTL:
+			return;
+		default:
+ 			break;
+		}
+	}
+}
+
+/**
+ * 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;
+}
+
+/**
+ * Handles moving to the next game frame
+ */
+void EventsManager::nextFrame() {
+	++_frameCounter;
+	_vm->_screen->update();
+}
+
+} // End of namespace Xeen
diff --git a/engines/xeen/events.h b/engines/xeen/events.h
new file mode 100644
index 0000000..637d710
--- /dev/null
+++ b/engines/xeen/events.h
@@ -0,0 +1,66 @@
+/* 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_EVENTS_H
+#define XEEN_EVENTS_H
+
+#include "common/scummsys.h"
+#include "common/events.h"
+
+namespace Xeen {
+
+#define GAME_FRAME_RATE (1000 / 18.2)
+
+class XeenEngine;
+
+class EventsManager {
+private:
+	XeenEngine *_vm;
+	uint32 _frameCounter;
+	uint32 _priorFrameCounterTime;
+	uint32 _gameCounter;
+	uint32 _priorGameCounterTime;
+
+	void nextFrame();
+public:
+	EventsManager(XeenEngine *vm);
+
+	~EventsManager();
+
+	uint32 getFrameCounter() { return _frameCounter; }
+
+	void showCursor();
+
+	void hideCursor();
+
+	bool isCursorVisible();
+
+	void pollEvents();
+
+	void updateGameCounter();
+
+	uint32 timeElapsed();
+};
+
+} // End of namespace Xeen
+
+#endif /* XEEN_EVENTS_H */
diff --git a/engines/xeen/module.mk b/engines/xeen/module.mk
index b02d26d..3b4529e 100644
--- a/engines/xeen/module.mk
+++ b/engines/xeen/module.mk
@@ -6,7 +6,9 @@ MODULE_OBJS := \
 	worldofxeen\worldofxeen_game.o \
 	debugger.o \
 	detection.o \
+	events.o \
 	resources.o \
+	screen.o \
 	xeen.o
 
 # This module can be built as a plugin
diff --git a/engines/xeen/screen.cpp b/engines/xeen/screen.cpp
new file mode 100644
index 0000000..d17e010
--- /dev/null
+++ b/engines/xeen/screen.cpp
@@ -0,0 +1,38 @@
+/* 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 "xeen/screen.h"
+
+namespace Xeen {
+
+/**
+ * Constructor
+ */
+Screen::Screen(XeenEngine *vm) : _vm(vm) {
+}
+
+void Screen::update() {
+	g_system->copyRectToScreen(getPixels(), pitch, 0, 0, w, h);
+	g_system->updateScreen();
+}
+
+} // End of namespace Xeen
diff --git a/engines/xeen/screen.h b/engines/xeen/screen.h
new file mode 100644
index 0000000..94dce60
--- /dev/null
+++ b/engines/xeen/screen.h
@@ -0,0 +1,45 @@
+/* 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_SCREEN_H
+#define XEEN_SCREEN_H
+
+#include "common/scummsys.h"
+#include "common/system.h"
+#include "graphics/surface.h"
+
+namespace Xeen {
+
+class XeenEngine;
+
+class Screen: public Graphics::Surface {
+private:
+	XeenEngine *_vm;
+public:
+	Screen(XeenEngine *vm);
+
+	void update();
+};
+
+} // End of namespace Xeen
+
+#endif /* XEEN_SCREEN_H */
diff --git a/engines/xeen/xeen.cpp b/engines/xeen/xeen.cpp
index 73f0c24..cf60aa4 100644
--- a/engines/xeen/xeen.cpp
+++ b/engines/xeen/xeen.cpp
@@ -35,10 +35,14 @@ namespace Xeen {
 XeenEngine::XeenEngine(OSystem *syst, const XeenGameDescription *gameDesc)
 		: _gameDescription(gameDesc), Engine(syst), _randomSource("Xeen") {
 	_debugger = nullptr;
+	_events = nullptr;
+	_screen = nullptr;
 }
 
 XeenEngine::~XeenEngine() {
 	delete _debugger;
+	delete _events;
+	delete _screen;
 }
 
 void XeenEngine::initialize() {
@@ -50,6 +54,8 @@ void XeenEngine::initialize() {
 
 	// Create sub-objects of the engine
 	_debugger = new Debugger(this);
+	_events = new EventsManager(this);
+	_screen = new Screen(this);
 	Resources::init(this);
 
 	// Set graphics mode
diff --git a/engines/xeen/xeen.h b/engines/xeen/xeen.h
index e5122ce..dba340e 100644
--- a/engines/xeen/xeen.h
+++ b/engines/xeen/xeen.h
@@ -33,6 +33,8 @@
 #include "engines/engine.h"
 #include "graphics/surface.h"
 #include "xeen/debugger.h"
+#include "xeen/events.h"
+#include "xeen/screen.h"
 
 /**
  * This is the namespace of the Xeen engine.
@@ -104,6 +106,8 @@ private:
 	virtual bool hasFeature(EngineFeature f) const;
 public:
 	Debugger *_debugger;
+	EventsManager *_events;
+	Screen *_screen;
 public:
 	XeenEngine(OSystem *syst, const XeenGameDescription *gameDesc);
 	virtual ~XeenEngine();


Commit: 4e05f36abdbeb0a0215c0ad5e939bce9a65cf69a
    https://github.com/scummvm/scummvm/commit/4e05f36abdbeb0a0215c0ad5e939bce9a65cf69a
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2014-12-25T20:56:35+11:00

Commit Message:
XEEN: Add XSurface base class and Screen dirty rect code

Changed paths:
  A engines/xeen/xsurface.cpp
  A engines/xeen/xsurface.h
    engines/xeen/module.mk
    engines/xeen/resources.cpp
    engines/xeen/resources.h
    engines/xeen/screen.cpp
    engines/xeen/screen.h



diff --git a/engines/xeen/module.mk b/engines/xeen/module.mk
index 3b4529e..c036376 100644
--- a/engines/xeen/module.mk
+++ b/engines/xeen/module.mk
@@ -9,7 +9,8 @@ MODULE_OBJS := \
 	events.o \
 	resources.o \
 	screen.o \
-	xeen.o
+	xeen.o \
+	xsurface.o
 
 # This module can be built as a plugin
 ifeq ($(ENABLE_XEEN), DYNAMIC_PLUGIN)
diff --git a/engines/xeen/resources.cpp b/engines/xeen/resources.cpp
index f99be12..e9c31e3 100644
--- a/engines/xeen/resources.cpp
+++ b/engines/xeen/resources.cpp
@@ -206,9 +206,27 @@ void Resources::init(XeenEngine *vm) {
 
 /*------------------------------------------------------------------------*/
 
+/**
+ * Opens the given file, throwing an error if it can't be opened
+ */
 void File::openFile(const Common::String &filename) {
 	if (!Common::File::open(filename))
 		error("Could not open file - %s", filename.c_str());
 }
 
+/*------------------------------------------------------------------------*/
+
+SpriteResource::SpriteResource(const Common::String &filename) {
+
+}
+
+int SpriteResource::size() const {
+	return _frames.size();
+}
+
+const XSurface &SpriteResource::getFrame(int frame) {
+	return _frames[frame];
+}
+
+
 } // End of namespace Xeen
diff --git a/engines/xeen/resources.h b/engines/xeen/resources.h
index 61b6310..4cf5212 100644
--- a/engines/xeen/resources.h
+++ b/engines/xeen/resources.h
@@ -24,7 +24,10 @@
 #define XEEN_RESOURCES_H
 
 #include "common/scummsys.h"
+#include "common/array.h"
 #include "common/file.h"
+#include "graphics/surface.h"
+#include "xeen/xsurface.h"
 
 namespace Xeen {
 
@@ -43,22 +46,24 @@ public:
  */
 class File : public Common::File {
 public:
-	/**
-	 * Constructor
-	 */
 	File() : Common::File() {}
-
-	/**
-	 * Constructor
-	 */
 	File(const Common::String &filename) { openFile(filename); }
+	virtual ~File() {}
 
-	/**
-	 * Opens the given file, throwing an error if it can't be opened
-	 */
 	void openFile(const Common::String &filename);
 };
 
-} // End of namespace MADS
+class SpriteResource {
+private:
+	Common::Array<XSurface> _frames;
+public:
+	SpriteResource(const Common::String &filename);
+
+	int size() const;
+
+	const XSurface &getFrame(int frame);
+};
+
+} // End of namespace Xeen
 
 #endif /* MADS_RESOURCES_H */
diff --git a/engines/xeen/screen.cpp b/engines/xeen/screen.cpp
index d17e010..038222b 100644
--- a/engines/xeen/screen.cpp
+++ b/engines/xeen/screen.cpp
@@ -31,8 +31,73 @@ Screen::Screen(XeenEngine *vm) : _vm(vm) {
 }
 
 void Screen::update() {
-	g_system->copyRectToScreen(getPixels(), pitch, 0, 0, w, h);
+	// Merge the dirty rects
+	mergeDirtyRects();
+
+	// Loop through copying dirty areas to the physical screen
+	Common::List<Common::Rect>::iterator i;
+	for (i = _dirtyRects.begin(); i != _dirtyRects.end(); ++i) {
+		const Common::Rect &r = *i;
+		const byte *srcP = (const byte *)getBasePtr(r.left, r.top);
+		g_system->copyRectToScreen(srcP, this->pitch, r.left, r.top,
+			r.width(), r.height());
+	}
+
+	// Signal the physical screen to update
 	g_system->updateScreen();
+	_dirtyRects.clear();
+}
+
+void Screen::addDirtyRect(const Common::Rect &r) {
+	_dirtyRects.push_back(r);
+}
+
+void Screen::transBlitFrom(const XSurface &src, const Common::Point &destPos) {
+	XSurface::transBlitFrom(src, destPos);
+	addDirtyRect(Common::Rect(destPos.x, destPos.y, destPos.x + src.w, destPos.y + src.h));
+}
+
+void Screen::blitFrom(const XSurface &src, const Common::Point &destPos) {
+	XSurface::blitFrom(src, destPos);
+	addDirtyRect(Common::Rect(destPos.x, destPos.y, destPos.x + src.w, destPos.y + src.h));
+}
+
+void Screen::mergeDirtyRects() {
+	Common::List<Common::Rect>::iterator rOuter, rInner;
+
+	// Ensure dirty rect list has at least two entries
+	rOuter = _dirtyRects.begin();
+	for (int i = 0; i < 2; ++i, ++rOuter) {
+		if (rOuter == _dirtyRects.end())
+			return;
+	}
+
+	// Process the dirty rect list to find any rects to merge
+	for (rOuter = _dirtyRects.begin(); rOuter != _dirtyRects.end(); ++rOuter) {
+		rInner = rOuter;
+		while (++rInner != _dirtyRects.end()) {
+
+			if ((*rOuter).intersects(*rInner)) {
+				// these two rectangles overlap or
+				// are next to each other - merge them
+
+				unionRectangle(*rOuter, *rOuter, *rInner);
+
+				// remove the inner rect from the list
+				_dirtyRects.erase(rInner);
+
+				// move back to beginning of list
+				rInner = rOuter;
+			}
+		}
+	}
+}
+
+bool Screen::unionRectangle(Common::Rect &destRect, const Common::Rect &src1, const Common::Rect &src2) {
+	destRect = src1;
+	destRect.extend(src2);
+
+	return !destRect.isEmpty();
 }
 
 } // End of namespace Xeen
diff --git a/engines/xeen/screen.h b/engines/xeen/screen.h
index 94dce60..491b702 100644
--- a/engines/xeen/screen.h
+++ b/engines/xeen/screen.h
@@ -25,19 +25,32 @@
 
 #include "common/scummsys.h"
 #include "common/system.h"
-#include "graphics/surface.h"
+#include "common/array.h"
+#include "common/rect.h"
+#include "xeen/xsurface.h"
 
 namespace Xeen {
 
 class XeenEngine;
 
-class Screen: public Graphics::Surface {
+class Screen: public XSurface {
 private:
 	XeenEngine *_vm;
+	Common::List<Common::Rect> _dirtyRects;
+
+	void mergeDirtyRects();
+
+	bool unionRectangle(Common::Rect &destRect, const Common::Rect &src1, const Common::Rect &src2);
+public:
+	virtual void transBlitFrom(const XSurface &src, const Common::Point &destPos);
+
+	virtual void blitFrom(const XSurface &src, const Common::Point &destPos);
 public:
 	Screen(XeenEngine *vm);
 
 	void update();
+
+	void addDirtyRect(const Common::Rect &r);
 };
 
 } // End of namespace Xeen
diff --git a/engines/xeen/xsurface.cpp b/engines/xeen/xsurface.cpp
new file mode 100644
index 0000000..4ab8cf6
--- /dev/null
+++ b/engines/xeen/xsurface.cpp
@@ -0,0 +1,75 @@
+/* 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 "xeen/xsurface.h"
+
+namespace Xeen {
+
+XSurface::XSurface(): Graphics::Surface() {
+}
+
+XSurface::XSurface(int w, int h) : Graphics::Surface() {
+	create(w, h);
+}
+
+void XSurface::create(uint16 w, uint16 h) {
+	Graphics::Surface::create(w, h, Graphics::PixelFormat::createFormatCLUT8());
+}
+
+void XSurface::transBlitFrom(const XSurface &src) {
+	transBlitFrom(src, Common::Point());
+}
+
+void XSurface::blitFrom(const XSurface &src) {
+	blitFrom(src, Common::Point());
+}
+
+void XSurface::transBlitFrom(const XSurface &src, const Common::Point &destPos) {
+	if (getPixels() == nullptr)
+		create(w, h);
+
+	for (int yp = 0; yp < src.h; ++yp) {
+		const byte *srcP = (const byte *)src.getBasePtr(0, yp);
+		byte *destP = (byte *)getBasePtr(destPos.x, destPos.y + yp);
+
+		for (int xp = 0; xp < this->w; ++xp, ++srcP, ++destP) {
+			if (*srcP != 0)
+				*destP = *srcP;
+		}
+	}
+}
+
+void XSurface::blitFrom(const XSurface &src, const Common::Point &destPos) {
+	if (getPixels() == nullptr)
+		create(w, h);
+
+	for (int yp = 0; yp < src.h; ++yp) {
+		const byte *srcP = (const byte *)src.getBasePtr(0, yp);
+		byte *destP = (byte *)getBasePtr(destPos.x, destPos.y + yp);
+
+		for (int xp = 0; xp < this->w; ++xp, ++srcP, ++destP) {
+			*destP = *srcP;
+		}
+	}
+}
+
+} // End of namespace Xeen
diff --git a/engines/xeen/xsurface.h b/engines/xeen/xsurface.h
new file mode 100644
index 0000000..e547bd9
--- /dev/null
+++ b/engines/xeen/xsurface.h
@@ -0,0 +1,51 @@
+/* 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_XSURFACE_H
+#define XEEN_XSURFACE_H
+
+#include "common/scummsys.h"
+#include "common/system.h"
+#include "common/rect.h"
+#include "graphics/surface.h"
+
+namespace Xeen {
+
+class XSurface: public Graphics::Surface {
+public:
+	virtual void transBlitFrom(const XSurface &src, const Common::Point &destPos);
+
+	virtual void blitFrom(const XSurface &src, const Common::Point &destPos);
+public:
+	XSurface();
+	XSurface(int w, int h);
+
+	void create(uint16 w, uint16 h);
+
+	void transBlitFrom(const XSurface &src);
+
+	void blitFrom(const XSurface &src);
+};
+
+} // End of namespace Xeen
+
+#endif /* XEEN_XSURFACE_H */


Commit: 42afa00392372b68013a871e90857dc151ae7c2f
    https://github.com/scummvm/scummvm/commit/42afa00392372b68013a871e90857dc151ae7c2f
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2014-12-26T10:05:51+11:00

Commit Message:
XEEN: Initial implementation of sprite resource class

Changed paths:
    engines/xeen/resources.cpp
    engines/xeen/resources.h
    engines/xeen/xsurface.cpp
    engines/xeen/xsurface.h



diff --git a/engines/xeen/resources.cpp b/engines/xeen/resources.cpp
index e9c31e3..3a1994d 100644
--- a/engines/xeen/resources.cpp
+++ b/engines/xeen/resources.cpp
@@ -217,7 +217,25 @@ void File::openFile(const Common::String &filename) {
 /*------------------------------------------------------------------------*/
 
 SpriteResource::SpriteResource(const Common::String &filename) {
+	File f(filename);
 
+	// Read in the index
+	int count = f.readUint16LE();
+	Common::Array<uint32> index;
+	index.resize(count);
+	for (int i = 0; i < count; ++i)
+		index[i] = f.readUint32LE();
+	
+	// Process each shape
+	_frames.resize(count);
+	for (int i = 0; i < count; ++i) {
+		uint16 cell1 = index[i] & 0xffff, cell2 = index[i] >> 16;
+		assert(cell1);
+
+		setFrameSize(f, cell1, cell2, _frames[i]);
+		decodeFrame(f, cell1, _frames[i]);
+		decodeFrame(f, cell2, _frames[i]);
+	}
 }
 
 int SpriteResource::size() const {
@@ -228,5 +246,126 @@ const XSurface &SpriteResource::getFrame(int frame) {
 	return _frames[frame];
 }
 
+void SpriteResource::setFrameSize(File &f, uint16 offset1, uint16 offset2, XSurface &s) {
+	int maxWidth = 0, maxHeight = 0;
+
+	// Check each of the two cells for the frame for their sizes
+	for (int i = 0; i < 2; ++i) {
+		uint16 offset = (i == 0) ? offset1 : offset2;
+		if (!offset)
+			break;
+
+		// Get the cell dimensions
+		f.seek(offset);
+		int x = f.readUint16LE();
+		int w = f.readUint16LE();
+		int y = f.readUint16LE();
+		int h = f.readUint16LE();
+
+		// Check for total size of the frame
+		if ((x + w) > maxWidth)
+			maxWidth = x + w;
+		if ((y + h) > maxHeight)
+			maxHeight = x + h;
+	}
+
+	// Create the surface
+	s.create(maxWidth, maxHeight);
+	
+	// Empty the surface
+	s.fillRect(Common::Rect(0, 0, maxWidth, maxHeight), 0);
+}
+
+void SpriteResource::decodeFrame(File &f, uint16 offset, XSurface &s) {
+	// Get cell header
+	f.seek(offset);
+	int xOffset = f.readUint16LE();
+	int width = f.readUint16LE();
+	int yOffset = f.readUint16LE();
+	int height = f.readUint16LE();
+
+	// The pattern steps used in the pattern command
+	const int patternSteps[] = { 0, 1, 1, 1, 2, 2, 3, 3, 0, -1, -1, -1, -2, -2, -3, -3 };
+
+	// Main loop
+	int byteCount, opr1, opr2;
+	int32 pos;
+	for (int yPos = yOffset, byteCount = 0; yPos < height + yOffset; yPos++, byteCount = 0) {
+		// The number of bytes in this scan line
+		int lineLength = f.readByte();
+
+		if (lineLength == 0) {
+			// Skip the specified number of scan lines
+			yPos += f.readByte();
+		} else {
+			// Skip the transparent color at the beginning of the scan line
+			int xPos = f.readByte() + xOffset; ++byteCount;
+			byte *destP = (byte *)s.getBasePtr(xPos, yPos);
+
+			while (byteCount < lineLength) {
+				// The next byte is an opcode that determines what 
+				// operators are to follow and how to interpret them.
+				int opcode = f.readByte(); ++byteCount;
+
+				// Decode the opcode
+				int len = opcode & 0x1F;
+				int cmd = (opcode & 0xE0) >> 5;
+
+				switch (cmd) {
+				case 0:   // The following len + 1 bytes are stored as indexes into the color table.
+				case 1:   // The following len + 33 bytes are stored as indexes into the color table.
+					for (int i = 0; i < opcode + 1; ++i, ++xPos)
+						*destP++ = f.readByte(); ++byteCount;
+					break;
+
+				case 2:   // The following byte is an index into the color table, draw it len + 3 times.
+					opr1 = f.readByte(); ++byteCount;
+					for (int i = 0; i < len + 3; ++i, ++xPos)
+						*destP++ = opr1;
+					break;
+
+				case 3:   // Stream copy command.
+					opr1 = f.readUint16LE(); byteCount += 2;
+					pos = f.pos();
+					f.seek(-opr1, SEEK_CUR);
+
+					for (int i = 0; i < len + 4; ++i, ++xPos)
+						*destP++ = f.readByte();
+
+					f.seek(pos, SEEK_SET);
+					break;
+
+				case 4:   // The following two bytes are indexes into the color table, draw the pair len + 2 times.
+					opr1 = f.readByte(); ++byteCount;
+					opr2 = f.readByte(); ++byteCount;
+					for (int i = 0; i < len + 2; ++i, xPos += 2) {
+						*destP++ = opr1;
+						*destP++ = opr2;
+					}
+					break;
+
+				case 5:   // Skip len + 1 pixels filling them with the transparent color.
+					xPos += len + 1;
+					break;
+
+				case 6:   // Pattern command.
+				case 7:
+					// The pattern command has a different opcode format
+					len = opcode & 0x07;
+					cmd = (opcode >> 2) & 0x0E;
+
+					opr1 = f.readByte(); ++byteCount;
+					for (int i = 0; i < len + 3; ++i, ++xPos) {
+						*destP++ = opr1;
+						opr1 += patternSteps[cmd + (i % 2)];
+					}
+					break;
+				default:
+					break;
+				}
+			}
+		}
+	}
+}
 
 } // End of namespace Xeen
diff --git a/engines/xeen/resources.h b/engines/xeen/resources.h
index 4cf5212..1c55cc8 100644
--- a/engines/xeen/resources.h
+++ b/engines/xeen/resources.h
@@ -56,6 +56,10 @@ public:
 class SpriteResource {
 private:
 	Common::Array<XSurface> _frames;
+
+	void setFrameSize(File &f, uint16 offset1, uint16 offset2, XSurface &s);
+
+	void decodeFrame(File &f, uint16 offset, XSurface &s);
 public:
 	SpriteResource(const Common::String &filename);
 
diff --git a/engines/xeen/xsurface.cpp b/engines/xeen/xsurface.cpp
index 4ab8cf6..b5f08f4 100644
--- a/engines/xeen/xsurface.cpp
+++ b/engines/xeen/xsurface.cpp
@@ -31,6 +31,10 @@ XSurface::XSurface(int w, int h) : Graphics::Surface() {
 	create(w, h);
 }
 
+XSurface::~XSurface() {
+	free();
+}
+
 void XSurface::create(uint16 w, uint16 h) {
 	Graphics::Surface::create(w, h, Graphics::PixelFormat::createFormatCLUT8());
 }
diff --git a/engines/xeen/xsurface.h b/engines/xeen/xsurface.h
index e547bd9..7a189fa 100644
--- a/engines/xeen/xsurface.h
+++ b/engines/xeen/xsurface.h
@@ -38,6 +38,7 @@ public:
 public:
 	XSurface();
 	XSurface(int w, int h);
+	~XSurface();
 
 	void create(uint16 w, uint16 h);
 


Commit: 1249bc03fdbf6d1bc390f9aea45b482cbb258e33
    https://github.com/scummvm/scummvm/commit/1249bc03fdbf6d1bc390f9aea45b482cbb258e33
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2014-12-26T13:10:30+11:00

Commit Message:
XEEN: Implemented horizontal and vertical page merging

Changed paths:
    engines/xeen/darkside/darkside_game.cpp
    engines/xeen/resources.cpp
    engines/xeen/screen.cpp
    engines/xeen/screen.h
    engines/xeen/xsurface.h



diff --git a/engines/xeen/darkside/darkside_game.cpp b/engines/xeen/darkside/darkside_game.cpp
index bc0d156..2e9186e 100644
--- a/engines/xeen/darkside/darkside_game.cpp
+++ b/engines/xeen/darkside/darkside_game.cpp
@@ -21,6 +21,8 @@
  */
 
 #include "xeen/darkside/darkside_game.h"
+#include "xeen/resources.h"
+#include "xeen/screen.h"
 
 namespace Xeen {
 
@@ -33,6 +35,23 @@ void DarkSideEngine::playGame() {
 }
 
 void DarkSideEngine::darkSideIntro() {
+	//sub_28F40
+	_screen->loadPalette("dark.pal");
+	File special("special.bin");
+	SpriteResource nwc[4] = {
+		SpriteResource("nwc1.int"), SpriteResource("nwc2.int"), 
+		SpriteResource("nwc3.int"), SpriteResource("nwc4.int")
+	};
+	File voc[3] = {
+		File("dragon1.voc"), File("dragon2.voc"), File("dragon3.voc")
+	};
+
+	_screen->loadBackground("nwc1.raw");
+	_screen->loadPage(0);
+	_screen->loadBackground("nwc2.raw");
+	_screen->loadPage(1);
+
+	_screen->horizMerge(0);
 }
 
 } // End of namespace Xeen
diff --git a/engines/xeen/resources.cpp b/engines/xeen/resources.cpp
index 3a1994d..b005d74 100644
--- a/engines/xeen/resources.cpp
+++ b/engines/xeen/resources.cpp
@@ -280,7 +280,7 @@ void SpriteResource::decodeFrame(File &f, uint16 offset, XSurface &s) {
 	// Get cell header
 	f.seek(offset);
 	int xOffset = f.readUint16LE();
-	int width = f.readUint16LE();
+	f.skip(2);
 	int yOffset = f.readUint16LE();
 	int height = f.readUint16LE();
 
@@ -288,7 +288,7 @@ void SpriteResource::decodeFrame(File &f, uint16 offset, XSurface &s) {
 	const int patternSteps[] = { 0, 1, 1, 1, 2, 2, 3, 3, 0, -1, -1, -1, -2, -2, -3, -3 };
 
 	// Main loop
-	int byteCount, opr1, opr2;
+	int opr1, opr2;
 	int32 pos;
 	for (int yPos = yOffset, byteCount = 0; yPos < height + yOffset; yPos++, byteCount = 0) {
 		// The number of bytes in this scan line
@@ -298,7 +298,7 @@ void SpriteResource::decodeFrame(File &f, uint16 offset, XSurface &s) {
 			// Skip the specified number of scan lines
 			yPos += f.readByte();
 		} else {
-			// Skip the transparent color at the beginning of the scan line
+			// Skip the transparent pixels at the beginning of the scan line
 			int xPos = f.readByte() + xOffset; ++byteCount;
 			byte *destP = (byte *)s.getBasePtr(xPos, yPos);
 
diff --git a/engines/xeen/screen.cpp b/engines/xeen/screen.cpp
index 038222b..4783890 100644
--- a/engines/xeen/screen.cpp
+++ b/engines/xeen/screen.cpp
@@ -21,6 +21,7 @@
  */
 
 #include "xeen/screen.h"
+#include "xeen/resources.h"
 
 namespace Xeen {
 
@@ -28,6 +29,7 @@ namespace Xeen {
  * Constructor
  */
 Screen::Screen(XeenEngine *vm) : _vm(vm) {
+
 }
 
 void Screen::update() {
@@ -100,4 +102,85 @@ bool Screen::unionRectangle(Common::Rect &destRect, const Common::Rect &src1, co
 	return !destRect.isEmpty();
 }
 
+/**
+ * Load a palette resource into the temporary palette
+ */
+void Screen::loadPalette(const Common::String &name) {
+	File f(name);
+	f.read(_tempPaltte, PALETTE_SIZE);
+}
+
+/**
+ * Load a background resource into memory
+ */
+void Screen::loadBackground(const Common::String &name) {
+	File f(name);
+
+	_background.create(SCREEN_WIDTH, SCREEN_HEIGHT);
+	assert(f.size() == (SCREEN_WIDTH * SCREEN_HEIGHT));
+	f.read((byte *)_background.getPixels(), SCREEN_WIDTH * SCREEN_HEIGHT);
+}
+
+/**
+ * Copy a loaded background into a display page
+ */
+void Screen::loadPage(int pageNum) {
+	assert(pageNum == 0 || pageNum == 1);
+	if (_pages[0].empty()) {
+		_pages[0].create(SCREEN_WIDTH, SCREEN_HEIGHT);
+		_pages[1].create(SCREEN_WIDTH, SCREEN_HEIGHT);
+	}
+
+	_pages[pageNum].blitFrom(_background);
+}
+
+/**
+ * Merge the two pages along a horizontal split point
+ */
+void Screen::horizMerge(int xp) {
+	if (_pages[0].empty())
+		return;
+
+	for (int y = 0; y < SCREEN_HEIGHT; ++y) {
+		byte *destP = (byte *)_background.getBasePtr(0, y);
+		const byte *srcP = (const byte *)_pages[0].getBasePtr(0, y);
+		Common::copy(srcP, srcP + SCREEN_WIDTH - xp, destP);
+
+		if (xp != 0) {
+			srcP = (const byte *)_pages[1].getBasePtr(xp, y);
+			Common::copy(srcP, srcP + SCREEN_WIDTH - xp, destP + xp);
+		}
+	}
+}
+
+/**
+ * Merge the two pages along a vertical split point
+ */
+void Screen::vertMerge(int yp) {
+	if (_pages[0].empty())
+		return;
+
+	for (int y = 0; y < SCREEN_HEIGHT - yp; ++y) {
+		const byte *srcP = (const byte *)_pages[0].getBasePtr(0, y);
+		byte *destP = (byte *)_background.getBasePtr(0, y);
+		Common::copy(srcP, srcP + SCREEN_WIDTH, destP);
+	}
+
+	for (int y = yp; y < SCREEN_HEIGHT; ++y) {
+		const byte *srcP = (const byte *)_pages[1].getBasePtr(0, y);
+		byte *destP = (byte *)_background.getBasePtr(0, y);
+		Common::copy(srcP, srcP + SCREEN_WIDTH, destP);
+	}
+}
+
+void Screen::draw(void *data) {
+	// TODO: Figure out data structure that can be passed to method
+	assert(!data);
+	drawBackground();
+}
+
+void Screen::drawBackground() {
+
+}
+
 } // End of namespace Xeen
diff --git a/engines/xeen/screen.h b/engines/xeen/screen.h
index 491b702..645c4da 100644
--- a/engines/xeen/screen.h
+++ b/engines/xeen/screen.h
@@ -31,16 +31,27 @@
 
 namespace Xeen {
 
+#define SCREEN_WIDTH 320
+#define SCREEN_HEIGHT 200
+#define PALETTE_COUNT 256
+#define PALETTE_SIZE (256 * 3)
+
 class XeenEngine;
 
 class Screen: public XSurface {
 private:
 	XeenEngine *_vm;
 	Common::List<Common::Rect> _dirtyRects;
+	byte _mainPalette[PALETTE_SIZE];
+	byte _tempPaltte[PALETTE_SIZE];
+	XSurface _background;
+	XSurface _pages[2];
 
 	void mergeDirtyRects();
 
 	bool unionRectangle(Common::Rect &destRect, const Common::Rect &src1, const Common::Rect &src2);
+
+	void drawBackground();
 public:
 	virtual void transBlitFrom(const XSurface &src, const Common::Point &destPos);
 
@@ -51,6 +62,18 @@ public:
 	void update();
 
 	void addDirtyRect(const Common::Rect &r);
+
+	void loadPalette(const Common::String &name);
+
+	void loadBackground(const Common::String &name);
+
+	void loadPage(int pageNum);
+
+	void horizMerge(int xp);
+
+	void vertMerge(int yp);
+
+	void draw(void *data);
 };
 
 } // End of namespace Xeen
diff --git a/engines/xeen/xsurface.h b/engines/xeen/xsurface.h
index 7a189fa..c2d6e78 100644
--- a/engines/xeen/xsurface.h
+++ b/engines/xeen/xsurface.h
@@ -45,6 +45,8 @@ public:
 	void transBlitFrom(const XSurface &src);
 
 	void blitFrom(const XSurface &src);
+
+	bool empty() const { return getPixels() == nullptr; }
 };
 
 } // End of namespace Xeen


Commit: 4f423c74b701b4dceff680259d174acb6a450b76
    https://github.com/scummvm/scummvm/commit/4f423c74b701b4dceff680259d174acb6a450b76
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2014-12-26T14:37:20+11:00

Commit Message:
XEEN: Implement beginnings of Dark Side intro and supporting methods

Changed paths:
  A engines/xeen/sound.cpp
  A engines/xeen/sound.h
    engines/xeen/darkside/darkside_game.cpp
    engines/xeen/events.cpp
    engines/xeen/events.h
    engines/xeen/module.mk
    engines/xeen/screen.cpp
    engines/xeen/screen.h
    engines/xeen/xeen.cpp
    engines/xeen/xeen.h



diff --git a/engines/xeen/darkside/darkside_game.cpp b/engines/xeen/darkside/darkside_game.cpp
index 2e9186e..728e155 100644
--- a/engines/xeen/darkside/darkside_game.cpp
+++ b/engines/xeen/darkside/darkside_game.cpp
@@ -46,12 +46,53 @@ void DarkSideEngine::darkSideIntro() {
 		File("dragon1.voc"), File("dragon2.voc"), File("dragon3.voc")
 	};
 
+	// Load backgrounds
 	_screen->loadBackground("nwc1.raw");
 	_screen->loadPage(0);
 	_screen->loadBackground("nwc2.raw");
 	_screen->loadPage(1);
 
+	// Draw the screen and fade it in
 	_screen->horizMerge(0);
+	_screen->draw();
+	_screen->fade(4);
+
+	bool breakFlag = false;
+	int nwcIndex = 0, nwcFrame = 0;
+	for (int idx = 0; idx < 55 && !shouldQuit(); ++idx) {
+		_events->updateGameCounter();
+		_screen->vertMerge(0);
+		const XSurface &frame = nwc[nwcIndex].getFrame(nwcFrame);
+		_screen->transBlitFrom(frame, Common::Point(0, 0));
+		_screen->draw();
+
+		switch (idx) {
+		case 17:
+			_sound->proc2(voc[0]);
+			break;
+		case 34:
+		case 44:
+			++nwcIndex;
+			++nwcFrame;
+			break;
+		case 35:
+			_sound->proc2(voc[1]);
+			break;
+		default:
+			++nwcFrame;
+		}
+
+		while (!shouldQuit() && _events->timeElapsed() < 2) {
+			_events->pollEventsAndWait();
+			Common::KeyState keyState;
+			if (_events->getKey(keyState)) {
+				if (keyState.keycode == Common::KEYCODE_ESCAPE)
+					breakFlag = true;
+			}
+		}
+	}
+
+
 }
 
 } // End of namespace Xeen
diff --git a/engines/xeen/events.cpp b/engines/xeen/events.cpp
index e75744e..c4adabc 100644
--- a/engines/xeen/events.cpp
+++ b/engines/xeen/events.cpp
@@ -39,6 +39,8 @@ EventsManager::EventsManager(XeenEngine *vm) : _vm(vm) {
 	_priorFrameCounterTime = 0;
 	_gameCounter = 0;
 	_priorGameCounterTime = 0;
+	_keyCode = Common::KEYCODE_INVALID;
+	_leftButton = _rightButton = false;
 }
 
 /**
@@ -81,12 +83,37 @@ void EventsManager::pollEvents() {
 		case Common::EVENT_QUIT:
 		case Common::EVENT_RTL:
 			return;
+		case Common::EVENT_KEYDOWN:
+			_keyCode = event.kbd.keycode;
+			break;
 		default:
  			break;
 		}
 	}
 }
 
+void EventsManager::pollEventsAndWait() {
+	pollEvents();
+	g_system->delayMillis(10);
+}
+
+void EventsManager::clearEvents() {
+	_keyCode = Common::KEYCODE_INVALID;
+	_leftButton = _rightButton = false;
+
+}
+
+
+bool EventsManager::getKey(Common::KeyState &key) {
+	if (_keyCode == Common::KEYCODE_INVALID) {
+		return false;
+	} else {
+		key = _keyCode;
+		_keyCode = Common::KEYCODE_INVALID;
+		return true;
+	}
+}
+
 /**
  * Updates the game counter to match the current frame counter
  */
diff --git a/engines/xeen/events.h b/engines/xeen/events.h
index 637d710..4d775ac 100644
--- a/engines/xeen/events.h
+++ b/engines/xeen/events.h
@@ -39,6 +39,8 @@ private:
 	uint32 _priorFrameCounterTime;
 	uint32 _gameCounter;
 	uint32 _priorGameCounterTime;
+	Common::KeyCode _keyCode;
+	bool _leftButton, _rightButton;
 
 	void nextFrame();
 public:
@@ -56,6 +58,12 @@ public:
 
 	void pollEvents();
 
+	void pollEventsAndWait();
+
+	void clearEvents();
+
+	bool getKey(Common::KeyState &key);
+
 	void updateGameCounter();
 
 	uint32 timeElapsed();
diff --git a/engines/xeen/module.mk b/engines/xeen/module.mk
index c036376..aafe9b4 100644
--- a/engines/xeen/module.mk
+++ b/engines/xeen/module.mk
@@ -9,6 +9,7 @@ MODULE_OBJS := \
 	events.o \
 	resources.o \
 	screen.o \
+	sound.o \
 	xeen.o \
 	xsurface.o
 
diff --git a/engines/xeen/screen.cpp b/engines/xeen/screen.cpp
index 4783890..65f9600 100644
--- a/engines/xeen/screen.cpp
+++ b/engines/xeen/screen.cpp
@@ -20,8 +20,11 @@
  *
  */
 
+#include "common/system.h"
+#include "graphics/palette.h"
 #include "xeen/screen.h"
 #include "xeen/resources.h"
+#include "xeen/xeen.h"
 
 namespace Xeen {
 
@@ -29,7 +32,7 @@ namespace Xeen {
  * Constructor
  */
 Screen::Screen(XeenEngine *vm) : _vm(vm) {
-
+	_fadeMode = false;
 }
 
 void Screen::update() {
@@ -116,9 +119,8 @@ void Screen::loadPalette(const Common::String &name) {
 void Screen::loadBackground(const Common::String &name) {
 	File f(name);
 
-	_background.create(SCREEN_WIDTH, SCREEN_HEIGHT);
 	assert(f.size() == (SCREEN_WIDTH * SCREEN_HEIGHT));
-	f.read((byte *)_background.getPixels(), SCREEN_WIDTH * SCREEN_HEIGHT);
+	f.read((byte *)getPixels(), SCREEN_WIDTH * SCREEN_HEIGHT);
 }
 
 /**
@@ -131,7 +133,7 @@ void Screen::loadPage(int pageNum) {
 		_pages[1].create(SCREEN_WIDTH, SCREEN_HEIGHT);
 	}
 
-	_pages[pageNum].blitFrom(_background);
+	_pages[pageNum].blitFrom(*this);
 }
 
 /**
@@ -142,7 +144,7 @@ void Screen::horizMerge(int xp) {
 		return;
 
 	for (int y = 0; y < SCREEN_HEIGHT; ++y) {
-		byte *destP = (byte *)_background.getBasePtr(0, y);
+		byte *destP = (byte *)getBasePtr(0, y);
 		const byte *srcP = (const byte *)_pages[0].getBasePtr(0, y);
 		Common::copy(srcP, srcP + SCREEN_WIDTH - xp, destP);
 
@@ -162,13 +164,13 @@ void Screen::vertMerge(int yp) {
 
 	for (int y = 0; y < SCREEN_HEIGHT - yp; ++y) {
 		const byte *srcP = (const byte *)_pages[0].getBasePtr(0, y);
-		byte *destP = (byte *)_background.getBasePtr(0, y);
+		byte *destP = (byte *)getBasePtr(0, y);
 		Common::copy(srcP, srcP + SCREEN_WIDTH, destP);
 	}
 
 	for (int y = yp; y < SCREEN_HEIGHT; ++y) {
 		const byte *srcP = (const byte *)_pages[1].getBasePtr(0, y);
-		byte *destP = (byte *)_background.getBasePtr(0, y);
+		byte *destP = (byte *)getBasePtr(0, y);
 		Common::copy(srcP, srcP + SCREEN_WIDTH, destP);
 	}
 }
@@ -176,11 +178,54 @@ void Screen::vertMerge(int yp) {
 void Screen::draw(void *data) {
 	// TODO: Figure out data structure that can be passed to method
 	assert(!data);
-	drawBackground();
+	drawScreen();
+}
+
+/**
+ * Mark the entire screen for drawing
+ */
+void Screen::drawScreen() {
+	addDirtyRect(Common::Rect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT));
+}
+
+void Screen::fade(int step) {
+	_fadeMode = true;
+	fadeInner(step);
+}
+
+void Screen::fade2(int step) {
+	_fadeMode = false;
+	fadeInner(step);
 }
 
-void Screen::drawBackground() {
+void Screen::fadeInner(int step) {
+	for (int idx = 128; idx != 0 && !_vm->shouldQuit(); idx -= step) {
+		int val = idx;
+		bool flag = !_fadeMode;
+		if (!flag) {
+			val = -(val - 128);
+			flag = step != 0x81;
+		}
+
+		if (!flag) {
+			step = 0x80;
+		} else {
+			// Create a scaled palette from the temporary one
+			for (int i = 0; i < PALETTE_SIZE; ++i) {
+				_mainPalette[i] = (_tempPaltte[i] * val * 2) >> 8;
+			}
+
+			updatePalette();
+		}
+	}
+}
+
+void Screen::updatePalette() {
+	updatePalette(_mainPalette, 0, 16);
+}
 
+void Screen::updatePalette(const byte *pal, int start, int count16) {
+	g_system->getPaletteManager()->setPalette(pal, start, count16 * 16);
 }
 
 } // End of namespace Xeen
diff --git a/engines/xeen/screen.h b/engines/xeen/screen.h
index 645c4da..3359af8 100644
--- a/engines/xeen/screen.h
+++ b/engines/xeen/screen.h
@@ -44,14 +44,20 @@ private:
 	Common::List<Common::Rect> _dirtyRects;
 	byte _mainPalette[PALETTE_SIZE];
 	byte _tempPaltte[PALETTE_SIZE];
-	XSurface _background;
 	XSurface _pages[2];
+	bool _fadeMode;
 
 	void mergeDirtyRects();
 
 	bool unionRectangle(Common::Rect &destRect, const Common::Rect &src1, const Common::Rect &src2);
 
-	void drawBackground();
+	void drawScreen();
+
+	void fadeInner(int step);
+
+	void updatePalette();
+
+	void updatePalette(const byte *pal, int start, int count16);
 public:
 	virtual void transBlitFrom(const XSurface &src, const Common::Point &destPos);
 
@@ -73,7 +79,11 @@ public:
 
 	void vertMerge(int yp);
 
-	void draw(void *data);
+	void draw(void *data = nullptr);
+
+	void fade(int step);
+
+	void fade2(int step);
 };
 
 } // End of namespace Xeen
diff --git a/engines/xeen/sound.cpp b/engines/xeen/sound.cpp
new file mode 100644
index 0000000..2863a3d
--- /dev/null
+++ b/engines/xeen/sound.cpp
@@ -0,0 +1,34 @@
+/* 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 "xeen/sound.h"
+
+namespace Xeen {
+
+SoundManager::SoundManager(XeenEngine *vm): _vm(vm) {
+}
+
+void SoundManager::proc2(File &f) {
+
+}
+
+} // End of namespace Xeen
diff --git a/engines/xeen/sound.h b/engines/xeen/sound.h
new file mode 100644
index 0000000..2e163e7
--- /dev/null
+++ b/engines/xeen/sound.h
@@ -0,0 +1,43 @@
+/* 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_SOUND_H
+#define XEEN_SOUND_H
+
+#include "common/scummsys.h"
+#include "common/system.h"
+#include "xeen/resources.h"
+
+namespace Xeen {
+
+class SoundManager {
+private:
+	XeenEngine *_vm;
+public:
+	SoundManager(XeenEngine *vm);
+
+	void proc2(File &f);
+};
+
+} // End of namespace Xeen
+
+#endif /* XEEN_SOUND_H */
diff --git a/engines/xeen/xeen.cpp b/engines/xeen/xeen.cpp
index cf60aa4..f1330f5 100644
--- a/engines/xeen/xeen.cpp
+++ b/engines/xeen/xeen.cpp
@@ -37,12 +37,14 @@ XeenEngine::XeenEngine(OSystem *syst, const XeenGameDescription *gameDesc)
 	_debugger = nullptr;
 	_events = nullptr;
 	_screen = nullptr;
+	_sound = nullptr;
 }
 
 XeenEngine::~XeenEngine() {
 	delete _debugger;
 	delete _events;
 	delete _screen;
+	delete _sound;
 }
 
 void XeenEngine::initialize() {
@@ -56,6 +58,7 @@ void XeenEngine::initialize() {
 	_debugger = new Debugger(this);
 	_events = new EventsManager(this);
 	_screen = new Screen(this);
+	_sound = new SoundManager(this);
 	Resources::init(this);
 
 	// Set graphics mode
diff --git a/engines/xeen/xeen.h b/engines/xeen/xeen.h
index dba340e..df53b78 100644
--- a/engines/xeen/xeen.h
+++ b/engines/xeen/xeen.h
@@ -35,6 +35,7 @@
 #include "xeen/debugger.h"
 #include "xeen/events.h"
 #include "xeen/screen.h"
+#include "xeen/sound.h"
 
 /**
  * This is the namespace of the Xeen engine.
@@ -108,6 +109,7 @@ public:
 	Debugger *_debugger;
 	EventsManager *_events;
 	Screen *_screen;
+	SoundManager *_sound;
 public:
 	XeenEngine(OSystem *syst, const XeenGameDescription *gameDesc);
 	virtual ~XeenEngine();


Commit: d213db3dc1b24e281e03dc593f21925db8fcd10e
    https://github.com/scummvm/scummvm/commit/d213db3dc1b24e281e03dc593f21925db8fcd10e
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2014-12-26T18:31:05+11:00

Commit Message:
XEEN: Converted SpriteResource to decoding sprite frames on the fly

Changed paths:
    engines/xeen/darkside/darkside_game.cpp
    engines/xeen/resources.cpp
    engines/xeen/resources.h
    engines/xeen/screen.cpp
    engines/xeen/screen.h
    engines/xeen/xsurface.cpp
    engines/xeen/xsurface.h



diff --git a/engines/xeen/darkside/darkside_game.cpp b/engines/xeen/darkside/darkside_game.cpp
index 728e155..a597ab2 100644
--- a/engines/xeen/darkside/darkside_game.cpp
+++ b/engines/xeen/darkside/darkside_game.cpp
@@ -59,11 +59,10 @@ void DarkSideEngine::darkSideIntro() {
 
 	bool breakFlag = false;
 	int nwcIndex = 0, nwcFrame = 0;
-	for (int idx = 0; idx < 55 && !shouldQuit(); ++idx) {
+	for (int idx = 0; idx < 55 && !shouldQuit() && !breakFlag; ++idx) {
 		_events->updateGameCounter();
 		_screen->vertMerge(0);
-		const XSurface &frame = nwc[nwcIndex].getFrame(nwcFrame);
-		_screen->transBlitFrom(frame, Common::Point(0, 0));
+		nwc[nwcIndex].draw(*_screen, nwcFrame, Common::Point(0, 0));
 		_screen->draw();
 
 		switch (idx) {
@@ -91,8 +90,6 @@ void DarkSideEngine::darkSideIntro() {
 			}
 		}
 	}
-
-
 }
 
 } // End of namespace Xeen
diff --git a/engines/xeen/resources.cpp b/engines/xeen/resources.cpp
index b005d74..4cc586f 100644
--- a/engines/xeen/resources.cpp
+++ b/engines/xeen/resources.cpp
@@ -217,70 +217,45 @@ void File::openFile(const Common::String &filename) {
 /*------------------------------------------------------------------------*/
 
 SpriteResource::SpriteResource(const Common::String &filename) {
+	// Open the resource
 	File f(filename);
 
 	// Read in the index
 	int count = f.readUint16LE();
-	Common::Array<uint32> index;
-	index.resize(count);
-	for (int i = 0; i < count; ++i)
-		index[i] = f.readUint32LE();
-	
-	// Process each shape
-	_frames.resize(count);
-	for (int i = 0; i < count; ++i) {
-		uint16 cell1 = index[i] & 0xffff, cell2 = index[i] >> 16;
-		assert(cell1);
+	_index.resize(count);
 
-		setFrameSize(f, cell1, cell2, _frames[i]);
-		decodeFrame(f, cell1, _frames[i]);
-		decodeFrame(f, cell2, _frames[i]);
+	for (int i = 0; i < count; ++i) {
+		_index[i]._offset1 = f.readUint16LE();
+		_index[i]._offset2 = f.readUint16LE();
 	}
-}
 
-int SpriteResource::size() const {
-	return _frames.size();
+	// Read in a copy of the file
+	_filesize = f.size();
+	_data = new byte[_filesize];
+	f.seek(0);
+	f.read(_data, _filesize);
 }
 
-const XSurface &SpriteResource::getFrame(int frame) {
-	return _frames[frame];
+SpriteResource::~SpriteResource() {
+	delete[] _data;
 }
 
-void SpriteResource::setFrameSize(File &f, uint16 offset1, uint16 offset2, XSurface &s) {
-	int maxWidth = 0, maxHeight = 0;
-
-	// Check each of the two cells for the frame for their sizes
-	for (int i = 0; i < 2; ++i) {
-		uint16 offset = (i == 0) ? offset1 : offset2;
-		if (!offset)
-			break;
-
-		// Get the cell dimensions
-		f.seek(offset);
-		int x = f.readUint16LE();
-		int w = f.readUint16LE();
-		int y = f.readUint16LE();
-		int h = f.readUint16LE();
-
-		// Check for total size of the frame
-		if ((x + w) > maxWidth)
-			maxWidth = x + w;
-		if ((y + h) > maxHeight)
-			maxHeight = x + h;
-	}
+int SpriteResource::size() const {
+	return _index.size();
+}
 
-	// Create the surface
-	s.create(maxWidth, maxHeight);
-	
-	// Empty the surface
-	s.fillRect(Common::Rect(0, 0, maxWidth, maxHeight), 0);
+void SpriteResource::draw(XSurface &dest, int frame, const Common::Point &destPos) const {
+	drawOffset(dest, _index[frame]._offset1, destPos);
+	if (_index[frame]._offset2)
+		drawOffset(dest, _index[frame]._offset2, destPos);
 }
 
-void SpriteResource::decodeFrame(File &f, uint16 offset, XSurface &s) {
+void SpriteResource::drawOffset(XSurface &dest, uint16 offset, const Common::Point &destPos) const {
 	// Get cell header
+	Common::MemoryReadStream f(_data, _filesize);
 	f.seek(offset);
 	int xOffset = f.readUint16LE();
-	f.skip(2);
+	int width = f.readUint16LE();
 	int yOffset = f.readUint16LE();
 	int height = f.readUint16LE();
 
@@ -300,7 +275,7 @@ void SpriteResource::decodeFrame(File &f, uint16 offset, XSurface &s) {
 		} else {
 			// Skip the transparent pixels at the beginning of the scan line
 			int xPos = f.readByte() + xOffset; ++byteCount;
-			byte *destP = (byte *)s.getBasePtr(xPos, yPos);
+			byte *destP = (byte *)dest.getBasePtr(destPos.x + xPos, destPos.y + yPos);
 
 			while (byteCount < lineLength) {
 				// The next byte is an opcode that determines what 
@@ -314,8 +289,9 @@ void SpriteResource::decodeFrame(File &f, uint16 offset, XSurface &s) {
 				switch (cmd) {
 				case 0:   // The following len + 1 bytes are stored as indexes into the color table.
 				case 1:   // The following len + 33 bytes are stored as indexes into the color table.
-					for (int i = 0; i < opcode + 1; ++i, ++xPos)
+					for (int i = 0; i < opcode + 1; ++i, ++xPos) {
 						*destP++ = f.readByte(); ++byteCount;
+					}
 					break;
 
 				case 2:   // The following byte is an index into the color table, draw it len + 3 times.
@@ -364,8 +340,13 @@ void SpriteResource::decodeFrame(File &f, uint16 offset, XSurface &s) {
 					break;
 				}
 			}
+
+			assert(byteCount == lineLength);
 		}
 	}
+
+	dest.addDirtyRect(Common::Rect(destPos.x, destPos.y,
+		destPos.x + xOffset + width, destPos.y + yOffset + height));
 }
 
 } // End of namespace Xeen
diff --git a/engines/xeen/resources.h b/engines/xeen/resources.h
index 1c55cc8..fcb1842 100644
--- a/engines/xeen/resources.h
+++ b/engines/xeen/resources.h
@@ -55,17 +55,23 @@ public:
 
 class SpriteResource {
 private:
-	Common::Array<XSurface> _frames;
+	struct IndexEntry {
+		uint16 _offset1, _offset2;
+	};
+	Common::Array<IndexEntry> _index;
 
-	void setFrameSize(File &f, uint16 offset1, uint16 offset2, XSurface &s);
+	int32 _filesize;
+	byte *_data;
 
-	void decodeFrame(File &f, uint16 offset, XSurface &s);
+	void drawOffset(XSurface &dest, uint16 offset, const Common::Point &destPos) const;
 public:
 	SpriteResource(const Common::String &filename);
 
+	~SpriteResource();
+
 	int size() const;
 
-	const XSurface &getFrame(int frame);
+	void draw(XSurface &dest, int frame, const Common::Point &destPos) const;
 };
 
 } // End of namespace Xeen
diff --git a/engines/xeen/screen.cpp b/engines/xeen/screen.cpp
index 65f9600..0c7df8b 100644
--- a/engines/xeen/screen.cpp
+++ b/engines/xeen/screen.cpp
@@ -33,6 +33,7 @@ namespace Xeen {
  */
 Screen::Screen(XeenEngine *vm) : _vm(vm) {
 	_fadeMode = false;
+	create(SCREEN_WIDTH, SCREEN_HEIGHT);
 }
 
 void Screen::update() {
@@ -57,16 +58,6 @@ void Screen::addDirtyRect(const Common::Rect &r) {
 	_dirtyRects.push_back(r);
 }
 
-void Screen::transBlitFrom(const XSurface &src, const Common::Point &destPos) {
-	XSurface::transBlitFrom(src, destPos);
-	addDirtyRect(Common::Rect(destPos.x, destPos.y, destPos.x + src.w, destPos.y + src.h));
-}
-
-void Screen::blitFrom(const XSurface &src, const Common::Point &destPos) {
-	XSurface::blitFrom(src, destPos);
-	addDirtyRect(Common::Rect(destPos.x, destPos.y, destPos.x + src.w, destPos.y + src.h));
-}
-
 void Screen::mergeDirtyRects() {
 	Common::List<Common::Rect>::iterator rOuter, rInner;
 
@@ -110,7 +101,8 @@ bool Screen::unionRectangle(Common::Rect &destRect, const Common::Rect &src1, co
  */
 void Screen::loadPalette(const Common::String &name) {
 	File f(name);
-	f.read(_tempPaltte, PALETTE_SIZE);
+	for (int i = 0; i < PALETTE_SIZE; ++i)
+		_tempPaltte[i] = f.readByte() << 2;
 }
 
 /**
@@ -133,7 +125,7 @@ void Screen::loadPage(int pageNum) {
 		_pages[1].create(SCREEN_WIDTH, SCREEN_HEIGHT);
 	}
 
-	_pages[pageNum].blitFrom(*this);
+	blitTo(_pages[pageNum]);
 }
 
 /**
@@ -217,6 +209,8 @@ void Screen::fadeInner(int step) {
 
 			updatePalette();
 		}
+
+		_vm->_events->pollEventsAndWait();
 	}
 }
 
diff --git a/engines/xeen/screen.h b/engines/xeen/screen.h
index 3359af8..02fe746 100644
--- a/engines/xeen/screen.h
+++ b/engines/xeen/screen.h
@@ -59,16 +59,12 @@ private:
 
 	void updatePalette(const byte *pal, int start, int count16);
 public:
-	virtual void transBlitFrom(const XSurface &src, const Common::Point &destPos);
-
-	virtual void blitFrom(const XSurface &src, const Common::Point &destPos);
+	virtual void addDirtyRect(const Common::Rect &r);
 public:
 	Screen(XeenEngine *vm);
 
 	void update();
 
-	void addDirtyRect(const Common::Rect &r);
-
 	void loadPalette(const Common::String &name);
 
 	void loadBackground(const Common::String &name);
diff --git a/engines/xeen/xsurface.cpp b/engines/xeen/xsurface.cpp
index b5f08f4..f63ad14 100644
--- a/engines/xeen/xsurface.cpp
+++ b/engines/xeen/xsurface.cpp
@@ -20,6 +20,7 @@
  *
  */
 
+#include "common/algorithm.h"
 #include "xeen/xsurface.h"
 
 namespace Xeen {
@@ -39,41 +40,43 @@ void XSurface::create(uint16 w, uint16 h) {
 	Graphics::Surface::create(w, h, Graphics::PixelFormat::createFormatCLUT8());
 }
 
-void XSurface::transBlitFrom(const XSurface &src) {
-	transBlitFrom(src, Common::Point());
+void XSurface::transBlitTo(XSurface &dest) const {
+	transBlitTo(dest, Common::Point());
 }
 
-void XSurface::blitFrom(const XSurface &src) {
-	blitFrom(src, Common::Point());
+void XSurface::blitTo(XSurface &dest) const {
+	blitTo(dest, Common::Point());
 }
 
-void XSurface::transBlitFrom(const XSurface &src, const Common::Point &destPos) {
-	if (getPixels() == nullptr)
-		create(w, h);
+void XSurface::transBlitTo(XSurface &dest, const Common::Point &destPos) const {
+	if (dest.getPixels() == nullptr)
+		dest.create(w, h);
 
-	for (int yp = 0; yp < src.h; ++yp) {
-		const byte *srcP = (const byte *)src.getBasePtr(0, yp);
-		byte *destP = (byte *)getBasePtr(destPos.x, destPos.y + yp);
+	for (int yp = 0; yp < h; ++yp) {
+		const byte *srcP = (const byte *)getBasePtr(0, yp);
+		byte *destP = (byte *)dest.getBasePtr(destPos.x, destPos.y + yp);
 
-		for (int xp = 0; xp < this->w; ++xp, ++srcP, ++destP) {
+		for (int xp = 0; xp < w; ++xp, ++srcP, ++destP) {
 			if (*srcP != 0)
 				*destP = *srcP;
 		}
 	}
+
+	dest.addDirtyRect(Common::Rect(destPos.x, destPos.y, destPos.x + w, destPos.y));
 }
 
-void XSurface::blitFrom(const XSurface &src, const Common::Point &destPos) {
-	if (getPixels() == nullptr)
-		create(w, h);
+void XSurface::blitTo(XSurface &dest, const Common::Point &destPos) const {
+	if (dest.getPixels() == nullptr)
+		dest.create(w, h);
 
-	for (int yp = 0; yp < src.h; ++yp) {
-		const byte *srcP = (const byte *)src.getBasePtr(0, yp);
-		byte *destP = (byte *)getBasePtr(destPos.x, destPos.y + yp);
+	for (int yp = 0; yp < h; ++yp) {
+		const byte *srcP = (const byte *)getBasePtr(0, yp);
+		byte *destP = (byte *)dest.getBasePtr(destPos.x, destPos.y + yp);
 
-		for (int xp = 0; xp < this->w; ++xp, ++srcP, ++destP) {
-			*destP = *srcP;
-		}
+		Common::copy(srcP, srcP + w, destP);
 	}
+
+	dest.addDirtyRect(Common::Rect(destPos.x, destPos.y, destPos.x + w, destPos.y));
 }
 
 } // End of namespace Xeen
diff --git a/engines/xeen/xsurface.h b/engines/xeen/xsurface.h
index c2d6e78..92f1236 100644
--- a/engines/xeen/xsurface.h
+++ b/engines/xeen/xsurface.h
@@ -32,9 +32,7 @@ namespace Xeen {
 
 class XSurface: public Graphics::Surface {
 public:
-	virtual void transBlitFrom(const XSurface &src, const Common::Point &destPos);
-
-	virtual void blitFrom(const XSurface &src, const Common::Point &destPos);
+	virtual void addDirtyRect(const Common::Rect &r) {}
 public:
 	XSurface();
 	XSurface(int w, int h);
@@ -42,9 +40,13 @@ public:
 
 	void create(uint16 w, uint16 h);
 
-	void transBlitFrom(const XSurface &src);
+	void transBlitTo(XSurface &dest) const;
+
+	void transBlitTo(XSurface &dest, const Common::Point &destPos) const;
+
+	void blitTo(XSurface &dest, const Common::Point &destPos) const;
 
-	void blitFrom(const XSurface &src);
+	void blitTo(XSurface &dest) const;
 
 	bool empty() const { return getPixels() == nullptr; }
 };


Commit: 1a6dd88713ff6a6994f9e4d69abf8e3c66538bb2
    https://github.com/scummvm/scummvm/commit/1a6dd88713ff6a6994f9e4d69abf8e3c66538bb2
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2014-12-26T18:50:14+11:00

Commit Message:
XEEN: Fix error in vertMerge

Changed paths:
    engines/xeen/darkside/darkside_game.cpp
    engines/xeen/resources.cpp
    engines/xeen/screen.cpp



diff --git a/engines/xeen/darkside/darkside_game.cpp b/engines/xeen/darkside/darkside_game.cpp
index a597ab2..17a998e 100644
--- a/engines/xeen/darkside/darkside_game.cpp
+++ b/engines/xeen/darkside/darkside_game.cpp
@@ -60,6 +60,7 @@ void DarkSideEngine::darkSideIntro() {
 	bool breakFlag = false;
 	int nwcIndex = 0, nwcFrame = 0;
 	for (int idx = 0; idx < 55 && !shouldQuit() && !breakFlag; ++idx) {
+		// Render the next frame
 		_events->updateGameCounter();
 		_screen->vertMerge(0);
 		nwc[nwcIndex].draw(*_screen, nwcFrame, Common::Point(0, 0));
@@ -72,7 +73,7 @@ void DarkSideEngine::darkSideIntro() {
 		case 34:
 		case 44:
 			++nwcIndex;
-			++nwcFrame;
+			nwcFrame = 0;
 			break;
 		case 35:
 			_sound->proc2(voc[1]);
diff --git a/engines/xeen/resources.cpp b/engines/xeen/resources.cpp
index 4cc586f..736f014 100644
--- a/engines/xeen/resources.cpp
+++ b/engines/xeen/resources.cpp
@@ -345,7 +345,7 @@ void SpriteResource::drawOffset(XSurface &dest, uint16 offset, const Common::Poi
 		}
 	}
 
-	dest.addDirtyRect(Common::Rect(destPos.x, destPos.y,
+	dest.addDirtyRect(Common::Rect(destPos.x + xOffset, destPos.y + yOffset,
 		destPos.x + xOffset + width, destPos.y + yOffset + height));
 }
 
diff --git a/engines/xeen/screen.cpp b/engines/xeen/screen.cpp
index 0c7df8b..e390f16 100644
--- a/engines/xeen/screen.cpp
+++ b/engines/xeen/screen.cpp
@@ -160,7 +160,7 @@ void Screen::vertMerge(int yp) {
 		Common::copy(srcP, srcP + SCREEN_WIDTH, destP);
 	}
 
-	for (int y = yp; y < SCREEN_HEIGHT; ++y) {
+	for (int y = SCREEN_HEIGHT - yp; y < SCREEN_HEIGHT; ++y) {
 		const byte *srcP = (const byte *)_pages[1].getBasePtr(0, y);
 		byte *destP = (byte *)getBasePtr(0, y);
 		Common::copy(srcP, srcP + SCREEN_WIDTH, destP);


Commit: cadb7176bc6336de2ee05c3465e9954157a8e4a6
    https://github.com/scummvm/scummvm/commit/cadb7176bc6336de2ee05c3465e9954157a8e4a6
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2014-12-26T18:57:58+11:00

Commit Message:
XEEN: Fix error in vertMerge

Changed paths:
    engines/xeen/screen.cpp



diff --git a/engines/xeen/screen.cpp b/engines/xeen/screen.cpp
index e390f16..5276b69 100644
--- a/engines/xeen/screen.cpp
+++ b/engines/xeen/screen.cpp
@@ -141,8 +141,8 @@ void Screen::horizMerge(int xp) {
 		Common::copy(srcP, srcP + SCREEN_WIDTH - xp, destP);
 
 		if (xp != 0) {
-			srcP = (const byte *)_pages[1].getBasePtr(xp, y);
-			Common::copy(srcP, srcP + SCREEN_WIDTH - xp, destP + xp);
+			srcP = (const byte *)_pages[1].getBasePtr(0, y);
+			Common::copy(srcP + SCREEN_WIDTH - xp, srcP + SCREEN_WIDTH, destP + SCREEN_WIDTH - xp);
 		}
 	}
 }


Commit: a93177e0b3a7aba23667b1edbf81fe4d949d69b7
    https://github.com/scummvm/scummvm/commit/a93177e0b3a7aba23667b1edbf81fe4d949d69b7
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2014-12-26T21:10:02+11:00

Commit Message:
XEEN: Fix for correct line offsets in sprite drawing

Changed paths:
    engines/xeen/resources.cpp



diff --git a/engines/xeen/resources.cpp b/engines/xeen/resources.cpp
index 736f014..6690ad0 100644
--- a/engines/xeen/resources.cpp
+++ b/engines/xeen/resources.cpp
@@ -322,6 +322,7 @@ void SpriteResource::drawOffset(XSurface &dest, uint16 offset, const Common::Poi
 
 				case 5:   // Skip len + 1 pixels filling them with the transparent color.
 					xPos += len + 1;
+					destP += len + 1;
 					break;
 
 				case 6:   // Pattern command.


Commit: 1d62e224b98e4d2c9736c4965b3da5735b32c022
    https://github.com/scummvm/scummvm/commit/1d62e224b98e4d2c9736c4965b3da5735b32c022
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2014-12-26T22:00:39+11:00

Commit Message:
XEEN: Implement button handlng and rest of Dark Side title screen

Changed paths:
    engines/xeen/darkside/darkside_game.cpp
    engines/xeen/darkside/darkside_game.h
    engines/xeen/events.cpp
    engines/xeen/events.h
    engines/xeen/resources.cpp
    engines/xeen/resources.h
    engines/xeen/sound.cpp
    engines/xeen/sound.h



diff --git a/engines/xeen/darkside/darkside_game.cpp b/engines/xeen/darkside/darkside_game.cpp
index 17a998e..c067242 100644
--- a/engines/xeen/darkside/darkside_game.cpp
+++ b/engines/xeen/darkside/darkside_game.cpp
@@ -35,11 +35,16 @@ void DarkSideEngine::playGame() {
 }
 
 void DarkSideEngine::darkSideIntro() {
+	showTitle();
+	if (shouldQuit())
+		return;
+}
+
+void DarkSideEngine::showTitle() {
 	//sub_28F40
 	_screen->loadPalette("dark.pal");
-	File special("special.bin");
 	SpriteResource nwc[4] = {
-		SpriteResource("nwc1.int"), SpriteResource("nwc2.int"), 
+		SpriteResource("nwc1.int"), SpriteResource("nwc2.int"),
 		SpriteResource("nwc3.int"), SpriteResource("nwc4.int")
 	};
 	File voc[3] = {
@@ -57,13 +62,13 @@ void DarkSideEngine::darkSideIntro() {
 	_screen->draw();
 	_screen->fade(4);
 
-	bool breakFlag = false;
+	// Initial loop for dragon roaring
 	int nwcIndex = 0, nwcFrame = 0;
-	for (int idx = 0; idx < 55 && !shouldQuit() && !breakFlag; ++idx) {
+	for (int idx = 0; idx < 55 && !shouldQuit(); ++idx) {
 		// Render the next frame
 		_events->updateGameCounter();
 		_screen->vertMerge(0);
-		nwc[nwcIndex].draw(*_screen, nwcFrame, Common::Point(0, 0));
+		nwc[nwcIndex].draw(*_screen, nwcFrame);
 		_screen->draw();
 
 		switch (idx) {
@@ -84,13 +89,54 @@ void DarkSideEngine::darkSideIntro() {
 
 		while (!shouldQuit() && _events->timeElapsed() < 2) {
 			_events->pollEventsAndWait();
-			Common::KeyState keyState;
-			if (_events->getKey(keyState)) {
-				if (keyState.keycode == Common::KEYCODE_ESCAPE)
-					breakFlag = true;
-			}
+			if (_events->isKeyMousePressed())
+				return;
 		}
 	}
+
+	// Loop for dragon using flyspray
+	for (int idx = 0; idx < 42 && !shouldQuit(); ++idx) {
+		_events->updateGameCounter();
+		_screen->vertMerge(SCREEN_HEIGHT);
+		nwc[3].draw(*_screen, idx);
+		_screen->draw();
+
+		switch (idx) {
+		case 3:
+			_sound->startMusic(40);
+			break;
+		case 11:
+			_sound->startMusic(0);
+		case 27:
+		case 30:
+			_sound->startMusic(3);
+			break;
+		case 31:
+			_sound->proc2(voc[2]);
+			break;
+		case 33:
+			_sound->startMusic(2);
+			break;
+		default:
+			break;
+		}
+
+		while (!shouldQuit() && _events->timeElapsed() < 2) {
+			_events->pollEventsAndWait();
+			if (_events->isKeyMousePressed())
+				return;
+		}
+	}
+
+	// Pause fora  bit
+	while (!shouldQuit() && _events->timeElapsed() < 10) {
+		_events->pollEventsAndWait();
+		if (_events->isKeyMousePressed())
+			return;
+	}
+
+	// TODO: Stop sound and music
+
 }
 
 } // End of namespace Xeen
diff --git a/engines/xeen/darkside/darkside_game.h b/engines/xeen/darkside/darkside_game.h
index 827ba20..5574d45 100644
--- a/engines/xeen/darkside/darkside_game.h
+++ b/engines/xeen/darkside/darkside_game.h
@@ -28,6 +28,8 @@
 namespace Xeen {
 
 class DarkSideEngine : virtual public XeenEngine {
+private:
+	void showTitle();
 protected:
 	void darkSideIntro();
 
diff --git a/engines/xeen/events.cpp b/engines/xeen/events.cpp
index c4adabc..8e1b207 100644
--- a/engines/xeen/events.cpp
+++ b/engines/xeen/events.cpp
@@ -86,6 +86,18 @@ void EventsManager::pollEvents() {
 		case Common::EVENT_KEYDOWN:
 			_keyCode = event.kbd.keycode;
 			break;
+		case Common::EVENT_LBUTTONDOWN:
+			_leftButton = true;
+			return;
+		case Common::EVENT_LBUTTONUP:
+			_leftButton = false;
+			return;
+		case Common::EVENT_RBUTTONDOWN:
+			_rightButton = true;
+			return;
+		case Common::EVENT_RBUTTONUP:
+			_rightButton = false;
+			break;
 		default:
  			break;
 		}
@@ -103,7 +115,11 @@ void EventsManager::clearEvents() {
 
 }
 
-
+void EventsManager::debounceMouse() {
+	while (_leftButton && !_vm->shouldQuit()) {
+		pollEventsAndWait();
+	}
+}
 bool EventsManager::getKey(Common::KeyState &key) {
 	if (_keyCode == Common::KEYCODE_INVALID) {
 		return false;
@@ -114,6 +130,21 @@ bool EventsManager::getKey(Common::KeyState &key) {
 	}
 }
 
+bool EventsManager::isKeyPending() const {
+	return _keyCode != Common::KEYCODE_INVALID;
+}
+
+/**
+ * Returns true if a key or mouse press is pending
+ */
+bool EventsManager::isKeyMousePressed() {
+	bool result = _leftButton || _rightButton || isKeyPending();
+	debounceMouse();
+	clearEvents();
+
+	return result;
+}
+
 /**
  * Updates the game counter to match the current frame counter
  */
diff --git a/engines/xeen/events.h b/engines/xeen/events.h
index 4d775ac..b380f7b 100644
--- a/engines/xeen/events.h
+++ b/engines/xeen/events.h
@@ -62,8 +62,14 @@ public:
 
 	void clearEvents();
 
+	void debounceMouse();
+
 	bool getKey(Common::KeyState &key);
 
+	bool isKeyPending() const;
+
+	bool isKeyMousePressed();
+
 	void updateGameCounter();
 
 	uint32 timeElapsed();
diff --git a/engines/xeen/resources.cpp b/engines/xeen/resources.cpp
index 6690ad0..40353c1 100644
--- a/engines/xeen/resources.cpp
+++ b/engines/xeen/resources.cpp
@@ -250,6 +250,11 @@ void SpriteResource::draw(XSurface &dest, int frame, const Common::Point &destPo
 		drawOffset(dest, _index[frame]._offset2, destPos);
 }
 
+void SpriteResource::draw(XSurface &dest, int frame) const {
+	draw(dest, frame, Common::Point());
+}
+
+
 void SpriteResource::drawOffset(XSurface &dest, uint16 offset, const Common::Point &destPos) const {
 	// Get cell header
 	Common::MemoryReadStream f(_data, _filesize);
diff --git a/engines/xeen/resources.h b/engines/xeen/resources.h
index fcb1842..d29f0f1 100644
--- a/engines/xeen/resources.h
+++ b/engines/xeen/resources.h
@@ -72,6 +72,8 @@ public:
 	int size() const;
 
 	void draw(XSurface &dest, int frame, const Common::Point &destPos) const;
+
+	void draw(XSurface &dest, int frame) const;
 };
 
 } // End of namespace Xeen
diff --git a/engines/xeen/sound.cpp b/engines/xeen/sound.cpp
index 2863a3d..9495b25 100644
--- a/engines/xeen/sound.cpp
+++ b/engines/xeen/sound.cpp
@@ -31,4 +31,9 @@ void SoundManager::proc2(File &f) {
 
 }
 
+void SoundManager::startMusic(int v1) {
+
+}
+
+
 } // End of namespace Xeen
diff --git a/engines/xeen/sound.h b/engines/xeen/sound.h
index 2e163e7..b122fc1 100644
--- a/engines/xeen/sound.h
+++ b/engines/xeen/sound.h
@@ -36,6 +36,8 @@ public:
 	SoundManager(XeenEngine *vm);
 
 	void proc2(File &f);
+
+	void startMusic(int v1);
 };
 
 } // End of namespace Xeen


Commit: 537da8b7b9090ef9be2ea9b4c3ef2b76461364ab
    https://github.com/scummvm/scummvm/commit/537da8b7b9090ef9be2ea9b4c3ef2b76461364ab
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2014-12-27T09:07:25+11:00

Commit Message:
XEEN: Second Dark Side title screen, beginnings of starting sequence

Changed paths:
    engines/xeen/darkside/darkside_game.cpp
    engines/xeen/darkside/darkside_game.h
    engines/xeen/screen.cpp
    engines/xeen/screen.h



diff --git a/engines/xeen/darkside/darkside_game.cpp b/engines/xeen/darkside/darkside_game.cpp
index c067242..3dd4c0e 100644
--- a/engines/xeen/darkside/darkside_game.cpp
+++ b/engines/xeen/darkside/darkside_game.cpp
@@ -34,13 +34,31 @@ void DarkSideEngine::playGame() {
 	playGame();
 }
 
+bool DarkSideEngine::pause(int amount) {
+	while (!shouldQuit() && _events->timeElapsed() < amount) {
+		_events->pollEventsAndWait();
+		if (_events->isKeyMousePressed())
+			return true;
+	}
+
+	return shouldQuit();
+}
+
 void DarkSideEngine::darkSideIntro() {
-	showTitle();
+	showTitle1();
 	if (shouldQuit())
 		return;
+
+	showTitle2();
+	if (shouldQuit())
+		return;
+
+	// TODO: Only show startup if not seen before
+	showStartSequence();
 }
 
-void DarkSideEngine::showTitle() {
+void DarkSideEngine::showTitle1() {
+	// TODO: Starting method, and sound
 	//sub_28F40
 	_screen->loadPalette("dark.pal");
 	SpriteResource nwc[4] = {
@@ -87,11 +105,8 @@ void DarkSideEngine::showTitle() {
 			++nwcFrame;
 		}
 
-		while (!shouldQuit() && _events->timeElapsed() < 2) {
-			_events->pollEventsAndWait();
-			if (_events->isKeyMousePressed())
-				return;
-		}
+		if (pause(2))
+			return;
 	}
 
 	// Loop for dragon using flyspray
@@ -121,22 +136,87 @@ void DarkSideEngine::showTitle() {
 			break;
 		}
 
-		while (!shouldQuit() && _events->timeElapsed() < 2) {
+		if (pause(2))
+			return;
+	}
+
+	// Pause for a bit
+	pause(10);
+}
+
+void DarkSideEngine::showTitle2() {
+	_screen->fadeOut(8);
+	//TODO: Stuff
+
+	_screen->loadBackground("jvc.raw");
+	_screen->draw();
+	_screen->fade(4);
+	
+	_events->updateGameCounter();
+	pause(60);
+}
+	
+void DarkSideEngine::showStartSequence() {
+	_screen->fadeOut(8);
+	_screen->loadBackground("pyramid2.raw");
+	_screen->loadPage(0);
+	_screen->loadPage(1);
+	_screen->loadBackground("pyramid3.raw");
+	_screen->saveScreen(1);
+
+	SpriteResource sprites[3] = {
+		SpriteResource("title.int"), SpriteResource("pyratop.int"), SpriteResource("pyramid.int")
+	};
+	File voc[2] = {
+		File("pharoh1a.voc"), File("pharoh1b.voc")
+	};
+
+	_screen->vertMerge(SCREEN_HEIGHT);
+	_screen->loadPage(0);
+	_screen->loadPage(1);
+
+	int yp = 0;
+	int frame = 0;
+	int idx1 = 0;
+	bool skipElapsed = false;
+	uint32 timeExpired = 0;
+	bool fadeFlag = true;
+
+	for (int idx = 200; idx > 0; ) {
+		_events->updateGameCounter();
+		_screen->vertMerge(yp);
+
+		sprites[0].draw(*_screen, 0);
+		if (frame)
+			sprites[0].draw(*_screen, frame);
+
+		idx1 = (idx1 + 1) % 4;
+		if (!idx1)
+			frame = (frame + 1) % 10;
+
+		_screen->draw();
+		if (!skipElapsed) {
+			timeExpired = MAX(_events->timeElapsed(), (uint32)1);
+			skipElapsed = true;
+		}
+
+		idx -= timeExpired;
+		frame = MIN(frame + timeExpired, (uint)200);
+
+		while (_events->timeElapsed() < 1) {
 			_events->pollEventsAndWait();
 			if (_events->isKeyMousePressed())
 				return;
 		}
 	}
 
-	// Pause fora  bit
-	while (!shouldQuit() && _events->timeElapsed() < 10) {
-		_events->pollEventsAndWait();
-		if (_events->isKeyMousePressed())
-			return;
-	}
-
-	// TODO: Stop sound and music
+	_screen->vertMerge(SCREEN_HEIGHT);
+	_screen->saveScreen(1);
+	_screen->draw();
+	_screen->freePages();
 
+	_events->updateGameCounter();
+	pause(30);
 }
 
 } // End of namespace Xeen
diff --git a/engines/xeen/darkside/darkside_game.h b/engines/xeen/darkside/darkside_game.h
index 5574d45..39ec87f 100644
--- a/engines/xeen/darkside/darkside_game.h
+++ b/engines/xeen/darkside/darkside_game.h
@@ -29,7 +29,13 @@ namespace Xeen {
 
 class DarkSideEngine : virtual public XeenEngine {
 private:
-	void showTitle();
+	bool pause(int amount);
+
+	void showTitle1();
+
+	void showTitle2();
+
+	void showStartSequence();
 protected:
 	void darkSideIntro();
 
diff --git a/engines/xeen/screen.cpp b/engines/xeen/screen.cpp
index 5276b69..699e13e 100644
--- a/engines/xeen/screen.cpp
+++ b/engines/xeen/screen.cpp
@@ -32,7 +32,7 @@ namespace Xeen {
  * Constructor
  */
 Screen::Screen(XeenEngine *vm) : _vm(vm) {
-	_fadeMode = false;
+	_fadeIn = false;
 	create(SCREEN_WIDTH, SCREEN_HEIGHT);
 }
 
@@ -128,6 +128,11 @@ void Screen::loadPage(int pageNum) {
 	blitTo(_pages[pageNum]);
 }
 
+void Screen::freePages() {
+	_pages[0].free();
+	_pages[1].free();
+}
+
 /**
  * Merge the two pages along a horizontal split point
  */
@@ -181,19 +186,19 @@ void Screen::drawScreen() {
 }
 
 void Screen::fade(int step) {
-	_fadeMode = true;
+	_fadeIn = true;
 	fadeInner(step);
 }
 
-void Screen::fade2(int step) {
-	_fadeMode = false;
+void Screen::fadeOut(int step) {
+	_fadeIn = false;
 	fadeInner(step);
 }
 
 void Screen::fadeInner(int step) {
-	for (int idx = 128; idx != 0 && !_vm->shouldQuit(); idx -= step) {
-		int val = idx;
-		bool flag = !_fadeMode;
+	for (int idx = 128; idx >= 0 && !_vm->shouldQuit(); idx -= step) {
+		int val = MAX(idx, 0);
+		bool flag = !_fadeIn;
 		if (!flag) {
 			val = -(val - 128);
 			flag = step != 0x81;
@@ -222,4 +227,17 @@ void Screen::updatePalette(const byte *pal, int start, int count16) {
 	g_system->getPaletteManager()->setPalette(pal, start, count16 * 16);
 }
 
+void Screen::saveScreen(int slot) {
+	assert(slot > 0 && slot < 10);
+	_savedScreens[slot - 1].copyFrom(*this);
+}
+
+void Screen::restoreScreen(int slot) {
+	assert(slot > 0 && slot < 10);
+
+	_savedScreens[slot - 1].blitTo(*this);
+	_savedScreens[slot - 1].free();
+}
+
+
 } // End of namespace Xeen
diff --git a/engines/xeen/screen.h b/engines/xeen/screen.h
index 02fe746..72d9da0 100644
--- a/engines/xeen/screen.h
+++ b/engines/xeen/screen.h
@@ -45,7 +45,8 @@ private:
 	byte _mainPalette[PALETTE_SIZE];
 	byte _tempPaltte[PALETTE_SIZE];
 	XSurface _pages[2];
-	bool _fadeMode;
+	XSurface _savedScreens[10];
+	bool _fadeIn;
 
 	void mergeDirtyRects();
 
@@ -71,6 +72,8 @@ public:
 
 	void loadPage(int pageNum);
 
+	void freePages();
+
 	void horizMerge(int xp);
 
 	void vertMerge(int yp);
@@ -79,7 +82,11 @@ public:
 
 	void fade(int step);
 
-	void fade2(int step);
+	void fadeOut(int step);
+
+	void saveScreen(int slot);
+
+	void restoreScreen(int slot);
 };
 
 } // End of namespace Xeen


Commit: 676e7583f2d992a5a047e1e1b9f9a9d8929f2a0a
    https://github.com/scummvm/scummvm/commit/676e7583f2d992a5a047e1e1b9f9a9d8929f2a0a
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2014-12-29T21:20:40-10:00

Commit Message:
XEEN: Temporary processing of Window list data to produce formatted output

Changed paths:
    engines/xeen/darkside/darkside_game.cpp
    engines/xeen/darkside/darkside_game.h
    engines/xeen/screen.cpp
    engines/xeen/screen.h
    engines/xeen/worldofxeen/worldofxeen_game.cpp



diff --git a/engines/xeen/darkside/darkside_game.cpp b/engines/xeen/darkside/darkside_game.cpp
index 3dd4c0e..c039d1f 100644
--- a/engines/xeen/darkside/darkside_game.cpp
+++ b/engines/xeen/darkside/darkside_game.cpp
@@ -31,10 +31,10 @@ DarkSideEngine::DarkSideEngine(OSystem *syst, const XeenGameDescription *gameDes
 }
 
 void DarkSideEngine::playGame() {
-	playGame();
+	// TODO
 }
 
-bool DarkSideEngine::pause(int amount) {
+bool DarkSideEngine::pause(uint amount) {
 	while (!shouldQuit() && _events->timeElapsed() < amount) {
 		_events->pollEventsAndWait();
 		if (_events->isKeyMousePressed())
@@ -45,6 +45,7 @@ bool DarkSideEngine::pause(int amount) {
 }
 
 void DarkSideEngine::darkSideIntro() {
+	/*
 	showTitle1();
 	if (shouldQuit())
 		return;
@@ -52,7 +53,7 @@ void DarkSideEngine::darkSideIntro() {
 	showTitle2();
 	if (shouldQuit())
 		return;
-
+		*/
 	// TODO: Only show startup if not seen before
 	showStartSequence();
 }
@@ -78,7 +79,7 @@ void DarkSideEngine::showTitle1() {
 	// Draw the screen and fade it in
 	_screen->horizMerge(0);
 	_screen->draw();
-	_screen->fade(4);
+	_screen->fadeIn(4);
 
 	// Initial loop for dragon roaring
 	int nwcIndex = 0, nwcFrame = 0;
@@ -150,7 +151,7 @@ void DarkSideEngine::showTitle2() {
 
 	_screen->loadBackground("jvc.raw");
 	_screen->draw();
-	_screen->fade(4);
+	_screen->fadeIn(4);
 	
 	_events->updateGameCounter();
 	pause(60);
@@ -162,7 +163,7 @@ void DarkSideEngine::showStartSequence() {
 	_screen->loadPage(0);
 	_screen->loadPage(1);
 	_screen->loadBackground("pyramid3.raw");
-	_screen->saveScreen(1);
+	_screen->saveBackground(1);
 
 	SpriteResource sprites[3] = {
 		SpriteResource("title.int"), SpriteResource("pyratop.int"), SpriteResource("pyramid.int")
@@ -211,7 +212,7 @@ void DarkSideEngine::showStartSequence() {
 	}
 
 	_screen->vertMerge(SCREEN_HEIGHT);
-	_screen->saveScreen(1);
+	_screen->saveBackground(1);
 	_screen->draw();
 	_screen->freePages();
 
diff --git a/engines/xeen/darkside/darkside_game.h b/engines/xeen/darkside/darkside_game.h
index 39ec87f..979885c 100644
--- a/engines/xeen/darkside/darkside_game.h
+++ b/engines/xeen/darkside/darkside_game.h
@@ -29,7 +29,7 @@ namespace Xeen {
 
 class DarkSideEngine : virtual public XeenEngine {
 private:
-	bool pause(int amount);
+	bool pause(uint amount);
 
 	void showTitle1();
 
diff --git a/engines/xeen/screen.cpp b/engines/xeen/screen.cpp
index 699e13e..c1b8a87 100644
--- a/engines/xeen/screen.cpp
+++ b/engines/xeen/screen.cpp
@@ -28,12 +28,178 @@
 
 namespace Xeen {
 
+const int WX[48] = {
+	0, 237, 225, 0,
+	235, 70, 52, 108, 232, 103, 226, 8,
+	0, 50, 0, 50,
+	228, 20, 0, 231,
+	72, 99, 65, 80,
+	0, 27, 15, 90,
+	0, 0, 0, 50,
+	12, 8, 232, 226,
+	225, 27, 225, 0,
+	0, 0, 0, 0,
+	0, 0, 0, 0
+};
+
+ const int WY[48] = {
+		0, 9, 1, 0,
+		148, 20, 149, 0,
+		9, 156, 0, 8,
+		143, 103, 7, 71,
+		106, 142, 20, 48,
+		37, 59, 23, 28,
+		0, 6, 15, 45,
+		0, 101, 0, 112,
+		11, 147, 74, 26,
+		74, 6, 140, 0,
+		0, 0, 0, 0,
+		0, 0, 0, 0
+	};
+
+ const int WW[48] = {
+	 320, 80, 94, 230,
+	 74, 180, 216, 92,
+	 80, 114, 93, 216,
+	 320, 216, 320, 132,
+	 91, 270, 320, 86,
+	 176, 138, 185, 176,
+	 320, 180, 146, 130,
+	 320, 320, 320, 216,
+	 152, 216, 80, 93,
+	 94, 168, 94, 0,
+	 0, 0, 0, 0,
+	 0, 0, 0, 0
+ };
+
+const int WH[48] = {
+200, 65, 72, 149,
+41, 163, 48, 200,
+65, 30, 146, 132,
+56, 36, 131, 58,
+40, 57, 160, 93,
+126, 82, 140, 120,
+146, 136, 76, 112,
+200, 45, 108, 36,
+83, 45, 64, 120,
+80, 136, 59, 0,
+0, 0, 0, 0,
+0, 0, 0, 0
+};
+
+	 const int WA[48] = {
+		 0, 0, 1, 0,
+		 2, 3, 4, 5,
+		 0, 6, 7, 8,
+		 9, 10, 11, 12,
+		 13, 14, 15, 16,
+		 17, 18, 19, 20,
+		 21, 22, 23, 24,
+		 25, 26, 27, 28,
+		 0, 0, 29, 30,
+		 31, 0, 0, 0,
+		 0, 0, 0, 0,
+		 0, 0, 0, 0
+	 };
+
+	 const int WB[48] = {
+		 0, 0, 8, 0,
+		 8, 8, 8, 0,
+		 0, 8, 8, 8,
+		 8, 8, 8, 8,
+		 8, 8, 8, 8,
+		 8, 8, 8, 8,
+		 8, 8, 8, 8,
+		 8, 8, 8, 8,
+		 0, 8, 8, 8,
+		 8, 8, 8, 8,
+		 8, 8, 8, 8,
+		 8, 8, 8, 8
+	 };
+
+	 const int WXlo[48] = { 0, 237, 225, 9,
+		 0, 80, 0, 0,
+		 0, 0, 0, 8,
+		 0, 0, 0, 0,
+		 0, 0, 0, 0,
+		 0, 99, 75, 80,
+		 0, 0, 0, 0,
+		 0, 0, 0, 0,
+		 0, 0, 0, 0,
+		 0, 0, 0, 0,
+		 0, 0, 0, 0,
+		 0, 0, 0, 0
+	 };
+
+	 const int WYcl[48] = {
+		 0, 12, 1, 8,
+		 0, 38, 0, 0,
+		 0, 0, 0, 8,
+		 0, 0, 0, 0,
+		 0, 0, 0, 0,
+		 0, 59, 36, 28,
+		 0, 0, 0, 0,
+		 0, 101, 0, 0,
+		 0, 0, 0, 0,
+		 0, 0, 0, 0,
+		 0, 0, 0, 0,
+		 0, 0, 0, 0
+	 };
+
+	 const int WXhi[48] = {
+		 320, 307, 319, 216,
+		 0, 240, 0, 0,
+		 0, 0, 0, 224,
+		 0, 0, 0, 0,
+		 0, 0, 0, 0,
+		 0, 237, 245, 256,
+		 320, 0, 0, 0,
+		 0, 320, 0, 0,
+		 52, 0, 0, 0,
+		 0, 0, 0, 0,
+		 0, 0, 0, 0,
+		 0, 0, 0, 0
+	 };
+
+	 const int WYch[48] = {
+		 200, 68, 73, 140,
+		 0, 166, 0, 0,
+		 0, 0, 0, 200,
+		 0, 0, 0, 0,
+		 0, 0, 0, 0,
+		 0, 0, 141, 172,
+		 148, 146, 0, 0,
+		 0, 0, 45, 0,
+		 0, 94, 0, 0,
+		 0, 0, 0, 0,
+		 0, 0, 0, 0,
+		 0, 0, 0, 0
+	 };
+
+Window::Window(const Common::Rect &bounds, int a, int border, int xLo, int ycL, int xHi, int ycH) {
+	_bounds = bounds;
+	_a = a;
+	_border = border;
+	_xLo = xLo;
+	_ycL = ycL;
+	_xHi = xHi;
+	_ycH = ycH;
+}
+
+/*------------------------------------------------------------------------*/
+
 /**
  * Constructor
  */
 Screen::Screen(XeenEngine *vm) : _vm(vm) {
 	_fadeIn = false;
 	create(SCREEN_WIDTH, SCREEN_HEIGHT);
+
+	for (int i = 0; i < 48; ++i) {
+		warning("Window(Common::Rect(%d, %d, %d, %d), %d, %d, %d, %d, %d, %d);",
+			WX[i], WY[i], WX[i] + WW[i], WY[i] + WH[i], WA[i], WB[i], WXlo[i],
+			WYcl[i], WXhi[i], WYch[i]);
+	}
 }
 
 void Screen::update() {
@@ -185,7 +351,7 @@ void Screen::drawScreen() {
 	addDirtyRect(Common::Rect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT));
 }
 
-void Screen::fade(int step) {
+void Screen::fadeIn(int step) {
 	_fadeIn = true;
 	fadeInner(step);
 }
@@ -227,12 +393,12 @@ void Screen::updatePalette(const byte *pal, int start, int count16) {
 	g_system->getPaletteManager()->setPalette(pal, start, count16 * 16);
 }
 
-void Screen::saveScreen(int slot) {
+void Screen::saveBackground(int slot) {
 	assert(slot > 0 && slot < 10);
 	_savedScreens[slot - 1].copyFrom(*this);
 }
 
-void Screen::restoreScreen(int slot) {
+void Screen::restoreBackground(int slot) {
 	assert(slot > 0 && slot < 10);
 
 	_savedScreens[slot - 1].blitTo(*this);
diff --git a/engines/xeen/screen.h b/engines/xeen/screen.h
index 72d9da0..157d0bc 100644
--- a/engines/xeen/screen.h
+++ b/engines/xeen/screen.h
@@ -38,6 +38,17 @@ namespace Xeen {
 
 class XeenEngine;
 
+class Window {
+private:
+	Common::Rect _bounds;
+	int _a;
+	int _border;
+	int _xLo, _xHi;
+	int _ycL, _ycH;
+public:
+	Window(const Common::Rect &bounds, int a, int border, int xLo, int ycL, int xHi, int ycH);
+};
+
 class Screen: public XSurface {
 private:
 	XeenEngine *_vm;
@@ -80,13 +91,13 @@ public:
 
 	void draw(void *data = nullptr);
 
-	void fade(int step);
+	void fadeIn(int step);
 
 	void fadeOut(int step);
 
-	void saveScreen(int slot);
+	void saveBackground(int slot);
 
-	void restoreScreen(int slot);
+	void restoreBackground(int slot);
 };
 
 } // End of namespace Xeen
diff --git a/engines/xeen/worldofxeen/worldofxeen_game.cpp b/engines/xeen/worldofxeen/worldofxeen_game.cpp
index f27b8b9..dba5612 100644
--- a/engines/xeen/worldofxeen/worldofxeen_game.cpp
+++ b/engines/xeen/worldofxeen/worldofxeen_game.cpp
@@ -30,7 +30,7 @@ WorldOfXeenEngine::WorldOfXeenEngine(OSystem *syst, const XeenGameDescription *g
 }
 
 void WorldOfXeenEngine::playGame () {
-	darkSideIntro();
+	//darkSideIntro();
 }
 
 } // End of namespace Xeen


Commit: 6a71a9f4d49c20bcebff4b91ccfbfa46e4775f10
    https://github.com/scummvm/scummvm/commit/6a71a9f4d49c20bcebff4b91ccfbfa46e4775f10
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2014-12-29T22:09:21-10:00

Commit Message:
XEEN: Proper setup of window list

Changed paths:
    engines/xeen/screen.cpp
    engines/xeen/screen.h



diff --git a/engines/xeen/screen.cpp b/engines/xeen/screen.cpp
index c1b8a87..79aa733 100644
--- a/engines/xeen/screen.cpp
+++ b/engines/xeen/screen.cpp
@@ -28,162 +28,14 @@
 
 namespace Xeen {
 
-const int WX[48] = {
-	0, 237, 225, 0,
-	235, 70, 52, 108, 232, 103, 226, 8,
-	0, 50, 0, 50,
-	228, 20, 0, 231,
-	72, 99, 65, 80,
-	0, 27, 15, 90,
-	0, 0, 0, 50,
-	12, 8, 232, 226,
-	225, 27, 225, 0,
-	0, 0, 0, 0,
-	0, 0, 0, 0
-};
-
- const int WY[48] = {
-		0, 9, 1, 0,
-		148, 20, 149, 0,
-		9, 156, 0, 8,
-		143, 103, 7, 71,
-		106, 142, 20, 48,
-		37, 59, 23, 28,
-		0, 6, 15, 45,
-		0, 101, 0, 112,
-		11, 147, 74, 26,
-		74, 6, 140, 0,
-		0, 0, 0, 0,
-		0, 0, 0, 0
-	};
+Window::Window() : _screen(nullptr), _a(0), _border(0),
+	_xLo(0), _xHi(0), _ycL(0), _ycH(0) {
+}
 
- const int WW[48] = {
-	 320, 80, 94, 230,
-	 74, 180, 216, 92,
-	 80, 114, 93, 216,
-	 320, 216, 320, 132,
-	 91, 270, 320, 86,
-	 176, 138, 185, 176,
-	 320, 180, 146, 130,
-	 320, 320, 320, 216,
-	 152, 216, 80, 93,
-	 94, 168, 94, 0,
-	 0, 0, 0, 0,
-	 0, 0, 0, 0
- };
-
-const int WH[48] = {
-200, 65, 72, 149,
-41, 163, 48, 200,
-65, 30, 146, 132,
-56, 36, 131, 58,
-40, 57, 160, 93,
-126, 82, 140, 120,
-146, 136, 76, 112,
-200, 45, 108, 36,
-83, 45, 64, 120,
-80, 136, 59, 0,
-0, 0, 0, 0,
-0, 0, 0, 0
-};
-
-	 const int WA[48] = {
-		 0, 0, 1, 0,
-		 2, 3, 4, 5,
-		 0, 6, 7, 8,
-		 9, 10, 11, 12,
-		 13, 14, 15, 16,
-		 17, 18, 19, 20,
-		 21, 22, 23, 24,
-		 25, 26, 27, 28,
-		 0, 0, 29, 30,
-		 31, 0, 0, 0,
-		 0, 0, 0, 0,
-		 0, 0, 0, 0
-	 };
-
-	 const int WB[48] = {
-		 0, 0, 8, 0,
-		 8, 8, 8, 0,
-		 0, 8, 8, 8,
-		 8, 8, 8, 8,
-		 8, 8, 8, 8,
-		 8, 8, 8, 8,
-		 8, 8, 8, 8,
-		 8, 8, 8, 8,
-		 0, 8, 8, 8,
-		 8, 8, 8, 8,
-		 8, 8, 8, 8,
-		 8, 8, 8, 8
-	 };
-
-	 const int WXlo[48] = { 0, 237, 225, 9,
-		 0, 80, 0, 0,
-		 0, 0, 0, 8,
-		 0, 0, 0, 0,
-		 0, 0, 0, 0,
-		 0, 99, 75, 80,
-		 0, 0, 0, 0,
-		 0, 0, 0, 0,
-		 0, 0, 0, 0,
-		 0, 0, 0, 0,
-		 0, 0, 0, 0,
-		 0, 0, 0, 0
-	 };
-
-	 const int WYcl[48] = {
-		 0, 12, 1, 8,
-		 0, 38, 0, 0,
-		 0, 0, 0, 8,
-		 0, 0, 0, 0,
-		 0, 0, 0, 0,
-		 0, 59, 36, 28,
-		 0, 0, 0, 0,
-		 0, 101, 0, 0,
-		 0, 0, 0, 0,
-		 0, 0, 0, 0,
-		 0, 0, 0, 0,
-		 0, 0, 0, 0
-	 };
-
-	 const int WXhi[48] = {
-		 320, 307, 319, 216,
-		 0, 240, 0, 0,
-		 0, 0, 0, 224,
-		 0, 0, 0, 0,
-		 0, 0, 0, 0,
-		 0, 237, 245, 256,
-		 320, 0, 0, 0,
-		 0, 320, 0, 0,
-		 52, 0, 0, 0,
-		 0, 0, 0, 0,
-		 0, 0, 0, 0,
-		 0, 0, 0, 0
-	 };
-
-	 const int WYch[48] = {
-		 200, 68, 73, 140,
-		 0, 166, 0, 0,
-		 0, 0, 0, 200,
-		 0, 0, 0, 0,
-		 0, 0, 0, 0,
-		 0, 0, 141, 172,
-		 148, 146, 0, 0,
-		 0, 0, 45, 0,
-		 0, 94, 0, 0,
-		 0, 0, 0, 0,
-		 0, 0, 0, 0,
-		 0, 0, 0, 0
-	 };
-
-Window::Window(const Common::Rect &bounds, int a, int border, int xLo, int ycL, int xHi, int ycH) {
-	_bounds = bounds;
-	_a = a;
-	_border = border;
-	_xLo = xLo;
-	_ycL = ycL;
-	_xHi = xHi;
-	_ycH = ycH;
+Window::Window(Screen *screen, const Common::Rect &bounds, int a, int border, 
+		int xLo, int ycL, int xHi, int ycH): 
+	_screen(screen), _bounds(bounds), _a(a), _border(border), 
+	_xLo(xLo), _ycL(ycL), _xHi(xHi), _ycH(ycH) {
 }
 
 /*------------------------------------------------------------------------*/
@@ -194,12 +46,61 @@ Window::Window(const Common::Rect &bounds, int a, int border, int xLo, int ycL,
 Screen::Screen(XeenEngine *vm) : _vm(vm) {
 	_fadeIn = false;
 	create(SCREEN_WIDTH, SCREEN_HEIGHT);
+	setupWindows();
+}
 
-	for (int i = 0; i < 48; ++i) {
-		warning("Window(Common::Rect(%d, %d, %d, %d), %d, %d, %d, %d, %d, %d);",
-			WX[i], WY[i], WX[i] + WW[i], WY[i] + WH[i], WA[i], WB[i], WXlo[i],
-			WYcl[i], WXhi[i], WYch[i]);
-	}
+void Screen::setupWindows() {
+	Window windows[48] = {
+		Window(this, Common::Rect(0, 0, 320, 200), 0, 0, 0, 0, 320, 200),
+		Window(this, Common::Rect(237, 9, 317, 74), 0, 0, 237, 12, 307, 68),
+		Window(this, Common::Rect(225, 1, 319, 73), 1, 8, 225, 1, 319, 73),
+		Window(this, Common::Rect(0, 0, 230, 149), 0, 0, 9, 8, 216, 140),
+		Window(this, Common::Rect(235, 148, 309, 189), 2, 8, 0, 0, 0, 0),
+		Window(this, Common::Rect(70, 20, 250, 183), 3, 8, 80, 38, 240, 166),
+		Window(this, Common::Rect(52, 149, 268, 197), 4, 8, 0, 0, 0, 0),
+		Window(this, Common::Rect(108, 0, 200, 200), 5, 0, 0, 0, 0, 0),
+		Window(this, Common::Rect(232, 9, 312, 74), 0, 0, 0, 0, 0, 0),
+		Window(this, Common::Rect(103, 156, 217, 186), 6, 8, 0, 0, 0, 0),
+		Window(this, Common::Rect(226, 0, 319, 146), 7, 8, 0, 0, 0, 0),
+		Window(this, Common::Rect(8, 8, 224, 140), 8, 8, 8, 8, 224, 200),
+		Window(this, Common::Rect(0, 143, 320, 199), 9, 8, 0, 0, 0, 0),
+		Window(this, Common::Rect(50, 103, 266, 139), 10, 8, 0, 0, 0, 0),
+		Window(this, Common::Rect(0, 7, 320, 138), 11, 8, 0, 0, 0, 0),
+		Window(this, Common::Rect(50, 71, 182, 129), 12, 8, 0, 0, 0, 0),
+		Window(this, Common::Rect(228, 106, 319, 146), 13, 8, 0, 0, 0, 0),
+		Window(this, Common::Rect(20, 142, 290, 199), 14, 8, 0, 0, 0, 0),
+		Window(this, Common::Rect(0, 20, 320, 180), 15, 8, 0, 0, 0, 0),
+		Window(this, Common::Rect(231, 48, 317, 141), 16, 8, 0, 0, 0, 0),
+		Window(this, Common::Rect(72, 37, 248, 163), 17, 8, 0, 0, 0, 0),
+		Window(this, Common::Rect(99, 59, 237, 141), 18, 8, 99, 59, 237, 0),
+		Window(this, Common::Rect(65, 23, 250, 163), 19, 8, 75, 36, 245, 141),
+		Window(this, Common::Rect(80, 28, 256, 148), 20, 8, 80, 28, 256, 172),
+		Window(this, Common::Rect(0, 0, 320, 146), 21, 8, 0, 0, 320, 148),
+		Window(this, Common::Rect(27, 6, 207, 142), 22, 8, 0, 0, 0, 146),
+		Window(this, Common::Rect(15, 15, 161, 91), 23, 8, 0, 0, 0, 0),
+		Window(this, Common::Rect(90, 45, 220, 157), 24, 8, 0, 0, 0, 0),
+		Window(this, Common::Rect(0, 0, 320, 200), 25, 8, 0, 0, 0, 0),
+		Window(this, Common::Rect(0, 101, 320, 146), 26, 8, 0, 101, 320, 0),
+		Window(this, Common::Rect(0, 0, 320, 108), 27, 8, 0, 0, 0, 45),
+		Window(this, Common::Rect(50, 112, 266, 148), 28, 8, 0, 0, 0, 0),
+		Window(this, Common::Rect(12, 11, 164, 94), 0, 0, 0, 0, 52, 0),
+		Window(this, Common::Rect(8, 147, 224, 192), 0, 8, 0, 0, 0, 94),
+		Window(this, Common::Rect(232, 74, 312, 138), 29, 8, 0, 0, 0, 0),
+		Window(this, Common::Rect(226, 26, 319, 146), 30, 8, 0, 0, 0, 0),
+		Window(this, Common::Rect(225, 74, 319, 154), 31, 8, 0, 0, 0, 0),
+		Window(this, Common::Rect(27, 6, 195, 142), 0, 8, 0, 0, 0, 0),
+		Window(this, Common::Rect(225, 140, 319, 199), 0, 8, 0, 0, 0, 0),
+		Window(this, Common::Rect(), 0, 8, 0, 0, 0, 0),
+		Window(this, Common::Rect(), 0, 8, 0, 0, 0, 0),
+		Window(this, Common::Rect(), 0, 8, 0, 0, 0, 0),
+		Window(this, Common::Rect(), 0, 8, 0, 0, 0, 0),
+		Window(this, Common::Rect(), 0, 8, 0, 0, 0, 0),
+		Window(this, Common::Rect(), 0, 8, 0, 0, 0, 0),
+		Window(this, Common::Rect(), 0, 8, 0, 0, 0, 0),
+		Window(this, Common::Rect(), 0, 8, 0, 0, 0, 0)
+	};
+
+	_windows = Common::Array<Window>(windows, 48);
 }
 
 void Screen::update() {
diff --git a/engines/xeen/screen.h b/engines/xeen/screen.h
index 157d0bc..cd4608c 100644
--- a/engines/xeen/screen.h
+++ b/engines/xeen/screen.h
@@ -37,21 +37,27 @@ namespace Xeen {
 #define PALETTE_SIZE (256 * 3)
 
 class XeenEngine;
+class Screen;
 
 class Window {
 private:
+	Screen *_screen;
 	Common::Rect _bounds;
 	int _a;
 	int _border;
 	int _xLo, _xHi;
 	int _ycL, _ycH;
 public:
-	Window(const Common::Rect &bounds, int a, int border, int xLo, int ycL, int xHi, int ycH);
+	Window();
+
+	Window(Screen *screen, const Common::Rect &bounds, int a, int border, 
+		int xLo, int ycL, int xHi, int ycH);
 };
 
 class Screen: public XSurface {
 private:
 	XeenEngine *_vm;
+	Common::Array<Window> _windows;
 	Common::List<Common::Rect> _dirtyRects;
 	byte _mainPalette[PALETTE_SIZE];
 	byte _tempPaltte[PALETTE_SIZE];
@@ -59,6 +65,8 @@ private:
 	XSurface _savedScreens[10];
 	bool _fadeIn;
 
+	void setupWindows();
+
 	void mergeDirtyRects();
 
 	bool unionRectangle(Common::Rect &destRect, const Common::Rect &src1, const Common::Rect &src2);


Commit: 9d6de4da652b2494d37756e9d12f944cddcf18c8
    https://github.com/scummvm/scummvm/commit/9d6de4da652b2494d37756e9d12f944cddcf18c8
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2014-12-30T10:22:05-10:00

Commit Message:
XEEN: Implemented cursor display

Changed paths:
    engines/xeen/events.cpp
    engines/xeen/events.h
    engines/xeen/resources.cpp
    engines/xeen/resources.h
    engines/xeen/screen.cpp
    engines/xeen/screen.h
    engines/xeen/worldofxeen/worldofxeen_game.cpp
    engines/xeen/xeen.cpp



diff --git a/engines/xeen/events.cpp b/engines/xeen/events.cpp
index 8e1b207..29dde3a 100644
--- a/engines/xeen/events.cpp
+++ b/engines/xeen/events.cpp
@@ -34,13 +34,11 @@ namespace Xeen {
 /**
  * Constructor
  */
-EventsManager::EventsManager(XeenEngine *vm) : _vm(vm) {
-	_frameCounter = 0;
-	_priorFrameCounterTime = 0;
-	_gameCounter = 0;
-	_priorGameCounterTime = 0;
-	_keyCode = Common::KEYCODE_INVALID;
-	_leftButton = _rightButton = false;
+EventsManager::EventsManager(XeenEngine *vm) : _vm(vm),
+		_frameCounter(0), _priorFrameCounterTime(0), _gameCounter(0),
+		_priorGameCounterTime(0), _keyCode(Common::KEYCODE_INVALID),
+		_leftButton(false), _rightButton(false),
+		_sprites("mouse.icn") {
 }
 
 /**
@@ -49,6 +47,16 @@ EventsManager::EventsManager(XeenEngine *vm) : _vm(vm) {
 EventsManager::~EventsManager() {
 }
 
+/*
+ * Set the cursor
+ */
+void EventsManager::setCursor(int cursorId) {
+	XSurface cursor;
+	_sprites.draw(cursor, cursorId);
+
+	CursorMan.replaceCursor(cursor.getPixels(), cursor.w, cursor.h, 0, 0, 0);
+}
+
 /**
  * Show the mouse cursor
  */
diff --git a/engines/xeen/events.h b/engines/xeen/events.h
index b380f7b..3590267 100644
--- a/engines/xeen/events.h
+++ b/engines/xeen/events.h
@@ -25,6 +25,7 @@
 
 #include "common/scummsys.h"
 #include "common/events.h"
+#include "xeen/resources.h"
 
 namespace Xeen {
 
@@ -41,6 +42,7 @@ private:
 	uint32 _priorGameCounterTime;
 	Common::KeyCode _keyCode;
 	bool _leftButton, _rightButton;
+	FramesResource _sprites;
 
 	void nextFrame();
 public:
@@ -50,6 +52,8 @@ public:
 
 	uint32 getFrameCounter() { return _frameCounter; }
 
+	void setCursor(int cursorId);
+
 	void showCursor();
 
 	void hideCursor();
diff --git a/engines/xeen/resources.cpp b/engines/xeen/resources.cpp
index 40353c1..4da84c1 100644
--- a/engines/xeen/resources.cpp
+++ b/engines/xeen/resources.cpp
@@ -216,19 +216,10 @@ void File::openFile(const Common::String &filename) {
 
 /*------------------------------------------------------------------------*/
 
-SpriteResource::SpriteResource(const Common::String &filename) {
+GraphicResource::GraphicResource(const Common::String &filename) {
 	// Open the resource
 	File f(filename);
 
-	// Read in the index
-	int count = f.readUint16LE();
-	_index.resize(count);
-
-	for (int i = 0; i < count; ++i) {
-		_index[i]._offset1 = f.readUint16LE();
-		_index[i]._offset2 = f.readUint16LE();
-	}
-
 	// Read in a copy of the file
 	_filesize = f.size();
 	_data = new byte[_filesize];
@@ -236,26 +227,15 @@ SpriteResource::SpriteResource(const Common::String &filename) {
 	f.read(_data, _filesize);
 }
 
-SpriteResource::~SpriteResource() {
+GraphicResource::~GraphicResource() {
 	delete[] _data;
 }
 
-int SpriteResource::size() const {
-	return _index.size();
-}
-
-void SpriteResource::draw(XSurface &dest, int frame, const Common::Point &destPos) const {
-	drawOffset(dest, _index[frame]._offset1, destPos);
-	if (_index[frame]._offset2)
-		drawOffset(dest, _index[frame]._offset2, destPos);
-}
-
-void SpriteResource::draw(XSurface &dest, int frame) const {
-	draw(dest, frame, Common::Point());
+int GraphicResource::size() const {
+	return READ_LE_UINT16(_data);
 }
 
-
-void SpriteResource::drawOffset(XSurface &dest, uint16 offset, const Common::Point &destPos) const {
+void GraphicResource::drawOffset(XSurface &dest, uint16 offset, const Common::Point &destPos) const {
 	// Get cell header
 	Common::MemoryReadStream f(_data, _filesize);
 	f.seek(offset);
@@ -264,6 +244,9 @@ void SpriteResource::drawOffset(XSurface &dest, uint16 offset, const Common::Poi
 	int yOffset = f.readUint16LE();
 	int height = f.readUint16LE();
 
+	if (dest.w < (xOffset + width) || dest.h < (yOffset + height))
+		dest.create(xOffset + width, yOffset + height);
+
 	// The pattern steps used in the pattern command
 	const int patternSteps[] = { 0, 1, 1, 1, 2, 2, 3, 3, 0, -1, -1, -1, -2, -2, -3, -3 };
 
@@ -355,4 +338,51 @@ void SpriteResource::drawOffset(XSurface &dest, uint16 offset, const Common::Poi
 		destPos.x + xOffset + width, destPos.y + yOffset + height));
 }
 
+/*------------------------------------------------------------------------*/
+
+FramesResource::FramesResource(const Common::String &filename) :
+		GraphicResource(filename) {
+	// Read in the index
+	Common::MemoryReadStream f(_data, _filesize);
+	int count = f.readUint16LE();
+	_index.resize(count);
+
+	for (int i = 0; i < count; ++i) {
+		_index[i] = f.readUint32LE();
+	}
+}
+
+void FramesResource::draw(XSurface &dest, int frame, const Common::Point &destPos) const {
+	drawOffset(dest, _index[frame], destPos);
+}
+
+void FramesResource::draw(XSurface &dest, int frame) const {
+	draw(dest, frame, Common::Point());
+}
+
+/*------------------------------------------------------------------------*/
+
+SpriteResource::SpriteResource(const Common::String &filename) : 
+		GraphicResource(filename) {
+	// Read in the index
+	Common::MemoryReadStream f(_data, _filesize);
+	int count = f.readUint16LE();
+	_index.resize(count);
+
+	for (int i = 0; i < count; ++i) {
+		_index[i]._offset1 = f.readUint16LE();
+		_index[i]._offset2 = f.readUint16LE();
+	}
+}
+
+void SpriteResource::draw(XSurface &dest, int frame, const Common::Point &destPos) const {
+	drawOffset(dest, _index[frame]._offset1, destPos);
+	if (_index[frame]._offset2)
+		drawOffset(dest, _index[frame]._offset2, destPos);
+}
+
+void SpriteResource::draw(XSurface &dest, int frame) const {
+	draw(dest, frame, Common::Point());
+}
+
 } // End of namespace Xeen
diff --git a/engines/xeen/resources.h b/engines/xeen/resources.h
index d29f0f1..0476319 100644
--- a/engines/xeen/resources.h
+++ b/engines/xeen/resources.h
@@ -53,23 +53,49 @@ public:
 	void openFile(const Common::String &filename);
 };
 
-class SpriteResource {
+class GraphicResource {
+protected:
+	int32 _filesize;
+	byte *_data;
+
+	void drawOffset(XSurface &dest, uint16 offset, const Common::Point &destPos) const;
+public:
+	GraphicResource(const Common::String &filename);
+
+	virtual ~GraphicResource();
+
+	int size() const;
+};
+
+/**
+ * Defines a resource that Contains a list of singular sprite frames 
+ */
+class FramesResource : public GraphicResource {
+private:
+	Common::Array<uint32> _index;
+public:
+	FramesResource(const Common::String &filename);
+	virtual ~FramesResource() {}
+
+	void draw(XSurface &dest, int frame, const Common::Point &destPos) const;
+
+	void draw(XSurface &dest, int frame) const;
+};
+
+/**
+ * Defines a resource that contains sets of two layered sprites per frame
+ */
+class SpriteResource : public GraphicResource {
 private:
 	struct IndexEntry {
 		uint16 _offset1, _offset2;
 	};
 	Common::Array<IndexEntry> _index;
 
-	int32 _filesize;
-	byte *_data;
-
-	void drawOffset(XSurface &dest, uint16 offset, const Common::Point &destPos) const;
 public:
 	SpriteResource(const Common::String &filename);
 
-	~SpriteResource();
-
-	int size() const;
+	virtual ~SpriteResource() {}
 
 	void draw(XSurface &dest, int frame, const Common::Point &destPos) const;
 
diff --git a/engines/xeen/screen.cpp b/engines/xeen/screen.cpp
index 79aa733..b1275aa 100644
--- a/engines/xeen/screen.cpp
+++ b/engines/xeen/screen.cpp
@@ -28,13 +28,13 @@
 
 namespace Xeen {
 
-Window::Window() : _screen(nullptr), _a(0), _border(0),
+Window::Window() : _screen(nullptr), _enabled(false), _a(0), _border(0),
 	_xLo(0), _xHi(0), _ycL(0), _ycH(0) {
 }
 
 Window::Window(Screen *screen, const Common::Rect &bounds, int a, int border, 
 		int xLo, int ycL, int xHi, int ycH): 
-	_screen(screen), _bounds(bounds), _a(a), _border(border), 
+	_screen(screen), _enabled(false), _bounds(bounds), _a(a), _border(border), 
 	_xLo(xLo), _ycL(ycL), _xHi(xHi), _ycH(ycH) {
 }
 
@@ -50,7 +50,7 @@ Screen::Screen(XeenEngine *vm) : _vm(vm) {
 }
 
 void Screen::setupWindows() {
-	Window windows[48] = {
+	Window windows[40] = {
 		Window(this, Common::Rect(0, 0, 320, 200), 0, 0, 0, 0, 320, 200),
 		Window(this, Common::Rect(237, 9, 317, 74), 0, 0, 237, 12, 307, 68),
 		Window(this, Common::Rect(225, 1, 319, 73), 1, 8, 225, 1, 319, 73),
@@ -89,18 +89,10 @@ void Screen::setupWindows() {
 		Window(this, Common::Rect(226, 26, 319, 146), 30, 8, 0, 0, 0, 0),
 		Window(this, Common::Rect(225, 74, 319, 154), 31, 8, 0, 0, 0, 0),
 		Window(this, Common::Rect(27, 6, 195, 142), 0, 8, 0, 0, 0, 0),
-		Window(this, Common::Rect(225, 140, 319, 199), 0, 8, 0, 0, 0, 0),
-		Window(this, Common::Rect(), 0, 8, 0, 0, 0, 0),
-		Window(this, Common::Rect(), 0, 8, 0, 0, 0, 0),
-		Window(this, Common::Rect(), 0, 8, 0, 0, 0, 0),
-		Window(this, Common::Rect(), 0, 8, 0, 0, 0, 0),
-		Window(this, Common::Rect(), 0, 8, 0, 0, 0, 0),
-		Window(this, Common::Rect(), 0, 8, 0, 0, 0, 0),
-		Window(this, Common::Rect(), 0, 8, 0, 0, 0, 0),
-		Window(this, Common::Rect(), 0, 8, 0, 0, 0, 0)
+		Window(this, Common::Rect(225, 140, 319, 199), 0, 8, 0, 0, 0, 0)
 	};
 
-	_windows = Common::Array<Window>(windows, 48);
+	_windows = Common::Array<Window>(windows, 40);
 }
 
 void Screen::update() {
diff --git a/engines/xeen/screen.h b/engines/xeen/screen.h
index cd4608c..4178460 100644
--- a/engines/xeen/screen.h
+++ b/engines/xeen/screen.h
@@ -47,6 +47,7 @@ private:
 	int _border;
 	int _xLo, _xHi;
 	int _ycL, _ycH;
+	bool _enabled;
 public:
 	Window();
 
diff --git a/engines/xeen/worldofxeen/worldofxeen_game.cpp b/engines/xeen/worldofxeen/worldofxeen_game.cpp
index dba5612..8057331 100644
--- a/engines/xeen/worldofxeen/worldofxeen_game.cpp
+++ b/engines/xeen/worldofxeen/worldofxeen_game.cpp
@@ -30,7 +30,15 @@ WorldOfXeenEngine::WorldOfXeenEngine(OSystem *syst, const XeenGameDescription *g
 }
 
 void WorldOfXeenEngine::playGame () {
+	_screen->loadPalette("mm4.pal");
+	_screen->fadeIn(4);
+
 	//darkSideIntro();
+	_events->setCursor(0);
+	_events->showCursor();
+	while (!shouldQuit()) {
+		_events->pollEventsAndWait();
+	}
 }
 
 } // End of namespace Xeen
diff --git a/engines/xeen/xeen.cpp b/engines/xeen/xeen.cpp
index f1330f5..5a29363 100644
--- a/engines/xeen/xeen.cpp
+++ b/engines/xeen/xeen.cpp
@@ -55,11 +55,11 @@ void XeenEngine::initialize() {
 	DebugMan.addDebugChannel(kDebugSound, "sound", "Sound and Music handling");
 
 	// Create sub-objects of the engine
+	Resources::init(this);
 	_debugger = new Debugger(this);
 	_events = new EventsManager(this);
 	_screen = new Screen(this);
 	_sound = new SoundManager(this);
-	Resources::init(this);
 
 	// Set graphics mode
 	initGraphics(320, 200, false);


Commit: fb47ec9627937fe5031f20d16c175e5a12b5dfe2
    https://github.com/scummvm/scummvm/commit/fb47ec9627937fe5031f20d16c175e5a12b5dfe2
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2014-12-30T17:28:53-10:00

Commit Message:
XEEN: In progress implementing options/main menu

Changed paths:
  A engines/xeen/menus.cpp
  A engines/xeen/menus.h
    engines/xeen/module.mk
    engines/xeen/screen.cpp
    engines/xeen/screen.h
    engines/xeen/sound.h
    engines/xeen/xeen.cpp



diff --git a/engines/xeen/menus.cpp b/engines/xeen/menus.cpp
new file mode 100644
index 0000000..4ddb85a
--- /dev/null
+++ b/engines/xeen/menus.cpp
@@ -0,0 +1,292 @@
+/* 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/menus.h"
+
+namespace Xeen {
+
+/**
+ * Saves the current list of buttons
+ */
+void Dialog::saveButtons() {
+	_savedButtons.push(_buttons);
+}
+
+/*
+ * Clears the current list of defined buttons
+ */
+void Dialog::clearButtons() {
+	_buttons.clear();
+}
+
+void Dialog::restoreButtons() {
+	_buttons = _savedButtons.pop();
+}
+
+/*------------------------------------------------------------------------*/
+
+void OptionsMenu::show(XeenEngine *vm) {
+	OptionsMenu *menu;
+
+	switch (vm->getGameID()) {
+	case GType_Clouds:
+		menu = new CloudsOptionsMenu(vm);
+		break;
+	case GType_DarkSide:
+		menu = new DarkSideOptionsMenu(vm);
+		break;
+	case GType_WorldOfXeen:
+		menu = new WorldOptionsMenu(vm);
+		break;
+	default:
+		error("Unsupported game");
+		break;
+	}
+
+	menu->execute();
+	delete menu;
+}
+
+void OptionsMenu::execute() {
+	SpriteResource special("special.icn");
+	Screen &screen = *_vm->_screen;
+	EventsManager &events = *_vm->_events;
+	
+	File newBright("newbrigh.m");
+	_vm->_sound->playMusic(newBright);
+
+	screen._windows[28].setBounds(Common::Rect(72, 25, 248, 175));
+
+	Common::String title1, title2;
+	startup(title1, title2);
+
+	bool firstTime = true;
+	while (!_vm->shouldQuit()) {
+		setBackground();
+		events.setCursor(0);
+
+		if (firstTime) {
+			firstTime = false;
+			warning("TODO: Read existing save file");
+		}
+
+		for (;;) {
+			clearButtons();
+
+			showTitles1(title1);
+			showTitles2();
+		}
+	}
+}
+
+void OptionsMenu::showTitles1(const Common::String &title) {
+	SpriteResource titleSprites(title);
+	Screen &screen = *_vm->_screen;
+	EventsManager &events = *_vm->_events;
+
+	int frame = 0;
+	while (!_vm->shouldQuit() && !events.isKeyMousePressed()) {
+		events.updateGameCounter();
+
+		frame = frame % (_vm->getGameID() == GType_WorldOfXeen ? 5 : 10);
+		screen.restoreBackground();
+		titleSprites.draw(screen, 0);
+
+		while (events.timeElapsed() == 0)
+			events.pollEventsAndWait();
+	}
+}
+
+void OptionsMenu::showTitles2() {
+	Screen &screen = *_vm->_screen;
+	EventsManager &events = *_vm->_events;
+	SoundManager &sound = *_vm->_sound;
+
+	File voc("elect.voc");
+	SpriteResource titleSprites("title2b.raw");
+	SpriteResource kludgeSprites("kludge.int");
+	SpriteResource title2Sprites[8] = {
+		SpriteResource("title2b.int"), SpriteResource("title2c.int"),
+		SpriteResource("title2d.int"), SpriteResource("title2e.int"),
+		SpriteResource("title2f.int"), SpriteResource("title2g.int"),
+		SpriteResource("title2h.int"), SpriteResource("title2i.int"),
+	};
+
+	kludgeSprites.draw(screen, 0);
+	screen.saveBackground();
+	sound.playSample(&voc, 0);
+
+	for (int i = 0; i < 30 && !_vm->shouldQuit(); ++i) {
+		events.updateGameCounter();
+		screen.restoreBackground();
+		title2Sprites[i / 4].draw(screen, i % 4);
+		screen._windows[0].update();
+
+		if (i == 19)
+			sound.playSample(nullptr, 0);
+
+		while (!_vm->shouldQuit() && events.timeElapsed() < 2)
+			events.pollEventsAndWait();
+	}
+
+	screen.restoreBackground();
+	screen._windows[0].update();
+}
+
+/*------------------------------------------------------------------------*/
+
+void CloudsOptionsMenu::startup(Common::String &title1, Common::String &title2) {
+	title1 = "title1.int";
+	title2 = "title1a.int";
+}
+
+/**
+* Draws the scroll in the background
+*/
+void Dialog::doScroll(bool drawFlag, bool doFade) {
+	Screen &screen = *_vm->_screen;
+	EventsManager &events = *_vm->_events;
+	const int SCROLL_L[8] = { 29, 23, 15, 251, 245, 233, 207, 185 };
+	const int SCROLL_R[8] = { 165, 171, 198, 218, 228, 245, 264, 281 };
+
+	saveButtons();
+	clearButtons();
+	screen.saveBackground();
+
+	// Load hand vga files
+	SpriteResource *hand[16];
+	for (int i = 0; i < 16; ++i) {
+		Common::String name = Common::String::format("hand%02u.vga");
+		hand[i] = new SpriteResource(name);
+	}
+
+	// Load marb vga files
+	SpriteResource *marb[5];
+	for (int i = 1; i < 5; ++i) {
+		Common::String name = Common::String::format("marb%02u.vga");
+		marb[i] = new SpriteResource(name);
+	}
+
+	if (drawFlag) {
+		for (int i = 22; i > 0; --i) {
+			events.updateGameCounter();
+			screen.restoreBackground();
+
+			if (i > 0 && i <= 14) {
+				hand[i - 1]->draw(screen, 0);
+			} else {
+				// TODO: Check '800h'.. horizontal reverse maybe?
+				hand[14]->draw(screen, 0, Common::Point(SCROLL_L[i - 14], 0));
+				marb[15]->draw(screen, 0, Common::Point(SCROLL_R[i - 14], 0));
+			}
+
+			if (i <= 20) {
+				marb[i / 5]->draw(screen, i % 5);
+			}
+
+			while (!_vm->shouldQuit() && _vm->_events->timeElapsed() == 0)
+				_vm->_events->pollEventsAndWait();
+
+			screen._windows[0].update();
+			if (i == 0 && doFade)
+				screen.fadeIn(2);
+		}
+	} else {
+		for (int i = 0; i < 22 && !events.isKeyMousePressed(); ++i) {
+			events.updateGameCounter();
+			screen.restoreBackground();
+
+			if (i < 14) {
+				hand[i]->draw(screen, 0);
+			}
+			else {
+				// TODO: Check '800h'.. horizontal reverse maybe?
+				hand[14]->draw(screen, 0, Common::Point(SCROLL_L[i - 7], 0));
+				marb[15]->draw(screen, 0, Common::Point(SCROLL_R[i - 7], 0));
+			}
+
+			if (i < 20) {
+				marb[i / 5]->draw(screen, i % 5);
+			}
+
+			while (!_vm->shouldQuit() && _vm->_events->timeElapsed() == 0)
+				_vm->_events->pollEventsAndWait();
+
+			screen._windows[0].update();
+			if (i == 0 && doFade)
+				screen.fadeIn(2);
+		}
+	}
+
+	if (drawFlag) {
+		hand[0]->draw(screen, 0);
+		marb[0]->draw(screen, 0);
+	} else {
+		screen.restoreBackground();
+	}
+
+	screen._windows[0].update();
+	restoreButtons();
+
+	// Free resources
+	for (int i = 1; i < 5; ++i)
+		delete marb[i];
+	for (int i = 0; i < 16; ++i)
+		delete hand[i];
+}
+
+/*------------------------------------------------------------------------*/
+
+void DarkSideOptionsMenu::startup(Common::String &title1, Common::String &title2) {
+	title1 = "title2.int";
+	title2 = "title2a.int";
+}
+
+/**
+* Draws the scroll in the background
+*/
+void DarkSideOptionsMenu::doScroll(bool drawFlag, bool doFade) {
+	if (doFade) {
+		_vm->_screen->fadeIn(2);
+	}
+}
+
+void WorldOptionsMenu::startup(Common::String &title1, Common::String &title2) {
+	title1 = "world.int";
+	title2 = "start.icn";
+
+	Screen &screen = *_vm->_screen;
+	screen.fadeOut(4);
+	screen.loadPalette("dark.pal");
+	screen.fadeIn(0x81);
+	_vm->_events->clearEvents();
+}
+
+void WorldOptionsMenu::setBackground() {
+	Screen &screen = *_vm->_screen;
+	screen.loadBackground("world.raw");
+	screen.saveBackground();
+	screen.fadeIn(4);	
+}
+
+} // End of namespace Xeen
diff --git a/engines/xeen/menus.h b/engines/xeen/menus.h
new file mode 100644
index 0000000..497c193
--- /dev/null
+++ b/engines/xeen/menus.h
@@ -0,0 +1,106 @@
+/* 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_MENUS_H
+#define XEEN_MENUS_H
+
+#include "common/array.h"
+#include "common/stack.h"
+#include "common/rect.h"
+#include "xeen/xeen.h"
+
+namespace Xeen {
+
+class DialogButton {
+public:
+	Common::Rect _bounds;
+	int _d;
+	int _i;
+};
+
+class Dialog {
+private:
+	Common::Array<DialogButton> _buttons;
+	Common::Stack< Common::Array<DialogButton> > _savedButtons;
+protected:
+	XeenEngine *_vm;
+
+	virtual void doScroll(bool drawFlag, bool doFade) = 0;
+public:
+	Dialog(XeenEngine *vm): _vm(vm) {}
+
+	void saveButtons();
+
+	void clearButtons();
+
+	void restoreButtons();
+};
+
+class OptionsMenu: public Dialog {
+private:
+	void execute();
+protected:
+	OptionsMenu(XeenEngine *vm) : Dialog(vm) {}
+protected:
+	virtual void startup(Common::String &title1, Common::String &title2);
+
+	virtual void setBackground() {}
+
+	virtual void showTitles1(const Common::String &title);
+
+	virtual void showTitles2();
+public:
+	static void show(XeenEngine *vm);
+};
+
+class CloudsOptionsMenu : public OptionsMenu {
+protected:
+	virtual void startup(Common::String &title1, Common::String &title2);
+
+	virtual void doScroll(bool drawFlag, bool doFade);
+public:
+	CloudsOptionsMenu(XeenEngine *vm) : OptionsMenu(vm) {}
+};
+
+class DarkSideOptionsMenu : public OptionsMenu {
+protected:
+	virtual void startup(Common::String &title1, Common::String &title2);
+
+	virtual void doScroll(bool drawFlag, bool doFade);
+public:
+	DarkSideOptionsMenu(XeenEngine *vm) : OptionsMenu(vm) {}
+};
+
+class WorldOptionsMenu : public DarkSideOptionsMenu {
+protected:
+	virtual void startup(Common::String &title1, Common::String &title2);
+
+	virtual void setBackground();
+
+	virtual void showTitles2() {}
+public:
+	WorldOptionsMenu(XeenEngine *vm) : DarkSideOptionsMenu(vm) {}
+};
+
+} // End of namespace Xeen
+
+#endif /* XEEN_MENUS_H */
diff --git a/engines/xeen/module.mk b/engines/xeen/module.mk
index aafe9b4..0dd15b9 100644
--- a/engines/xeen/module.mk
+++ b/engines/xeen/module.mk
@@ -7,6 +7,7 @@ MODULE_OBJS := \
 	debugger.o \
 	detection.o \
 	events.o \
+	menus.o \
 	resources.o \
 	screen.o \
 	sound.o \
diff --git a/engines/xeen/screen.cpp b/engines/xeen/screen.cpp
index b1275aa..f773ee5 100644
--- a/engines/xeen/screen.cpp
+++ b/engines/xeen/screen.cpp
@@ -38,6 +38,11 @@ Window::Window(Screen *screen, const Common::Rect &bounds, int a, int border,
 	_xLo(xLo), _ycL(ycL), _xHi(xHi), _ycH(ycH) {
 }
 
+void Window::update() {
+	// Window updates are not specifically necessary since all drawing 
+	// automatically gets added to the screen's dirty rect list
+}
+
 /*------------------------------------------------------------------------*/
 
 /**
diff --git a/engines/xeen/screen.h b/engines/xeen/screen.h
index 4178460..728140a 100644
--- a/engines/xeen/screen.h
+++ b/engines/xeen/screen.h
@@ -53,12 +53,15 @@ public:
 
 	Window(Screen *screen, const Common::Rect &bounds, int a, int border, 
 		int xLo, int ycL, int xHi, int ycH);
+
+	void setBounds(const Common::Rect &r) { _bounds = r; }
+
+	void update();
 };
 
 class Screen: public XSurface {
 private:
 	XeenEngine *_vm;
-	Common::Array<Window> _windows;
 	Common::List<Common::Rect> _dirtyRects;
 	byte _mainPalette[PALETTE_SIZE];
 	byte _tempPaltte[PALETTE_SIZE];
@@ -82,6 +85,8 @@ private:
 public:
 	virtual void addDirtyRect(const Common::Rect &r);
 public:
+	Common::Array<Window> _windows;
+public:
 	Screen(XeenEngine *vm);
 
 	void update();
@@ -104,9 +109,9 @@ public:
 
 	void fadeOut(int step);
 
-	void saveBackground(int slot);
+	void saveBackground(int slot = 0);
 
-	void restoreBackground(int slot);
+	void restoreBackground(int slot = 0);
 };
 
 } // End of namespace Xeen
diff --git a/engines/xeen/sound.h b/engines/xeen/sound.h
index b122fc1..73f5aa0 100644
--- a/engines/xeen/sound.h
+++ b/engines/xeen/sound.h
@@ -38,6 +38,10 @@ public:
 	void proc2(File &f);
 
 	void startMusic(int v1);
+
+	void playMusic(const File &f) {}
+
+	void playSample(const Common::SeekableReadStream *stream, int v2) {}
 };
 
 } // End of namespace Xeen
diff --git a/engines/xeen/xeen.cpp b/engines/xeen/xeen.cpp
index 5a29363..311e139 100644
--- a/engines/xeen/xeen.cpp
+++ b/engines/xeen/xeen.cpp
@@ -214,6 +214,8 @@ void XeenEngine::writeSavegameHeader(Common::OutSaveFile *out, XeenSavegameHeade
 }
 
 void XeenEngine::playGame() {
+	//showIntro();
+	
 }
 
 } // End of namespace Xeen


Commit: 9506635bad402d58886cc9a47512871b321a10a2
    https://github.com/scummvm/scummvm/commit/9506635bad402d58886cc9a47512871b321a10a2
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2014-12-30T22:50:24-10:00

Commit Message:
XEEN: Implemented Window functionality

Changed paths:
    engines/xeen/events.cpp
    engines/xeen/events.h
    engines/xeen/menus.cpp
    engines/xeen/menus.h
    engines/xeen/screen.cpp
    engines/xeen/screen.h
    engines/xeen/xeen.cpp
    engines/xeen/xeen.h



diff --git a/engines/xeen/events.cpp b/engines/xeen/events.cpp
index 29dde3a..54cc843 100644
--- a/engines/xeen/events.cpp
+++ b/engines/xeen/events.cpp
@@ -176,4 +176,9 @@ void EventsManager::nextFrame() {
 	_vm->_screen->update();
 }
 
+/*------------------------------------------------------------------------*/
+
+GameEvent::GameEvent() {
+}
+
 } // End of namespace Xeen
diff --git a/engines/xeen/events.h b/engines/xeen/events.h
index 3590267..bf41bc9 100644
--- a/engines/xeen/events.h
+++ b/engines/xeen/events.h
@@ -79,6 +79,11 @@ public:
 	uint32 timeElapsed();
 };
 
+class GameEvent {
+public:
+	GameEvent();
+};
+
 } // End of namespace Xeen
 
 #endif /* XEEN_EVENTS_H */
diff --git a/engines/xeen/menus.cpp b/engines/xeen/menus.cpp
index 4ddb85a..da272b6 100644
--- a/engines/xeen/menus.cpp
+++ b/engines/xeen/menus.cpp
@@ -43,6 +43,10 @@ void Dialog::restoreButtons() {
 	_buttons = _savedButtons.pop();
 }
 
+void Dialog::addButton(const Common::Rect &bounds, char c, SpriteResource *sprites, bool d) {
+	_buttons.push_back(DialogButton(bounds, c, sprites, d));
+}
+
 /*------------------------------------------------------------------------*/
 
 void OptionsMenu::show(XeenEngine *vm) {
@@ -77,8 +81,9 @@ void OptionsMenu::execute() {
 
 	screen._windows[28].setBounds(Common::Rect(72, 25, 248, 175));
 
-	Common::String title1, title2;
-	startup(title1, title2);
+	Common::String title1, buttonsName;
+	startup(title1, buttonsName);
+	SpriteResource buttonSprites(buttonsName);
 
 	bool firstTime = true;
 	while (!_vm->shouldQuit()) {
@@ -91,10 +96,17 @@ void OptionsMenu::execute() {
 		}
 
 		for (;;) {
-			clearButtons();
-
 			showTitles1(title1);
 			showTitles2();
+
+		reopen:
+			clearButtons();
+			setupButtons(&buttonSprites);
+			openWindow();
+
+			while (!_vm->shouldQuit()) {
+				
+			}
 		}
 	}
 }
@@ -108,9 +120,9 @@ void OptionsMenu::showTitles1(const Common::String &title) {
 	while (!_vm->shouldQuit() && !events.isKeyMousePressed()) {
 		events.updateGameCounter();
 
-		frame = frame % (_vm->getGameID() == GType_WorldOfXeen ? 5 : 10);
+		frame = ++frame % (_vm->getGameID() == GType_WorldOfXeen ? 5 : 10);
 		screen.restoreBackground();
-		titleSprites.draw(screen, 0);
+		titleSprites.draw(screen, frame);
 
 		while (events.timeElapsed() == 0)
 			events.pollEventsAndWait();
@@ -153,6 +165,20 @@ void OptionsMenu::showTitles2() {
 	screen._windows[0].update();
 }
 
+void OptionsMenu::setupButtons(SpriteResource *buttons) {
+	addButton(Common::Rect(124, 87, 124 + 53, 87 + 10), 'S', buttons, true);
+	addButton(Common::Rect(126, 98, 126 + 47, 98 + 10), 'L', buttons, true);
+	addButton(Common::Rect(91, 110, 91 + 118, 110 + 10), 'C', buttons, true);
+	addButton(Common::Rect(85, 121, 85 + 131, 121 + 10), 'O', buttons, true);
+}
+
+void WorldOptionsMenu::setupButtons(SpriteResource *buttons) {
+	addButton(Common::Rect(93, 53, 93 + 134, 53 + 20), 'S', buttons, false);
+	addButton(Common::Rect(93, 78, 93 + 134, 78 + 20), 'L', buttons, false);
+	addButton(Common::Rect(93, 103, 93 + 134, 103 + 20), 'C', buttons, false);
+	addButton(Common::Rect(93, 128, 93 + 134, 128 + 20), 'O', buttons, false);
+}
+
 /*------------------------------------------------------------------------*/
 
 void CloudsOptionsMenu::startup(Common::String &title1, Common::String &title2) {
@@ -289,4 +315,9 @@ void WorldOptionsMenu::setBackground() {
 	screen.fadeIn(4);	
 }
 
+void WorldOptionsMenu::openWindow() {
+	_vm->_screen->_windows[28].open();
+}
+
+
 } // End of namespace Xeen
diff --git a/engines/xeen/menus.h b/engines/xeen/menus.h
index 497c193..774c7cf 100644
--- a/engines/xeen/menus.h
+++ b/engines/xeen/menus.h
@@ -33,8 +33,14 @@ namespace Xeen {
 class DialogButton {
 public:
 	Common::Rect _bounds;
-	int _d;
-	int _i;
+	SpriteResource *_sprites;
+	char _c;
+	bool _d;
+
+	DialogButton(const Common::Rect &bounds, char c, SpriteResource *sprites, bool d) :
+		_bounds(bounds), _c(c), _sprites(sprites), _d(d) {}
+
+	DialogButton() : _c('\0'), _sprites(nullptr), _d(false) {}
 };
 
 class Dialog {
@@ -53,6 +59,8 @@ public:
 	void clearButtons();
 
 	void restoreButtons();
+
+	void addButton(const Common::Rect &bounds, char c, SpriteResource *sprites, bool d);
 };
 
 class OptionsMenu: public Dialog {
@@ -68,6 +76,10 @@ protected:
 	virtual void showTitles1(const Common::String &title);
 
 	virtual void showTitles2();
+
+	virtual void setupButtons(SpriteResource *buttons);
+
+	virtual void openWindow() {}
 public:
 	static void show(XeenEngine *vm);
 };
@@ -97,6 +109,10 @@ protected:
 	virtual void setBackground();
 
 	virtual void showTitles2() {}
+
+	virtual void setupButtons(SpriteResource *buttons);
+
+	virtual void openWindow();
 public:
 	WorldOptionsMenu(XeenEngine *vm) : DarkSideOptionsMenu(vm) {}
 };
diff --git a/engines/xeen/screen.cpp b/engines/xeen/screen.cpp
index f773ee5..1f8e50c 100644
--- a/engines/xeen/screen.cpp
+++ b/engines/xeen/screen.cpp
@@ -22,25 +22,76 @@
 
 #include "common/system.h"
 #include "graphics/palette.h"
+#include "graphics/surface.h"
 #include "xeen/screen.h"
 #include "xeen/resources.h"
 #include "xeen/xeen.h"
 
 namespace Xeen {
 
-Window::Window() : _screen(nullptr), _enabled(false), _a(0), _border(0),
+Window::Window() : _vm(nullptr), _enabled(false), _a(0), _border(0),
 	_xLo(0), _xHi(0), _ycL(0), _ycH(0) {
 }
 
-Window::Window(Screen *screen, const Common::Rect &bounds, int a, int border, 
+Window::Window(XeenEngine *vm, const Common::Rect &bounds, int a, int border, 
 		int xLo, int ycL, int xHi, int ycH): 
-	_screen(screen), _enabled(false), _bounds(bounds), _a(a), _border(border), 
-	_xLo(xLo), _ycL(ycL), _xHi(xHi), _ycH(ycH) {
+		_vm(vm), _enabled(false), _a(a), _border(border), 
+		_xLo(xLo), _ycL(ycL), _xHi(xHi), _ycH(ycH) {
+	setBounds(bounds);
 }
 
+void Window::setBounds(const Common::Rect &r) {
+	_bounds = r;
+	_innerBounds = r;
+	_innerBounds.grow(-_border);
+}
+
+void Window::open() {
+	if (!_enabled) {
+		_vm->_screen->_windowStack.push_back(this);
+		open2();
+	}
+
+	if (_vm->_mode == MODE_9) {
+		warning("TODO: copyFileToMemory");
+	}
+}
+
+void Window::open2() {
+	create(_bounds.width(), _bounds.height());
+	copyRectToSurface(*_vm->_screen, 0, 0, _bounds);
+	_dirtyRects.push(_bounds);
+}
+
+void Window::close() {
+	if (_enabled) {
+		// Update any remaining pending changes to the screen and free
+		// the window's internal surface storage
+		update();
+		free();
+
+		// Remove the window from the stack and flag it as now disabled
+		for (uint i = 0; i < _vm->_screen->_windowStack.size(); ++i) {
+			if (_vm->_screen->_windowStack[i] == this)
+				_vm->_screen->_windowStack.remove_at(i);
+		}
+
+		_enabled = false;
+	}
+
+	if (_vm->_mode == MODE_9) {
+		warning("TODO: copyFileToMemory");
+	}
+}
+
+/**
+ * Pushes any pending changes for the window to the screen
+ */
 void Window::update() {
-	// Window updates are not specifically necessary since all drawing 
-	// automatically gets added to the screen's dirty rect list
+	while (!_dirtyRects.empty()) {
+		Common::Rect r = _dirtyRects.pop();
+		blitTo(*_vm->_screen, Common::Point(_bounds.left, _bounds.top));
+	}
 }
 
 /*------------------------------------------------------------------------*/
@@ -56,50 +107,56 @@ Screen::Screen(XeenEngine *vm) : _vm(vm) {
 
 void Screen::setupWindows() {
 	Window windows[40] = {
-		Window(this, Common::Rect(0, 0, 320, 200), 0, 0, 0, 0, 320, 200),
-		Window(this, Common::Rect(237, 9, 317, 74), 0, 0, 237, 12, 307, 68),
-		Window(this, Common::Rect(225, 1, 319, 73), 1, 8, 225, 1, 319, 73),
-		Window(this, Common::Rect(0, 0, 230, 149), 0, 0, 9, 8, 216, 140),
-		Window(this, Common::Rect(235, 148, 309, 189), 2, 8, 0, 0, 0, 0),
-		Window(this, Common::Rect(70, 20, 250, 183), 3, 8, 80, 38, 240, 166),
-		Window(this, Common::Rect(52, 149, 268, 197), 4, 8, 0, 0, 0, 0),
-		Window(this, Common::Rect(108, 0, 200, 200), 5, 0, 0, 0, 0, 0),
-		Window(this, Common::Rect(232, 9, 312, 74), 0, 0, 0, 0, 0, 0),
-		Window(this, Common::Rect(103, 156, 217, 186), 6, 8, 0, 0, 0, 0),
-		Window(this, Common::Rect(226, 0, 319, 146), 7, 8, 0, 0, 0, 0),
-		Window(this, Common::Rect(8, 8, 224, 140), 8, 8, 8, 8, 224, 200),
-		Window(this, Common::Rect(0, 143, 320, 199), 9, 8, 0, 0, 0, 0),
-		Window(this, Common::Rect(50, 103, 266, 139), 10, 8, 0, 0, 0, 0),
-		Window(this, Common::Rect(0, 7, 320, 138), 11, 8, 0, 0, 0, 0),
-		Window(this, Common::Rect(50, 71, 182, 129), 12, 8, 0, 0, 0, 0),
-		Window(this, Common::Rect(228, 106, 319, 146), 13, 8, 0, 0, 0, 0),
-		Window(this, Common::Rect(20, 142, 290, 199), 14, 8, 0, 0, 0, 0),
-		Window(this, Common::Rect(0, 20, 320, 180), 15, 8, 0, 0, 0, 0),
-		Window(this, Common::Rect(231, 48, 317, 141), 16, 8, 0, 0, 0, 0),
-		Window(this, Common::Rect(72, 37, 248, 163), 17, 8, 0, 0, 0, 0),
-		Window(this, Common::Rect(99, 59, 237, 141), 18, 8, 99, 59, 237, 0),
-		Window(this, Common::Rect(65, 23, 250, 163), 19, 8, 75, 36, 245, 141),
-		Window(this, Common::Rect(80, 28, 256, 148), 20, 8, 80, 28, 256, 172),
-		Window(this, Common::Rect(0, 0, 320, 146), 21, 8, 0, 0, 320, 148),
-		Window(this, Common::Rect(27, 6, 207, 142), 22, 8, 0, 0, 0, 146),
-		Window(this, Common::Rect(15, 15, 161, 91), 23, 8, 0, 0, 0, 0),
-		Window(this, Common::Rect(90, 45, 220, 157), 24, 8, 0, 0, 0, 0),
-		Window(this, Common::Rect(0, 0, 320, 200), 25, 8, 0, 0, 0, 0),
-		Window(this, Common::Rect(0, 101, 320, 146), 26, 8, 0, 101, 320, 0),
-		Window(this, Common::Rect(0, 0, 320, 108), 27, 8, 0, 0, 0, 45),
-		Window(this, Common::Rect(50, 112, 266, 148), 28, 8, 0, 0, 0, 0),
-		Window(this, Common::Rect(12, 11, 164, 94), 0, 0, 0, 0, 52, 0),
-		Window(this, Common::Rect(8, 147, 224, 192), 0, 8, 0, 0, 0, 94),
-		Window(this, Common::Rect(232, 74, 312, 138), 29, 8, 0, 0, 0, 0),
-		Window(this, Common::Rect(226, 26, 319, 146), 30, 8, 0, 0, 0, 0),
-		Window(this, Common::Rect(225, 74, 319, 154), 31, 8, 0, 0, 0, 0),
-		Window(this, Common::Rect(27, 6, 195, 142), 0, 8, 0, 0, 0, 0),
-		Window(this, Common::Rect(225, 140, 319, 199), 0, 8, 0, 0, 0, 0)
+		Window(_vm, Common::Rect(0, 0, 320, 200), 0, 0, 0, 0, 320, 200),
+		Window(_vm, Common::Rect(237, 9, 317, 74), 0, 0, 237, 12, 307, 68),
+		Window(_vm, Common::Rect(225, 1, 319, 73), 1, 8, 225, 1, 319, 73),
+		Window(_vm, Common::Rect(0, 0, 230, 149), 0, 0, 9, 8, 216, 140),
+		Window(_vm, Common::Rect(235, 148, 309, 189), 2, 8, 0, 0, 0, 0),
+		Window(_vm, Common::Rect(70, 20, 250, 183), 3, 8, 80, 38, 240, 166),
+		Window(_vm, Common::Rect(52, 149, 268, 197), 4, 8, 0, 0, 0, 0),
+		Window(_vm, Common::Rect(108, 0, 200, 200), 5, 0, 0, 0, 0, 0),
+		Window(_vm, Common::Rect(232, 9, 312, 74), 0, 0, 0, 0, 0, 0),
+		Window(_vm, Common::Rect(103, 156, 217, 186), 6, 8, 0, 0, 0, 0),
+		Window(_vm, Common::Rect(226, 0, 319, 146), 7, 8, 0, 0, 0, 0),
+		Window(_vm, Common::Rect(8, 8, 224, 140), 8, 8, 8, 8, 224, 200),
+		Window(_vm, Common::Rect(0, 143, 320, 199), 9, 8, 0, 0, 0, 0),
+		Window(_vm, Common::Rect(50, 103, 266, 139), 10, 8, 0, 0, 0, 0),
+		Window(_vm, Common::Rect(0, 7, 320, 138), 11, 8, 0, 0, 0, 0),
+		Window(_vm, Common::Rect(50, 71, 182, 129), 12, 8, 0, 0, 0, 0),
+		Window(_vm, Common::Rect(228, 106, 319, 146), 13, 8, 0, 0, 0, 0),
+		Window(_vm, Common::Rect(20, 142, 290, 199), 14, 8, 0, 0, 0, 0),
+		Window(_vm, Common::Rect(0, 20, 320, 180), 15, 8, 0, 0, 0, 0),
+		Window(_vm, Common::Rect(231, 48, 317, 141), 16, 8, 0, 0, 0, 0),
+		Window(_vm, Common::Rect(72, 37, 248, 163), 17, 8, 0, 0, 0, 0),
+		Window(_vm, Common::Rect(99, 59, 237, 141), 18, 8, 99, 59, 237, 0),
+		Window(_vm, Common::Rect(65, 23, 250, 163), 19, 8, 75, 36, 245, 141),
+		Window(_vm, Common::Rect(80, 28, 256, 148), 20, 8, 80, 28, 256, 172),
+		Window(_vm, Common::Rect(0, 0, 320, 146), 21, 8, 0, 0, 320, 148),
+		Window(_vm, Common::Rect(27, 6, 207, 142), 22, 8, 0, 0, 0, 146),
+		Window(_vm, Common::Rect(15, 15, 161, 91), 23, 8, 0, 0, 0, 0),
+		Window(_vm, Common::Rect(90, 45, 220, 157), 24, 8, 0, 0, 0, 0),
+		Window(_vm, Common::Rect(0, 0, 320, 200), 25, 8, 0, 0, 0, 0),
+		Window(_vm, Common::Rect(0, 101, 320, 146), 26, 8, 0, 101, 320, 0),
+		Window(_vm, Common::Rect(0, 0, 320, 108), 27, 8, 0, 0, 0, 45),
+		Window(_vm, Common::Rect(50, 112, 266, 148), 28, 8, 0, 0, 0, 0),
+		Window(_vm, Common::Rect(12, 11, 164, 94), 0, 0, 0, 0, 52, 0),
+		Window(_vm, Common::Rect(8, 147, 224, 192), 0, 8, 0, 0, 0, 94),
+		Window(_vm, Common::Rect(232, 74, 312, 138), 29, 8, 0, 0, 0, 0),
+		Window(_vm, Common::Rect(226, 26, 319, 146), 30, 8, 0, 0, 0, 0),
+		Window(_vm, Common::Rect(225, 74, 319, 154), 31, 8, 0, 0, 0, 0),
+		Window(_vm, Common::Rect(27, 6, 195, 142), 0, 8, 0, 0, 0, 0),
+		Window(_vm, Common::Rect(225, 140, 319, 199), 0, 8, 0, 0, 0, 0)
 	};
 
 	_windows = Common::Array<Window>(windows, 40);
 }
 
+void Screen::closeWindows() {
+	for (int i = (int)_windowStack.size() - 1; i >= 0; --i)
+		_windowStack[i]->close();
+	assert(_windowStack.size() == 0);
+}
+
 void Screen::update() {
 	// Merge the dirty rects
 	mergeDirtyRects();
diff --git a/engines/xeen/screen.h b/engines/xeen/screen.h
index 728140a..b132e33 100644
--- a/engines/xeen/screen.h
+++ b/engines/xeen/screen.h
@@ -26,6 +26,7 @@
 #include "common/scummsys.h"
 #include "common/system.h"
 #include "common/array.h"
+#include "common/queue.h"
 #include "common/rect.h"
 #include "xeen/xsurface.h"
 
@@ -39,22 +40,30 @@ namespace Xeen {
 class XeenEngine;
 class Screen;
 
-class Window {
+class Window: public XSurface {
 private:
-	Screen *_screen;
+	XeenEngine *_vm;
 	Common::Rect _bounds;
+	Common::Rect _innerBounds;
 	int _a;
 	int _border;
 	int _xLo, _xHi;
 	int _ycL, _ycH;
 	bool _enabled;
+	Common::Queue<Common::Rect> _dirtyRects;
+
+	void open2();
 public:
 	Window();
 
-	Window(Screen *screen, const Common::Rect &bounds, int a, int border, 
+	Window(XeenEngine *vm, const Common::Rect &bounds, int a, int border,
 		int xLo, int ycL, int xHi, int ycH);
 
-	void setBounds(const Common::Rect &r) { _bounds = r; }
+	void setBounds(const Common::Rect &r);
+
+	void open();
+
+	void close();
 
 	void update();
 };
@@ -86,9 +95,13 @@ public:
 	virtual void addDirtyRect(const Common::Rect &r);
 public:
 	Common::Array<Window> _windows;
+
+	Common::Array<Window *> _windowStack;
 public:
 	Screen(XeenEngine *vm);
 
+	void closeWindows();
+
 	void update();
 
 	void loadPalette(const Common::String &name);
diff --git a/engines/xeen/xeen.cpp b/engines/xeen/xeen.cpp
index 311e139..505d9bd 100644
--- a/engines/xeen/xeen.cpp
+++ b/engines/xeen/xeen.cpp
@@ -38,6 +38,7 @@ XeenEngine::XeenEngine(OSystem *syst, const XeenGameDescription *gameDesc)
 	_events = nullptr;
 	_screen = nullptr;
 	_sound = nullptr;
+	_eventData = nullptr;
 }
 
 XeenEngine::~XeenEngine() {
@@ -45,6 +46,7 @@ XeenEngine::~XeenEngine() {
 	delete _events;
 	delete _screen;
 	delete _sound;
+	delete _eventData;
 }
 
 void XeenEngine::initialize() {
@@ -61,6 +63,9 @@ void XeenEngine::initialize() {
 	_screen = new Screen(this);
 	_sound = new SoundManager(this);
 
+	File f("029.obj");
+	_eventData = f.readStream(f.size());
+
 	// Set graphics mode
 	initGraphics(320, 200, false);
 
diff --git a/engines/xeen/xeen.h b/engines/xeen/xeen.h
index df53b78..1b99a85 100644
--- a/engines/xeen/xeen.h
+++ b/engines/xeen/xeen.h
@@ -64,6 +64,11 @@ enum XeenDebugChannels {
 	kDebugSound     = 1 << 3
 };
 
+enum Mode {
+	MODE_0 = 0,
+	MODE_9 = 9
+};
+
 struct XeenGameDescription;
 
 #define XEEN_SAVEGAME_VERSION 1
@@ -110,6 +115,9 @@ public:
 	EventsManager *_events;
 	Screen *_screen;
 	SoundManager *_sound;
+	Mode _mode;
+	GameEvent _gameEvent;
+	Common::SeekableReadStream *_eventData;
 public:
 	XeenEngine(OSystem *syst, const XeenGameDescription *gameDesc);
 	virtual ~XeenEngine();


Commit: 5c88d2cc42d9b6124f552464b9c02e800f3956df
    https://github.com/scummvm/scummvm/commit/5c88d2cc42d9b6124f552464b9c02e800f3956df
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2014-12-31T11:12:18-10:00

Commit Message:
XEEN: Implement window framing code and dialog event handling

Changed paths:
  A engines/xeen/resdata.cpp
  A engines/xeen/resdata.h
    engines/xeen/events.cpp
    engines/xeen/events.h
    engines/xeen/menus.cpp
    engines/xeen/menus.h
    engines/xeen/module.mk
    engines/xeen/screen.cpp
    engines/xeen/screen.h
    engines/xeen/xsurface.cpp
    engines/xeen/xsurface.h



diff --git a/engines/xeen/events.cpp b/engines/xeen/events.cpp
index 54cc843..fd0871e 100644
--- a/engines/xeen/events.cpp
+++ b/engines/xeen/events.cpp
@@ -94,6 +94,9 @@ void EventsManager::pollEvents() {
 		case Common::EVENT_KEYDOWN:
 			_keyCode = event.kbd.keycode;
 			break;
+		case Common::EVENT_MOUSEMOVE:
+			_mousePos = event.mouse;
+			break;
 		case Common::EVENT_LBUTTONDOWN:
 			_leftButton = true;
 			return;
@@ -168,6 +171,16 @@ uint32 EventsManager::timeElapsed() {
 	return _frameCounter - _gameCounter;
 }
 
+bool EventsManager::wait(uint numFrames, bool interruptable) {
+	while (!_vm->shouldQuit() && timeElapsed() < numFrames) {
+		pollEventsAndWait();
+		if (interruptable && (_leftButton || _rightButton || isKeyPending()))
+			return true;
+	}
+
+	return false;
+}
+
 /**
  * Handles moving to the next game frame
  */
diff --git a/engines/xeen/events.h b/engines/xeen/events.h
index bf41bc9..6183b75 100644
--- a/engines/xeen/events.h
+++ b/engines/xeen/events.h
@@ -41,11 +41,13 @@ private:
 	uint32 _gameCounter;
 	uint32 _priorGameCounterTime;
 	Common::KeyCode _keyCode;
-	bool _leftButton, _rightButton;
 	FramesResource _sprites;
 
 	void nextFrame();
 public:
+	bool _leftButton, _rightButton;
+	Common::Point _mousePos;
+public:
 	EventsManager(XeenEngine *vm);
 
 	~EventsManager();
@@ -77,6 +79,8 @@ public:
 	void updateGameCounter();
 
 	uint32 timeElapsed();
+
+	bool wait(uint numFrames, bool interruptable = false);
 };
 
 class GameEvent {
diff --git a/engines/xeen/menus.cpp b/engines/xeen/menus.cpp
index da272b6..0a7b030 100644
--- a/engines/xeen/menus.cpp
+++ b/engines/xeen/menus.cpp
@@ -47,6 +47,39 @@ void Dialog::addButton(const Common::Rect &bounds, char c, SpriteResource *sprit
 	_buttons.push_back(DialogButton(bounds, c, sprites, d));
 }
 
+void Dialog::checkEvents() {
+	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)) {
+				_key = _buttons[i]._c;
+				return;
+			}
+		}
+	} else if (events.isKeyPending()) {
+		Common::KeyState keyState;
+		events.getKey(keyState);
+		if (keyState.ascii >= 32 && keyState.ascii <= 127) {
+			_key = keyState.ascii;
+			return;
+		}
+	}
+}
+
+/*------------------------------------------------------------------------*/
+
+void SettingsBaseDialog::showContents(SpriteResource &title1, bool waitFlag) {
+	while (!_vm->shouldQuit() && _key == Common::KEYCODE_INVALID) {
+		checkEvents();
+	}
+}
+
 /*------------------------------------------------------------------------*/
 
 void OptionsMenu::show(XeenEngine *vm) {
@@ -81,9 +114,9 @@ void OptionsMenu::execute() {
 
 	screen._windows[28].setBounds(Common::Rect(72, 25, 248, 175));
 
-	Common::String title1, buttonsName;
-	startup(title1, buttonsName);
-	SpriteResource buttonSprites(buttonsName);
+	Common::String title1, title2;
+	startup(title1, title2);
+	SpriteResource title1Sprites(title1), title2Sprites(title2);
 
 	bool firstTime = true;
 	while (!_vm->shouldQuit()) {
@@ -96,33 +129,33 @@ void OptionsMenu::execute() {
 		}
 
 		for (;;) {
-			showTitles1(title1);
+			showTitles1(title1Sprites);
 			showTitles2();
 
 		reopen:
 			clearButtons();
-			setupButtons(&buttonSprites);
+			setupButtons(&title2Sprites);
 			openWindow();
 
 			while (!_vm->shouldQuit()) {
+				showContents(title1Sprites, true);
 				
 			}
 		}
 	}
 }
 
-void OptionsMenu::showTitles1(const Common::String &title) {
-	SpriteResource titleSprites(title);
+void OptionsMenu::showTitles1(SpriteResource &sprites) {
 	Screen &screen = *_vm->_screen;
 	EventsManager &events = *_vm->_events;
 
-	int frame = 0;
+	int frameNum = 0;
 	while (!_vm->shouldQuit() && !events.isKeyMousePressed()) {
 		events.updateGameCounter();
 
-		frame = ++frame % (_vm->getGameID() == GType_WorldOfXeen ? 5 : 10);
+		frameNum = ++frameNum % (_vm->getGameID() == GType_WorldOfXeen ? 5 : 10);
 		screen.restoreBackground();
-		titleSprites.draw(screen, frame);
+		sprites.draw(screen, frameNum);
 
 		while (events.timeElapsed() == 0)
 			events.pollEventsAndWait();
@@ -319,5 +352,32 @@ void WorldOptionsMenu::openWindow() {
 	_vm->_screen->_windows[28].open();
 }
 
+void WorldOptionsMenu::showContents(SpriteResource &title1, bool waitFlag) {
+	Screen &screen = *_vm->_screen;
+	EventsManager &events = *_vm->_events;
+	
+	events.updateGameCounter();
+	_bgFrame = ++_bgFrame % 5;
+	title1.draw(screen._windows[0], 0);
+	screen._windows[28].frame();
+
+	screen._windows[28].writeString("\r\x01\x03c\fdMight and Magic Options\n"
+		"World of Xeen\x02\n"
+		"117Copyright (c) 1993 NWC, Inc.\n"
+		"All Rights Reserved\x01");
+
+	for (uint btnIndex = 0; btnIndex < _buttons.size(); ++btnIndex) {
+		DialogButton &btn = _buttons[btnIndex];
+		if (btn._d) {
+			btn._sprites->draw(screen._windows[0], btnIndex * 2,
+				Common::Point(btn._bounds.left, btn._bounds.top));
+		}
+	}
+
+	if (waitFlag) {
+		screen._windows[0].update();
+		SettingsBaseDialog::showContents(title1, true);
+	}
+}
 
 } // End of namespace Xeen
diff --git a/engines/xeen/menus.h b/engines/xeen/menus.h
index 774c7cf..07a7bb7 100644
--- a/engines/xeen/menus.h
+++ b/engines/xeen/menus.h
@@ -45,14 +45,17 @@ public:
 
 class Dialog {
 private:
-	Common::Array<DialogButton> _buttons;
 	Common::Stack< Common::Array<DialogButton> > _savedButtons;
 protected:
 	XeenEngine *_vm;
+	Common::Array<DialogButton> _buttons;
+	char _key;
 
 	virtual void doScroll(bool drawFlag, bool doFade) = 0;
+
+	void checkEvents();
 public:
-	Dialog(XeenEngine *vm): _vm(vm) {}
+	Dialog(XeenEngine *vm): _vm(vm), _key('\0') {}
 
 	void saveButtons();
 
@@ -63,17 +66,23 @@ public:
 	void addButton(const Common::Rect &bounds, char c, SpriteResource *sprites, bool d);
 };
 
-class OptionsMenu: public Dialog {
+class SettingsBaseDialog : public Dialog {
+protected:
+	virtual void showContents(SpriteResource &title1, bool mode);
+public:
+	SettingsBaseDialog(XeenEngine *vm) : Dialog(vm) {}
+};
+class OptionsMenu : public SettingsBaseDialog {
 private:
 	void execute();
 protected:
-	OptionsMenu(XeenEngine *vm) : Dialog(vm) {}
+	OptionsMenu(XeenEngine *vm) : SettingsBaseDialog(vm) {}
 protected:
 	virtual void startup(Common::String &title1, Common::String &title2);
 
 	virtual void setBackground() {}
 
-	virtual void showTitles1(const Common::String &title);
+	virtual void showTitles1(SpriteResource &sprites);
 
 	virtual void showTitles2();
 
@@ -103,6 +112,8 @@ public:
 };
 
 class WorldOptionsMenu : public DarkSideOptionsMenu {
+private:
+	int _bgFrame;
 protected:
 	virtual void startup(Common::String &title1, Common::String &title2);
 
@@ -113,8 +124,10 @@ protected:
 	virtual void setupButtons(SpriteResource *buttons);
 
 	virtual void openWindow();
+
+	virtual void showContents(SpriteResource &title1, bool mode);
 public:
-	WorldOptionsMenu(XeenEngine *vm) : DarkSideOptionsMenu(vm) {}
+	WorldOptionsMenu(XeenEngine *vm) : DarkSideOptionsMenu(vm), _bgFrame(0) {}
 };
 
 } // End of namespace Xeen
diff --git a/engines/xeen/module.mk b/engines/xeen/module.mk
index 0dd15b9..a410fbc 100644
--- a/engines/xeen/module.mk
+++ b/engines/xeen/module.mk
@@ -8,6 +8,7 @@ MODULE_OBJS := \
 	detection.o \
 	events.o \
 	menus.o \
+	resdata.o \
 	resources.o \
 	screen.o \
 	sound.o \
diff --git a/engines/xeen/resdata.cpp b/engines/xeen/resdata.cpp
new file mode 100644
index 0000000..44002c6
--- /dev/null
+++ b/engines/xeen/resdata.cpp
@@ -0,0 +1,151 @@
+/* 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/resdata.h"
+
+namespace Xeen {
+
+const byte SYMBOLS[20][64] = {
+	{ // 0
+		0x00, 0x00, 0xA8, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0x00, 0xA8, 0x9E, 0x9C, 0x9C, 0x9E, 0x9E, 0x9E,
+		0xAC, 0x9C, 0xA4, 0xAC, 0xAC, 0x9A, 0x9A, 0x9A, 0xAC, 0x9E, 0xAC, 0xA8, 0xA8, 0xA6, 0x97, 0x98,
+		0xAC, 0xA0, 0xAC, 0xAC, 0xA4, 0xA6, 0x98, 0x99, 0x00, 0xAC, 0xA0, 0xA0, 0xA8, 0xAC, 0x9A, 0x9A,
+		0x00, 0x00, 0xAC, 0xAC, 0xAC, 0xA4, 0x9B, 0x9A, 0x00, 0x00, 0x00, 0x00, 0xAC, 0xA0, 0x9B, 0x9B,
+	},
+	{ // 1
+		0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E,
+		0x99, 0x9A, 0x9A, 0x99, 0x99, 0x99, 0x9A, 0x99, 0x98, 0x98, 0x98, 0x97, 0x97, 0x97, 0x97, 0x97,
+		0x99, 0x98, 0x98, 0x99, 0x98, 0x98, 0x99, 0x99, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A,
+		0x9A, 0x9B, 0x9B, 0x9C, 0x9B, 0x9A, 0x9C, 0x9A, 0x9B, 0x9A, 0x99, 0x99, 0x99, 0x9A, 0x9A, 0x9B,
+	},
+	{ // 2
+		0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E,
+		0x99, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x99, 0x98, 0x98, 0x99, 0x98, 0x98, 0x97, 0x98, 0x98,
+		0x99, 0x98, 0x98, 0x98, 0x99, 0x99, 0x98, 0x99, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A,
+		0x9B, 0x9B, 0x9C, 0x9C, 0x9B, 0x9B, 0x9B, 0x9B, 0x99, 0x9A, 0x9B, 0x9B, 0x9A, 0x9A, 0x99, 0x9A,
+	},
+	{ // 3
+		0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E,
+		0x99, 0x9A, 0x9A, 0x9A, 0x99, 0x99, 0x99, 0x9A, 0x98, 0x98, 0x97, 0x97, 0x98, 0x98, 0x98, 0x98,
+		0x99, 0x99, 0x98, 0x99, 0x98, 0x98, 0x99, 0x99, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A,
+		0x9B, 0x9C, 0x9B, 0x9B, 0x9C, 0x9C, 0x9C, 0x9C, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x99, 0x99, 0x9A,
+	},
+	{ // 4
+		0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E,
+		0x9A, 0x9A, 0x9A, 0x99, 0x99, 0x99, 0x99, 0x9A, 0x97, 0x97, 0x97, 0x97, 0x97, 0x98, 0x98, 0x98,
+		0x99, 0x99, 0x98, 0x99, 0x99, 0x98, 0x98, 0x98, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A,
+		0x9A, 0x9C, 0x9B, 0x9B, 0x9C, 0x9B, 0x9B, 0x9B, 0x9A, 0x99, 0x9B, 0x9B, 0x9A, 0x99, 0x9A, 0x9A,
+	},
+	{ // 5
+		0xA4, 0xA4, 0xA8, 0xA8, 0x00, 0x00, 0x00, 0x00, 0x9E, 0x9E, 0x9E, 0xA0, 0xA8, 0xAC, 0x00, 0x00,
+		0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9E, 0xAC, 0x00, 0x97, 0x97, 0x97, 0x98, 0x9C, 0x9C, 0xA0, 0xAC,
+		0x99, 0x98, 0x99, 0x99, 0x99, 0x9B, 0xA0, 0xAC, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9B, 0xA0, 0xAC,
+		0x9C, 0x9B, 0x9C, 0x9C, 0x9C, 0xA0, 0xAC, 0x00, 0x99, 0x9A, 0x9A, 0x9B, 0x9B, 0xA4, 0xAC, 0x00,
+	},
+	{ // 6
+		0x00, 0x00, 0x00, 0xAC, 0xA4, 0x9C, 0x99, 0x99, 0x00, 0x00, 0x00, 0xAC, 0xA0, 0x9C, 0x9B, 0x99,
+		0x00, 0x00, 0xAC, 0xA0, 0x9C, 0x99, 0x99, 0x99, 0x00, 0xAC, 0xA0, 0x9C, 0x99, 0x98, 0x99, 0x99,
+		0x00, 0xAC, 0xA0, 0x9C, 0x9C, 0xA0, 0x9C, 0x9A, 0x00, 0x00, 0xAC, 0xA4, 0xA0, 0x99, 0x99, 0x99,
+		0x00, 0xAC, 0xA0, 0x9C, 0x99, 0x99, 0x99, 0x99, 0x00, 0xAC, 0xA4, 0x9C, 0x99, 0x99, 0x99, 0x99,
+	},
+	{ // 7
+		0xAC, 0xA0, 0x9C, 0x99, 0x99, 0x99, 0x99, 0x99, 0xAC, 0xA4, 0x9C, 0x99, 0x99, 0x99, 0x99, 0x99,
+		0x00, 0xAC, 0xA0, 0x9C, 0x99, 0x99, 0x99, 0x99, 0x00, 0x00, 0xAC, 0xA4, 0x9C, 0x9C, 0x99, 0x99,
+		0x00, 0x00, 0xAC, 0xA0, 0x9C, 0x99, 0x99, 0x99, 0x00, 0x00, 0x00, 0xAC, 0xA4, 0x9C, 0x99, 0x99,
+		0x00, 0x00, 0xAC, 0xA0, 0x9B, 0xA0, 0x9E, 0x9C, 0x00, 0xAC, 0xA4, 0x9C, 0x99, 0x9C, 0x99, 0x99,
+	},
+	{ // 8
+		0x00, 0xAC, 0xA0, 0x9C, 0x99, 0x99, 0x9B, 0x99, 0xAC, 0xA4, 0x9C, 0x99, 0x99, 0x99, 0x99, 0x99,
+		0xAC, 0xA0, 0x9C, 0x99, 0x99, 0x99, 0x99, 0x99, 0xAC, 0xA4, 0x9C, 0x99, 0x99, 0x99, 0x99, 0x99,
+		0x00, 0xAC, 0xA4, 0x9C, 0x99, 0x99, 0x99, 0x99, 0xAC, 0xA0, 0x9C, 0x99, 0x99, 0x99, 0x99, 0x99,
+		0x00, 0xAC, 0xA0, 0x9C, 0x99, 0x99, 0x9C, 0x99, 0x00, 0xAC, 0xA4, 0x9C, 0x99, 0x9E, 0x9C, 0x99,
+	},
+	{ // 9
+		0x00, 0x00, 0xAC, 0xA4, 0xA0, 0x9C, 0x99, 0x99, 0x00, 0xAC, 0xA0, 0x9C, 0x9C, 0xA0, 0x9C, 0x9A,
+		0xAC, 0xA4, 0x9C, 0x9A, 0x99, 0x99, 0x99, 0x99, 0xAC, 0xA0, 0x9C, 0x99, 0x99, 0x99, 0x99, 0x99,
+		0xAC, 0xA4, 0x9C, 0x99, 0x99, 0x99, 0x99, 0x99, 0x00, 0xAC, 0xA0, 0x9C, 0x99, 0x99, 0x99, 0x99,
+		0x00, 0xAC, 0xA4, 0x9C, 0x9A, 0x9C, 0x99, 0x99, 0x00, 0x00, 0xAC, 0xA0, 0x9C, 0x9A, 0x99, 0x99,
+	},
+	{ // 10
+		0x99, 0x99, 0x99, 0x9A, 0xA0, 0xAC, 0x00, 0x00, 0x99, 0x99, 0x99, 0x9C, 0xA0, 0xAC, 0x00, 0x00,
+		0x99, 0x99, 0x9C, 0x9E, 0xA4, 0xAC, 0x00, 0x00, 0x99, 0x99, 0x9C, 0x99, 0x9C, 0xA4, 0xAC, 0x00,
+		0x99, 0x99, 0x99, 0x99, 0x9C, 0xA0, 0xAC, 0x00, 0x99, 0x99, 0x99, 0x9C, 0xA0, 0xAC, 0x00, 0x00,
+		0x99, 0x99, 0x99, 0xA0, 0xA4, 0xAC, 0x00, 0x00, 0x9A, 0x9B, 0x9E, 0x9C, 0x9C, 0xA4, 0xAC, 0x00,
+	},
+	{ // 11
+		0x99, 0x99, 0x99, 0x99, 0x9C, 0xA0, 0xAC, 0x00, 0x99, 0x99, 0x99, 0x99, 0x99, 0x9C, 0x9E, 0xAC,
+		0x99, 0x99, 0x99, 0x99, 0x9C, 0xA0, 0xAC, 0x00, 0x99, 0x99, 0x99, 0x99, 0x9C, 0xA0, 0xAC, 0x00,
+		0x99, 0x99, 0x99, 0x99, 0x99, 0x9C, 0xA4, 0xAC, 0x99, 0x99, 0x99, 0x99, 0x99, 0x9C, 0xA0, 0xAC,
+		0x9C, 0x99, 0x99, 0x99, 0x9C, 0x9C, 0xA4, 0xAC, 0x99, 0x9E, 0x9E, 0x9C, 0x9C, 0xA0, 0xAC, 0x00,
+	},
+	{ // 12
+		0x99, 0x99, 0x9C, 0xA0, 0xA4, 0xAC, 0x00, 0x00, 0x9B, 0x9C, 0x9E, 0x9C, 0x9C, 0xA4, 0xAC, 0x00,
+		0x99, 0x99, 0x99, 0x99, 0x99, 0xA0, 0xAC, 0x00, 0x99, 0x99, 0x99, 0x99, 0x99, 0x9C, 0xA0, 0xAC,
+		0x99, 0x99, 0x99, 0x99, 0x9C, 0x9C, 0xA4, 0xAC, 0x99, 0x99, 0x99, 0x9C, 0xA0, 0xA4, 0xAC, 0x00,
+		0x99, 0x99, 0x9C, 0x99, 0x99, 0x9C, 0xA0, 0xAC, 0x99, 0x99, 0x99, 0x99, 0x99, 0x9C, 0xA0, 0xAC,
+	},
+	{ // 13
+		0x99, 0x99, 0x99, 0x99, 0x9C, 0xA0, 0xAC, 0x00, 0x99, 0x99, 0x99, 0x9C, 0xA0, 0xAC, 0x00, 0x00,
+		0x99, 0x9B, 0x9C, 0xA0, 0xA4, 0xAC, 0x00, 0x00, 0x99, 0x99, 0x9A, 0x99, 0x9C, 0xA0, 0xAC, 0x00,
+		0x99, 0x99, 0x99, 0x99, 0x99, 0x9C, 0xA4, 0xAC, 0x99, 0x99, 0x99, 0x99, 0x99, 0x9C, 0xA0, 0xAC,
+		0x99, 0x99, 0x99, 0x99, 0x9A, 0x9C, 0xA4, 0xAC, 0x99, 0x99, 0x99, 0x9A, 0x9C, 0xA4, 0xAC, 0x00,
+	},
+	{ // 14
+		0x00, 0x00, 0xAC, 0x9E, 0x9C, 0x9C, 0x9C, 0x9B, 0x00, 0xAC, 0x9C, 0xA0, 0x9E, 0xA4, 0xA4, 0xA4,
+		0xAC, 0x9C, 0xA4, 0xAC, 0xAC, 0xAC, 0x9C, 0x9E, 0xAC, 0xA0, 0xAC, 0xA8, 0x9E, 0xA8, 0xAC, 0x99,
+		0xAC, 0x9E, 0xAC, 0xA8, 0xAC, 0x9E, 0xA4, 0xAC, 0xAC, 0xA4, 0xA0, 0xAC, 0xAC, 0xA0, 0xA4, 0xAC,
+		0x00, 0xAC, 0xA4, 0xA0, 0xA0, 0xA4, 0xAC, 0xA4, 0x00, 0x00, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC,
+	},
+	{ // 15
+		0x9C, 0x9C, 0x9C, 0x9B, 0x9C, 0x9C, 0x9C, 0x9B, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4,
+		0x9E, 0x9E, 0x9E, 0x9C, 0x9E, 0x9E, 0x9E, 0x9E, 0x99, 0x99, 0x99, 0x99, 0x99, 0x98, 0x99, 0x98,
+		0x9C, 0x9C, 0x9B, 0x9B, 0x9B, 0x9C, 0x9C, 0x9C, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0x9E, 0x9E, 0xA0,
+		0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC,
+	},
+	{ // 16
+		0x9B, 0x9B, 0x9B, 0x9B, 0x9C, 0x9B, 0x9C, 0x9C, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4,
+		0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9E, 0x98, 0x98, 0x98, 0x98, 0x99, 0x99, 0x99, 0x99,
+		0x9C, 0x9B, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0xA0, 0xA0, 0xA0, 0x9E, 0xA0, 0x9E, 0x9E, 0xA0,
+		0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC,
+	},
+	{ // 17
+		0x9C, 0x9C, 0x9C, 0x9B, 0x9B, 0x9B, 0x9C, 0x9B, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4,
+		0x9E, 0x9E, 0x9E, 0x9C, 0x9C, 0x9C, 0x9E, 0x9E, 0x98, 0x98, 0x98, 0x99, 0x9A, 0x9A, 0x99, 0x98,
+		0x9C, 0x9B, 0x9C, 0x9C, 0x9C, 0x9B, 0x9B, 0x9C, 0xA0, 0x9E, 0x9E, 0xA0, 0xA0, 0xA0, 0xA0, 0x9E,
+		0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC,
+	},
+	{ // 18
+		0x9B, 0x9B, 0x9C, 0x9C, 0x9C, 0x9B, 0x9B, 0x9B, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4,
+		0x9E, 0x9E, 0x9E, 0x9E, 0x9C, 0x9C, 0x9C, 0x9E, 0x98, 0x98, 0x98, 0x98, 0x9A, 0x9A, 0x98, 0x99,
+		0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9B, 0x9C, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0xA0, 0xA0, 0xA0,
+		0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC,
+	},
+	{ // 19
+		0x9C, 0x9B, 0x9C, 0x9C, 0xA0, 0xA4, 0xAC, 0x00, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xAC, 0x00, 0x00,
+		0x9E, 0x9E, 0x9C, 0x9C, 0x9E, 0xA0, 0xAC, 0x00, 0x99, 0x98, 0x98, 0x99, 0x9A, 0x9A, 0xA0, 0xAC,
+		0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0xA0, 0xAC, 0xA0, 0xA0, 0x9E, 0xA0, 0xA0, 0xA0, 0xA0, 0xAC,
+		0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xAC, 0x00, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0x00, 0x00,
+	}
+};
+
+} // End of namespace Xeen
diff --git a/engines/xeen/resdata.h b/engines/xeen/resdata.h
new file mode 100644
index 0000000..ce355e7
--- /dev/null
+++ b/engines/xeen/resdata.h
@@ -0,0 +1,35 @@
+/* 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_RESDATA_H
+#define XEEN_RESDATA_H
+
+#include "common/scummsys.h"
+#include "gui/debugger.h"
+
+namespace Xeen {
+
+extern const byte SYMBOLS[20][64];
+
+} // End of namespace Xeen
+
+#endif	/* XEEN_RESDATA_H */
diff --git a/engines/xeen/screen.cpp b/engines/xeen/screen.cpp
index 1f8e50c..4563e37 100644
--- a/engines/xeen/screen.cpp
+++ b/engines/xeen/screen.cpp
@@ -61,6 +61,62 @@ void Window::open2() {
 	create(_bounds.width(), _bounds.height());
 	copyRectToSurface(*_vm->_screen, 0, 0, _bounds);
 	_dirtyRects.push(_bounds);
+	frame();
+}
+
+void Window::frame() {
+	Screen &screen = *_vm->_screen;
+	int xCount = (_bounds.width() - 9) / SYMBOL_WIDTH;
+	int yCount = (_bounds.height() - 9) / SYMBOL_HEIGHT;
+
+	// Write the top line
+	screen._writePos = Common::Point(_bounds.left, _bounds.top);
+	screen.writeSymbol(0);
+
+	if (xCount > 0) {
+		int symbolId = 1;
+		for (int i = 0; i < xCount; ++i) {
+			screen.writeSymbol(symbolId);
+			if (++symbolId == 5)
+				symbolId = 1;
+		}
+	}
+
+	screen._writePos.x = _bounds.right - SYMBOL_WIDTH;
+	screen.writeSymbol(5);
+
+	// Write the vertical edges
+	if (yCount > 0) {
+		int symbolId = 6;
+		for (int i = 0; i < yCount; ++i) {
+			screen._writePos.y += 8;
+
+			screen._writePos.x = _bounds.left;
+			screen.writeSymbol(symbolId);
+
+			screen._writePos.x = _bounds.right - SYMBOL_WIDTH;
+			screen.writeSymbol(symbolId + 4);
+
+			if (++symbolId == 10)
+				symbolId = 6;
+		}
+	}
+
+	// Write the bottom line
+	screen._writePos = Common::Point(_bounds.left, _bounds.bottom - SYMBOL_HEIGHT);
+	screen.writeSymbol(14);
+
+	if (xCount > 0) {
+		int symbolId = 15;
+		for (int i = 0; i < xCount; ++i) {
+			screen.writeSymbol(symbolId);
+			if (++symbolId == 19)
+				symbolId = 15;
+		}
+	}
+
+	screen._writePos.x = _bounds.right - SYMBOL_WIDTH;
+	screen.writeSymbol(19);
 }
 
 void Window::close() {
@@ -94,6 +150,10 @@ void Window::update() {
 	}
 }
 
+void Window::addDirtyRect(const Common::Rect &r) {
+	_dirtyRects.push(r);
+}
+
 /*------------------------------------------------------------------------*/
 
 /**
diff --git a/engines/xeen/screen.h b/engines/xeen/screen.h
index b132e33..cbf5767 100644
--- a/engines/xeen/screen.h
+++ b/engines/xeen/screen.h
@@ -54,6 +54,8 @@ private:
 
 	void open2();
 public:
+	virtual void addDirtyRect(const Common::Rect &r);
+public:
 	Window();
 
 	Window(XeenEngine *vm, const Common::Rect &bounds, int a, int border,
@@ -66,6 +68,8 @@ public:
 	void close();
 
 	void update();
+
+	void frame();
 };
 
 class Screen: public XSurface {
diff --git a/engines/xeen/xsurface.cpp b/engines/xeen/xsurface.cpp
index f63ad14..d3c5478 100644
--- a/engines/xeen/xsurface.cpp
+++ b/engines/xeen/xsurface.cpp
@@ -22,6 +22,7 @@
 
 #include "common/algorithm.h"
 #include "xeen/xsurface.h"
+#include "xeen/resdata.h"
 
 namespace Xeen {
 
@@ -79,4 +80,39 @@ void XSurface::blitTo(XSurface &dest, const Common::Point &destPos) const {
 	dest.addDirtyRect(Common::Rect(destPos.x, destPos.y, destPos.x + w, destPos.y));
 }
 
+/**
+ * Draws a symbol to the surface.
+ * @param symbolId	Symbol number from 0 to 19
+ */
+void XSurface::writeSymbol(int symbolId) {
+	const byte *srcP = &SYMBOLS[symbolId][0];
+
+	for (int yp = 0; yp < SYMBOL_HEIGHT; ++yp) {
+		byte *destP = (byte *)getBasePtr(_writePos.x, _writePos.y + yp);
+
+		for (int xp = 0; xp < SYMBOL_WIDTH; ++xp, ++destP) {
+			byte b = *srcP++;
+			if (b)
+				*destP = b;
+		}
+	}
+
+	_writePos.x += 8;
+}
+
+/**
+ * Write a string to the surface
+ */
+void XSurface::writeString(const Common::String &s) {
+	error("TODO");
+}
+
+/**
+ * Wrie a character to the surface
+ */
+void XSurface::writeChar(char c) {
+	error("TODO");
+}
+
+
 } // End of namespace Xeen
diff --git a/engines/xeen/xsurface.h b/engines/xeen/xsurface.h
index 92f1236..6688285 100644
--- a/engines/xeen/xsurface.h
+++ b/engines/xeen/xsurface.h
@@ -30,8 +30,13 @@
 
 namespace Xeen {
 
+#define SYMBOL_WIDTH 8
+#define SYMBOL_HEIGHT 8
+
 class XSurface: public Graphics::Surface {
 public:
+	Common::Point _writePos;
+public:
 	virtual void addDirtyRect(const Common::Rect &r) {}
 public:
 	XSurface();
@@ -49,6 +54,12 @@ public:
 	void blitTo(XSurface &dest) const;
 
 	bool empty() const { return getPixels() == nullptr; }
+
+	void writeSymbol(int symbolId);
+
+	void writeString(const Common::String &s);
+
+	void writeChar(char c);
 };
 
 } // End of namespace Xeen


Commit: d21c47e019434797217b1b44708c8f1810a003b3
    https://github.com/scummvm/scummvm/commit/d21c47e019434797217b1b44708c8f1810a003b3
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2014-12-31T16:14:45-10:00

Commit Message:
XEEN: Lot of font code implemented

Changed paths:
    engines/xeen/resdata.cpp
    engines/xeen/resdata.h
    engines/xeen/screen.cpp
    engines/xeen/screen.h
    engines/xeen/xsurface.cpp
    engines/xeen/xsurface.h



diff --git a/engines/xeen/resdata.cpp b/engines/xeen/resdata.cpp
index 44002c6..1cdd3ac 100644
--- a/engines/xeen/resdata.cpp
+++ b/engines/xeen/resdata.cpp
@@ -148,4 +148,47 @@ const byte SYMBOLS[20][64] = {
 	}
 };
 
+const byte TEXT_COLORS[40][4] = {
+	{ 0x00, 0x19, 0x19, 0x19 },
+	{ 0x00, 0x08, 0x08, 0x08 },
+	{ 0x00, 0x0F, 0x0F, 0x0F },
+	{ 0x00, 0x15, 0x15, 0x15 },
+	{ 0x00, 0x01, 0x01, 0x01 },
+	{ 0x00, 0x21, 0x21, 0x21 },
+	{ 0x00, 0x26, 0x26, 0x26 },
+	{ 0x00, 0x2B, 0x2B, 0x2B },
+	{ 0x00, 0x31, 0x31, 0x31 },
+	{ 0x00, 0x36, 0x36, 0x36 },
+	{ 0x00, 0x3D, 0x3D, 0x3D },
+	{ 0x00, 0x41, 0x41, 0x41 },
+	{ 0x00, 0x46, 0x46, 0x46 },
+	{ 0x00, 0x4C, 0x4C, 0x4C },
+	{ 0x00, 0x50, 0x50, 0x50 },
+	{ 0x00, 0x55, 0x55, 0x55 },
+	{ 0x00, 0x5D, 0x5D, 0x5D },
+	{ 0x00, 0x60, 0x60, 0x60 },
+	{ 0x00, 0x65, 0x65, 0x65 },
+	{ 0x00, 0x6C, 0x6C, 0x6C },
+	{ 0x00, 0x70, 0x70, 0x70 },
+	{ 0x00, 0x75, 0x75, 0x75 },
+	{ 0x00, 0x7B, 0x7B, 0x7B },
+	{ 0x00, 0x80, 0x80, 0x80 },
+	{ 0x00, 0x85, 0x85, 0x85 },
+	{ 0x00, 0x8D, 0x8D, 0x8D },
+	{ 0x00, 0x90, 0x90, 0x90 },
+	{ 0x00, 0x97, 0x97, 0x97 },
+	{ 0x00, 0x9D, 0x9D, 0x9D },
+	{ 0x00, 0xA4, 0xA4, 0xA4 },
+	{ 0x00, 0xAB, 0xAB, 0xAB },
+	{ 0x00, 0xB0, 0xB0, 0xB0 },
+	{ 0x00, 0xB6, 0xB6, 0xB6 },
+	{ 0x00, 0xBD, 0xBD, 0xBD },
+	{ 0x00, 0xC0, 0xC0, 0xC0 },
+	{ 0x00, 0xC6, 0xC6, 0xC6 },
+	{ 0x00, 0xCD, 0xCD, 0xCD },
+	{ 0x00, 0xD0, 0xD0, 0xD0 },
+	{ 0x00, 0xD6, 0xD6, 0xD6 },
+	{ 0x00, 0xDB, 0xDB, 0xDB },
+};
+
 } // End of namespace Xeen
diff --git a/engines/xeen/resdata.h b/engines/xeen/resdata.h
index ce355e7..deb6e58 100644
--- a/engines/xeen/resdata.h
+++ b/engines/xeen/resdata.h
@@ -30,6 +30,8 @@ namespace Xeen {
 
 extern const byte SYMBOLS[20][64];
 
+extern const byte TEXT_COLORS[40][4];
+
 } // End of namespace Xeen
 
 #endif	/* XEEN_RESDATA_H */
diff --git a/engines/xeen/screen.cpp b/engines/xeen/screen.cpp
index 4563e37..2da2412 100644
--- a/engines/xeen/screen.cpp
+++ b/engines/xeen/screen.cpp
@@ -66,8 +66,8 @@ void Window::open2() {
 
 void Window::frame() {
 	Screen &screen = *_vm->_screen;
-	int xCount = (_bounds.width() - 9) / SYMBOL_WIDTH;
-	int yCount = (_bounds.height() - 9) / SYMBOL_HEIGHT;
+	int xCount = (_bounds.width() - 9) / FONT_WIDTH;
+	int yCount = (_bounds.height() - 9) / FONT_HEIGHT;
 
 	// Write the top line
 	screen._writePos = Common::Point(_bounds.left, _bounds.top);
@@ -82,7 +82,7 @@ void Window::frame() {
 		}
 	}
 
-	screen._writePos.x = _bounds.right - SYMBOL_WIDTH;
+	screen._writePos.x = _bounds.right - FONT_WIDTH;
 	screen.writeSymbol(5);
 
 	// Write the vertical edges
@@ -94,7 +94,7 @@ void Window::frame() {
 			screen._writePos.x = _bounds.left;
 			screen.writeSymbol(symbolId);
 
-			screen._writePos.x = _bounds.right - SYMBOL_WIDTH;
+			screen._writePos.x = _bounds.right - FONT_WIDTH;
 			screen.writeSymbol(symbolId + 4);
 
 			if (++symbolId == 10)
@@ -103,7 +103,7 @@ void Window::frame() {
 	}
 
 	// Write the bottom line
-	screen._writePos = Common::Point(_bounds.left, _bounds.bottom - SYMBOL_HEIGHT);
+	screen._writePos = Common::Point(_bounds.left, _bounds.bottom - FONT_HEIGHT);
 	screen.writeSymbol(14);
 
 	if (xCount > 0) {
@@ -115,7 +115,7 @@ void Window::frame() {
 		}
 	}
 
-	screen._writePos.x = _bounds.right - SYMBOL_WIDTH;
+	screen._writePos.x = _bounds.right - FONT_WIDTH;
 	screen.writeSymbol(19);
 }
 
@@ -154,6 +154,17 @@ void Window::addDirtyRect(const Common::Rect &r) {
 	_dirtyRects.push(r);
 }
 
+/**
+ * Fill the content area of a window with the current background color 
+ */
+void Window::fill() {
+	fillRect(_innerBounds, _bgColor);
+}
+
+void Window::writeString(const Common::String &s) {
+	_vm->_screen->writeString(s, _innerBounds);
+}
+
 /*------------------------------------------------------------------------*/
 
 /**
@@ -163,6 +174,16 @@ Screen::Screen(XeenEngine *vm) : _vm(vm) {
 	_fadeIn = false;
 	create(SCREEN_WIDTH, SCREEN_HEIGHT);
 	setupWindows();
+
+	// Load font data for the screen
+	File f("fnt");
+	byte *data = new byte[f.size()];
+	f.read(data, f.size());
+	_fontData = data;
+}
+
+Screen::~Screen() {
+	delete[] _fontData;
 }
 
 void Screen::setupWindows() {
diff --git a/engines/xeen/screen.h b/engines/xeen/screen.h
index cbf5767..907409d 100644
--- a/engines/xeen/screen.h
+++ b/engines/xeen/screen.h
@@ -70,7 +70,10 @@ public:
 	void update();
 
 	void frame();
-};
+
+	void fill();
+
+	void writeString(const Common::String &s);};
 
 class Screen: public XSurface {
 private:
@@ -104,6 +107,8 @@ public:
 public:
 	Screen(XeenEngine *vm);
 
+	virtual ~Screen();
+
 	void closeWindows();
 
 	void update();
diff --git a/engines/xeen/xsurface.cpp b/engines/xeen/xsurface.cpp
index d3c5478..5e7d831 100644
--- a/engines/xeen/xsurface.cpp
+++ b/engines/xeen/xsurface.cpp
@@ -21,16 +21,29 @@
  */
 
 #include "common/algorithm.h"
+#include "common/util.h"
 #include "xeen/xsurface.h"
 #include "xeen/resdata.h"
 
 namespace Xeen {
 
-XSurface::XSurface(): Graphics::Surface() {
+const byte *XSurface::_fontData;
+
+XSurface::XSurface() : Graphics::Surface(), _bgColor(DEFAULT_BG_COLOR), _fontReduced(false),
+		_fontJustify(JUSTIFY_NONE), _msgWraps(false) {
+	_textColors[0] = 0;
+	_textColors[1] = 0x40;
+	_textColors[2] = 0x30;
+	_textColors[3] = 0x20;
 }
 
-XSurface::XSurface(int w, int h) : Graphics::Surface() {
+XSurface::XSurface(int w, int h) : Graphics::Surface(), _bgColor(DEFAULT_BG_COLOR),
+		_fontReduced(false), _fontJustify(JUSTIFY_NONE), _msgWraps(false) {
 	create(w, h);
+	_textColors[0] = 0;
+	_textColors[1] = 0x40;
+	_textColors[2] = 0x30;
+	_textColors[3] = 0x20;
 }
 
 XSurface::~XSurface() {
@@ -87,10 +100,10 @@ void XSurface::blitTo(XSurface &dest, const Common::Point &destPos) const {
 void XSurface::writeSymbol(int symbolId) {
 	const byte *srcP = &SYMBOLS[symbolId][0];
 
-	for (int yp = 0; yp < SYMBOL_HEIGHT; ++yp) {
+	for (int yp = 0; yp < FONT_HEIGHT; ++yp) {
 		byte *destP = (byte *)getBasePtr(_writePos.x, _writePos.y + yp);
 
-		for (int xp = 0; xp < SYMBOL_WIDTH; ++xp, ++destP) {
+		for (int xp = 0; xp < FONT_WIDTH; ++xp, ++destP) {
 			byte b = *srcP++;
 			if (b)
 				*destP = b;
@@ -102,9 +115,158 @@ void XSurface::writeSymbol(int symbolId) {
 
 /**
  * Write a string to the surface
+ * @param s			String to display
+ * @param bounds	Window bounds to display string within
+ * @returns			Any string remainder that couldn't be displayed
+ * @remarks		Note that bounds is just used for wrapping purposes. Unless
+ *		justification is set, the message will be written at _writePos
  */
-void XSurface::writeString(const Common::String &s) {
-	error("TODO");
+Common::String XSurface::writeString(const Common::String &s, const Common::Rect &bounds) {
+	_displayString = s.c_str();
+
+	for (;;) {
+		_msgWraps = false;
+		
+		// Get the size of the string that can be displayed on the likne
+		int xp = _fontJustify ? bounds.left : _writePos.x;
+		while (!getNextCharWidth(xp)) {
+			if (xp >= bounds.right) {
+				--_displayString;
+				_msgWraps = true;
+			}
+		}
+
+		// Get the end point of the text that can be displayed
+		const char *displayEnd = _displayString;
+		_displayString = s.c_str();
+
+		if (*displayEnd && _fontJustify != JUSTIFY_RIGHT && xp >= bounds.right) {
+			// Need to handle justification of text
+			// First, move backwards to find the end of the previous word
+			// for a convenient point to break the line at
+			const char *endP = displayEnd;
+			while (endP > _displayString && (*endP & 0x7f) != ' ')
+				--endP;
+
+			if (endP == _displayString) {
+				// There was no word breaks at all in the string
+				--displayEnd;
+				if (_fontJustify == JUSTIFY_NONE && _writePos.x != bounds.left) {
+					// Move to the next line
+					if (!newLine(bounds))
+						continue;
+					// Ran out of space to display string
+					break;
+				}
+			} else {
+				// Found word break, find end of previous word 
+				while (displayEnd > _displayString && (*displayEnd & 0x7f) == ' ')
+					--displayEnd;
+			}
+		}
+
+		// Main character display loop
+		while (_displayString <= displayEnd) {
+			char c = getNextChar();
+			
+			if (c == ' ') {
+				_writePos.x += _fontReduced ? 3 : 4;
+			} else if (c == '\r') {
+				fillRect(bounds, _bgColor);
+				_writePos = Common::Point(bounds.left, bounds.top);
+			} else if (c == 1) {
+				// Turn off reduced font mode
+				_fontReduced = false;
+			} else if (c == 2) {
+				// Turn on reduced font mode
+				_fontReduced = true;
+			} else if (c == 3) {
+				// Justify text
+				c = getNextChar();
+				if (c == 'r')
+					_fontJustify = JUSTIFY_RIGHT;
+				else if (c == 'c')
+					_fontJustify = JUSTIFY_CENTER;
+				else
+					_fontJustify = JUSTIFY_NONE;
+			} else if (c == 4) {
+				// Draw an empty box of a given width
+				int w = fontAtoi();
+				Common::Point pt = _writePos;
+				if (_fontJustify == JUSTIFY_RIGHT)
+					pt.x -= w;
+				fillRect(Common::Rect(pt.x, pt.y, pt.x + w, pt.y + (_fontReduced ? 9 : 10)),
+					_bgColor);
+			} else if (c == 5) {
+				continue;
+			} else if (c == 6) {
+				// Non-breakable space
+				writeChar(' ');
+			} else if (c == 7) {
+				// Set text background color
+				int c = fontAtoi();
+				_bgColor = (c < 0 || c > 255) ? DEFAULT_BG_COLOR : c;
+			} else if (c == 8) {
+				// Draw a character outline
+				c = getNextChar();
+				if (c == ' ') {
+					c = '\0';
+					_writePos.x -= 3;
+				} else {
+					if (c == 6)
+						c = ' ';
+					byte charSize = _fontData[0x1000 + (int)c + (_fontReduced ? 0x80 : 0)];
+					_writePos.x -= charSize;
+				}
+
+				if (_writePos.x < bounds.left)
+					_writePos.x = bounds.left;
+
+				if (c) {
+					int oldX = _writePos.x;
+					byte oldColor[4];
+					Common::copy(&_textColors[0], &_textColors[4], &oldColor[0]);
+
+					_textColors[1] = _textColors[2] = _textColors[3] = _bgColor;
+					writeChar(c);
+
+					Common::copy(&oldColor[0], &oldColor[4], &_textColors[0]);
+					_writePos.x = oldX;
+				}
+			} else if (c == 9) {
+				// Skip x position
+				int xp = fontAtoi();
+				_writePos.x = MIN(bounds.left + xp, (int)bounds.right);
+			} else if (c == 10) {
+				// Newline
+				if (newLine(bounds))
+					break;
+			} else if (c == 11) {
+				// Skip y position
+				int yp = fontAtoi(	);
+				_writePos.y = MIN(bounds.top + yp, (int)bounds.bottom);
+			} else if (c == 12) {
+				// Set text colors
+				int idx = fontAtoi();
+				if (idx < 0)
+					idx = 0;
+				setTextColor(idx);
+			} else if (c < ' ') {
+				// Invalid command
+				displayEnd = nullptr;
+				break;
+			} else {
+				// Standard character - write it out
+				writeChar(c);
+			}
+		}
+
+		if (_displayString > displayEnd && _fontJustify != JUSTIFY_RIGHT && _msgWraps
+				&& newLine(bounds))
+			break;
+	}
+
+	return Common::String(_displayString);
 }
 
 /**
@@ -114,5 +276,79 @@ void XSurface::writeChar(char c) {
 	error("TODO");
 }
 
+/**
+ * Return the next pending character to display
+ */
+char XSurface::getNextChar() {
+	return  *_displayString++ & 0x7f;
+}
+
+/**
+* Return the width of a given character
+*/
+bool XSurface::getNextCharWidth(int &total) {
+	char c = getNextChar();
+
+	if (c > ' ') {
+		total += _fontData[0x1000 + (int)c + (_fontReduced ? 0x80 : 0)];
+		return false;
+	} else if (c == ' ') {
+		total += 4;
+		return false;
+	} else if (c == 8) {
+		c = getNextChar();
+		if (c == ' ') {
+			total -= 2;
+			return false;
+		} else {
+			_displayString -= 2;
+			return true;
+		}
+	} else if (c == 12) {
+		c = getNextChar();
+		if (c != 'd')
+			getNextChar();
+		return false;
+	} else {
+		--_displayString;
+		return true;
+	}
+}
+
+bool XSurface::newLine(const Common::Rect &bounds) {
+	// Move past any spaces currently being pointed to
+	while ((*_displayString & 0x7f) == ' ')
+		++_displayString;
+
+	_msgWraps = false;
+	_writePos.x = bounds.left;
+	
+	int h = _fontReduced ? 9 : 10;
+	_writePos.y += h;
+
+	return ((_writePos.y + h - 1) > bounds.bottom);
+}
+
+int XSurface::fontAtoi(int len) {
+	int total = 0;
+	for (int i = 0; i < len; ++i) {
+		char c = getNextChar();
+		if (c == ' ')
+			c = '0';
+
+		int digit = c - '0';
+		if (digit < 0 || digit > 9)
+			return -1;
+
+		total = total * 10 + digit;
+	}
+
+	return total;
+}
+
+void XSurface::setTextColor(int idx) {
+	const byte *colP = &TEXT_COLORS[idx][0];
+	Common::copy(colP, colP + 4, &_textColors[0]);
+}
 
 } // End of namespace Xeen
diff --git a/engines/xeen/xsurface.h b/engines/xeen/xsurface.h
index 6688285..6e88ae9 100644
--- a/engines/xeen/xsurface.h
+++ b/engines/xeen/xsurface.h
@@ -30,18 +30,39 @@
 
 namespace Xeen {
 
-#define SYMBOL_WIDTH 8
-#define SYMBOL_HEIGHT 8
+#define FONT_WIDTH 8
+#define FONT_HEIGHT 8
+#define DEFAULT_BG_COLOR 0x99
+
+enum Justify { JUSTIFY_NONE = 0, JUSTIFY_CENTER = 1, JUSTIFY_RIGHT = 2 };
 
 class XSurface: public Graphics::Surface {
+private:
+	const char *_displayString;
+	bool _msgWraps;
+
+	char getNextChar();
+
+	bool getNextCharWidth(int &total);
+
+	bool newLine(const Common::Rect &bounds);
+
+	int fontAtoi(int len = 3);
+
+	void setTextColor(int idx);
 public:
+	static const byte *_fontData;
 	Common::Point _writePos;
+	byte _textColors[4];
+	byte _bgColor;
+	bool _fontReduced;
+	Justify _fontJustify;
 public:
 	virtual void addDirtyRect(const Common::Rect &r) {}
 public:
 	XSurface();
 	XSurface(int w, int h);
-	~XSurface();
+	virtual ~XSurface();
 
 	void create(uint16 w, uint16 h);
 
@@ -57,7 +78,7 @@ public:
 
 	void writeSymbol(int symbolId);
 
-	void writeString(const Common::String &s);
+	Common::String writeString(const Common::String &s, const Common::Rect &bounds);
 
 	void writeChar(char c);
 };


Commit: c6a2f539d428ea580274a3ac5605e00fad7b8570
    https://github.com/scummvm/scummvm/commit/c6a2f539d428ea580274a3ac5605e00fad7b8570
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2014-12-31T16:27:37-10:00

Commit Message:
XEEN: Split the font code into it's own file

Changed paths:
  A engines/xeen/font.cpp
  A engines/xeen/font.h
    engines/xeen/module.mk
    engines/xeen/screen.cpp
    engines/xeen/screen.h
    engines/xeen/xsurface.cpp
    engines/xeen/xsurface.h



diff --git a/engines/xeen/font.cpp b/engines/xeen/font.cpp
new file mode 100644
index 0000000..2894bce
--- /dev/null
+++ b/engines/xeen/font.cpp
@@ -0,0 +1,313 @@
+/* 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 "xeen/font.h"
+#include "xeen/resdata.h"
+
+namespace Xeen {
+
+FontSurface::FontSurface() : XSurface(), _fontData(nullptr), _bgColor(DEFAULT_BG_COLOR), 
+		_fontReduced(false),_fontJustify(JUSTIFY_NONE), _msgWraps(false) {
+	_textColors[0] = 0;
+	_textColors[1] = 0x40;
+	_textColors[2] = 0x30;
+	_textColors[3] = 0x20;
+}
+
+FontSurface::FontSurface(int w, int h) : XSurface(), _fontData(nullptr), _msgWraps(false),
+		_bgColor(DEFAULT_BG_COLOR), _fontReduced(false), _fontJustify(JUSTIFY_NONE) {
+	create(w, h);
+	_textColors[0] = 0;
+	_textColors[1] = 0x40;
+	_textColors[2] = 0x30;
+	_textColors[3] = 0x20;
+}
+
+/**
+ * Draws a symbol to the surface.
+ * @param symbolId	Symbol number from 0 to 19
+ */
+void FontSurface::writeSymbol(int symbolId) {
+	const byte *srcP = &SYMBOLS[symbolId][0];
+
+	for (int yp = 0; yp < FONT_HEIGHT; ++yp) {
+		byte *destP = (byte *)getBasePtr(_writePos.x, _writePos.y + yp);
+
+		for (int xp = 0; xp < FONT_WIDTH; ++xp, ++destP) {
+			byte b = *srcP++;
+			if (b)
+				*destP = b;
+		}
+	}
+
+	_writePos.x += 8;
+}
+
+/**
+ * Write a string to the surface
+ * @param s			String to display
+ * @param bounds	Window bounds to display string within
+ * @returns			Any string remainder that couldn't be displayed
+ * @remarks		Note that bounds is just used for wrapping purposes. Unless
+ *		justification is set, the message will be written at _writePos
+ */
+Common::String FontSurface::writeString(const Common::String &s, const Common::Rect &bounds) {
+	_displayString = s.c_str();
+	assert(_fontData);
+
+	for (;;) {
+		_msgWraps = false;
+		
+		// Get the size of the string that can be displayed on the likne
+		int xp = _fontJustify ? bounds.left : _writePos.x;
+		while (!getNextCharWidth(xp)) {
+			if (xp >= bounds.right) {
+				--_displayString;
+				_msgWraps = true;
+			}
+		}
+
+		// Get the end point of the text that can be displayed
+		const char *displayEnd = _displayString;
+		_displayString = s.c_str();
+
+		if (*displayEnd && _fontJustify != JUSTIFY_RIGHT && xp >= bounds.right) {
+			// Need to handle justification of text
+			// First, move backwards to find the end of the previous word
+			// for a convenient point to break the line at
+			const char *endP = displayEnd;
+			while (endP > _displayString && (*endP & 0x7f) != ' ')
+				--endP;
+
+			if (endP == _displayString) {
+				// There was no word breaks at all in the string
+				--displayEnd;
+				if (_fontJustify == JUSTIFY_NONE && _writePos.x != bounds.left) {
+					// Move to the next line
+					if (!newLine(bounds))
+						continue;
+					// Ran out of space to display string
+					break;
+				}
+			} else {
+				// Found word break, find end of previous word 
+				while (displayEnd > _displayString && (*displayEnd & 0x7f) == ' ')
+					--displayEnd;
+			}
+		}
+
+		// Main character display loop
+		while (_displayString <= displayEnd) {
+			char c = getNextChar();
+			
+			if (c == ' ') {
+				_writePos.x += _fontReduced ? 3 : 4;
+			} else if (c == '\r') {
+				fillRect(bounds, _bgColor);
+				_writePos = Common::Point(bounds.left, bounds.top);
+			} else if (c == 1) {
+				// Turn off reduced font mode
+				_fontReduced = false;
+			} else if (c == 2) {
+				// Turn on reduced font mode
+				_fontReduced = true;
+			} else if (c == 3) {
+				// Justify text
+				c = getNextChar();
+				if (c == 'r')
+					_fontJustify = JUSTIFY_RIGHT;
+				else if (c == 'c')
+					_fontJustify = JUSTIFY_CENTER;
+				else
+					_fontJustify = JUSTIFY_NONE;
+			} else if (c == 4) {
+				// Draw an empty box of a given width
+				int w = fontAtoi();
+				Common::Point pt = _writePos;
+				if (_fontJustify == JUSTIFY_RIGHT)
+					pt.x -= w;
+				fillRect(Common::Rect(pt.x, pt.y, pt.x + w, pt.y + (_fontReduced ? 9 : 10)),
+					_bgColor);
+			} else if (c == 5) {
+				continue;
+			} else if (c == 6) {
+				// Non-breakable space
+				writeChar(' ');
+			} else if (c == 7) {
+				// Set text background color
+				int c = fontAtoi();
+				_bgColor = (c < 0 || c > 255) ? DEFAULT_BG_COLOR : c;
+			} else if (c == 8) {
+				// Draw a character outline
+				c = getNextChar();
+				if (c == ' ') {
+					c = '\0';
+					_writePos.x -= 3;
+				} else {
+					if (c == 6)
+						c = ' ';
+					byte charSize = _fontData[0x1000 + (int)c + (_fontReduced ? 0x80 : 0)];
+					_writePos.x -= charSize;
+				}
+
+				if (_writePos.x < bounds.left)
+					_writePos.x = bounds.left;
+
+				if (c) {
+					int oldX = _writePos.x;
+					byte oldColor[4];
+					Common::copy(&_textColors[0], &_textColors[4], &oldColor[0]);
+
+					_textColors[1] = _textColors[2] = _textColors[3] = _bgColor;
+					writeChar(c);
+
+					Common::copy(&oldColor[0], &oldColor[4], &_textColors[0]);
+					_writePos.x = oldX;
+				}
+			} else if (c == 9) {
+				// Skip x position
+				int xp = fontAtoi();
+				_writePos.x = MIN(bounds.left + xp, (int)bounds.right);
+			} else if (c == 10) {
+				// Newline
+				if (newLine(bounds))
+					break;
+			} else if (c == 11) {
+				// Skip y position
+				int yp = fontAtoi(	);
+				_writePos.y = MIN(bounds.top + yp, (int)bounds.bottom);
+			} else if (c == 12) {
+				// Set text colors
+				int idx = fontAtoi();
+				if (idx < 0)
+					idx = 0;
+				setTextColor(idx);
+			} else if (c < ' ') {
+				// Invalid command
+				displayEnd = nullptr;
+				break;
+			} else {
+				// Standard character - write it out
+				writeChar(c);
+			}
+		}
+
+		if (_displayString > displayEnd && _fontJustify != JUSTIFY_RIGHT && _msgWraps
+				&& newLine(bounds))
+			break;
+	}
+
+	return Common::String(_displayString);
+}
+
+/**
+ * Return the next pending character to display
+ */
+char FontSurface::getNextChar() {
+	return  *_displayString++ & 0x7f;
+}
+
+/**
+* Return the width of a given character
+*/
+bool FontSurface::getNextCharWidth(int &total) {
+	char c = getNextChar();
+
+	if (c > ' ') {
+		total += _fontData[0x1000 + (int)c + (_fontReduced ? 0x80 : 0)];
+		return false;
+	} else if (c == ' ') {
+		total += 4;
+		return false;
+	} else if (c == 8) {
+		c = getNextChar();
+		if (c == ' ') {
+			total -= 2;
+			return false;
+		} else {
+			_displayString -= 2;
+			return true;
+		}
+	} else if (c == 12) {
+		c = getNextChar();
+		if (c != 'd')
+			getNextChar();
+		return false;
+	} else {
+		--_displayString;
+		return true;
+	}
+}
+
+/**
+ * Handles moving to the next line of the given bounded area
+ */
+bool FontSurface::newLine(const Common::Rect &bounds) {
+	// Move past any spaces currently being pointed to
+	while ((*_displayString & 0x7f) == ' ')
+		++_displayString;
+
+	_msgWraps = false;
+	_writePos.x = bounds.left;
+	
+	int h = _fontReduced ? 9 : 10;
+	_writePos.y += h;
+
+	return ((_writePos.y + h - 1) > bounds.bottom);
+}
+
+/**
+ * Extract a number of a given maximum length from the string
+ */
+int FontSurface::fontAtoi(int len) {
+	int total = 0;
+	for (int i = 0; i < len; ++i) {
+		char c = getNextChar();
+		if (c == ' ')
+			c = '0';
+
+		int digit = c - '0';
+		if (digit < 0 || digit > 9)
+			return -1;
+
+		total = total * 10 + digit;
+	}
+
+	return total;
+}
+
+/**
+ * Set the text colors based on the specified index in the master text colors list
+ */
+void FontSurface::setTextColor(int idx) {
+	const byte *colP = &TEXT_COLORS[idx][0];
+	Common::copy(colP, colP + 4, &_textColors[0]);
+}
+
+/**
+ * Wrie a character to the surface
+ */
+void FontSurface::writeChar(char c) {
+	error("TODO");
+}
+
+} // End of namespace Xeen
diff --git a/engines/xeen/font.h b/engines/xeen/font.h
new file mode 100644
index 0000000..0f53d5e
--- /dev/null
+++ b/engines/xeen/font.h
@@ -0,0 +1,71 @@
+/* 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_FONT_H
+#define XEEN_FONT_H
+
+#include "xeen/xsurface.h"
+
+namespace Xeen {
+
+#define FONT_WIDTH 8
+#define FONT_HEIGHT 8
+#define DEFAULT_BG_COLOR 0x99
+
+enum Justify { JUSTIFY_NONE = 0, JUSTIFY_CENTER = 1, JUSTIFY_RIGHT = 2 };
+
+class FontSurface: public XSurface {
+private:
+	const char *_displayString;
+	bool _msgWraps;
+
+	char getNextChar();
+
+	bool getNextCharWidth(int &total);
+
+	bool newLine(const Common::Rect &bounds);
+
+	int fontAtoi(int len = 3);
+
+	void setTextColor(int idx);
+
+	void writeChar(char c);
+public:
+	const byte *_fontData;
+	Common::Point _writePos;
+	byte _textColors[4];
+	byte _bgColor;
+	bool _fontReduced;
+	Justify _fontJustify;
+public:
+	FontSurface();
+	FontSurface(int w, int h);
+	virtual ~FontSurface() {}
+
+	void writeSymbol(int symbolId);
+
+	Common::String writeString(const Common::String &s, const Common::Rect &bounds);
+};
+
+} // End of namespace Xeen
+
+#endif /* XEEN_FONT_H */
diff --git a/engines/xeen/module.mk b/engines/xeen/module.mk
index a410fbc..9d7b0eb 100644
--- a/engines/xeen/module.mk
+++ b/engines/xeen/module.mk
@@ -7,6 +7,7 @@ MODULE_OBJS := \
 	debugger.o \
 	detection.o \
 	events.o \
+	font.o \
 	menus.o \
 	resdata.o \
 	resources.o \
diff --git a/engines/xeen/screen.cpp b/engines/xeen/screen.cpp
index 2da2412..757251a 100644
--- a/engines/xeen/screen.cpp
+++ b/engines/xeen/screen.cpp
@@ -158,7 +158,7 @@ void Window::addDirtyRect(const Common::Rect &r) {
  * Fill the content area of a window with the current background color 
  */
 void Window::fill() {
-	fillRect(_innerBounds, _bgColor);
+	fillRect(_innerBounds, _vm->_screen->_bgColor);
 }
 
 void Window::writeString(const Common::String &s) {
diff --git a/engines/xeen/screen.h b/engines/xeen/screen.h
index 907409d..4fd19d1 100644
--- a/engines/xeen/screen.h
+++ b/engines/xeen/screen.h
@@ -28,6 +28,7 @@
 #include "common/array.h"
 #include "common/queue.h"
 #include "common/rect.h"
+#include "xeen/font.h"
 #include "xeen/xsurface.h"
 
 namespace Xeen {
@@ -75,7 +76,7 @@ public:
 
 	void writeString(const Common::String &s);};
 
-class Screen: public XSurface {
+class Screen: public FontSurface {
 private:
 	XeenEngine *_vm;
 	Common::List<Common::Rect> _dirtyRects;
diff --git a/engines/xeen/xsurface.cpp b/engines/xeen/xsurface.cpp
index 5e7d831..cd21a58 100644
--- a/engines/xeen/xsurface.cpp
+++ b/engines/xeen/xsurface.cpp
@@ -27,23 +27,11 @@
 
 namespace Xeen {
 
-const byte *XSurface::_fontData;
-
-XSurface::XSurface() : Graphics::Surface(), _bgColor(DEFAULT_BG_COLOR), _fontReduced(false),
-		_fontJustify(JUSTIFY_NONE), _msgWraps(false) {
-	_textColors[0] = 0;
-	_textColors[1] = 0x40;
-	_textColors[2] = 0x30;
-	_textColors[3] = 0x20;
+XSurface::XSurface() : Graphics::Surface() {
 }
 
-XSurface::XSurface(int w, int h) : Graphics::Surface(), _bgColor(DEFAULT_BG_COLOR),
-		_fontReduced(false), _fontJustify(JUSTIFY_NONE), _msgWraps(false) {
+XSurface::XSurface(int w, int h) : Graphics::Surface() {
 	create(w, h);
-	_textColors[0] = 0;
-	_textColors[1] = 0x40;
-	_textColors[2] = 0x30;
-	_textColors[3] = 0x20;
 }
 
 XSurface::~XSurface() {
@@ -93,262 +81,4 @@ void XSurface::blitTo(XSurface &dest, const Common::Point &destPos) const {
 	dest.addDirtyRect(Common::Rect(destPos.x, destPos.y, destPos.x + w, destPos.y));
 }
 
-/**
- * Draws a symbol to the surface.
- * @param symbolId	Symbol number from 0 to 19
- */
-void XSurface::writeSymbol(int symbolId) {
-	const byte *srcP = &SYMBOLS[symbolId][0];
-
-	for (int yp = 0; yp < FONT_HEIGHT; ++yp) {
-		byte *destP = (byte *)getBasePtr(_writePos.x, _writePos.y + yp);
-
-		for (int xp = 0; xp < FONT_WIDTH; ++xp, ++destP) {
-			byte b = *srcP++;
-			if (b)
-				*destP = b;
-		}
-	}
-
-	_writePos.x += 8;
-}
-
-/**
- * Write a string to the surface
- * @param s			String to display
- * @param bounds	Window bounds to display string within
- * @returns			Any string remainder that couldn't be displayed
- * @remarks		Note that bounds is just used for wrapping purposes. Unless
- *		justification is set, the message will be written at _writePos
- */
-Common::String XSurface::writeString(const Common::String &s, const Common::Rect &bounds) {
-	_displayString = s.c_str();
-
-	for (;;) {
-		_msgWraps = false;
-		
-		// Get the size of the string that can be displayed on the likne
-		int xp = _fontJustify ? bounds.left : _writePos.x;
-		while (!getNextCharWidth(xp)) {
-			if (xp >= bounds.right) {
-				--_displayString;
-				_msgWraps = true;
-			}
-		}
-
-		// Get the end point of the text that can be displayed
-		const char *displayEnd = _displayString;
-		_displayString = s.c_str();
-
-		if (*displayEnd && _fontJustify != JUSTIFY_RIGHT && xp >= bounds.right) {
-			// Need to handle justification of text
-			// First, move backwards to find the end of the previous word
-			// for a convenient point to break the line at
-			const char *endP = displayEnd;
-			while (endP > _displayString && (*endP & 0x7f) != ' ')
-				--endP;
-
-			if (endP == _displayString) {
-				// There was no word breaks at all in the string
-				--displayEnd;
-				if (_fontJustify == JUSTIFY_NONE && _writePos.x != bounds.left) {
-					// Move to the next line
-					if (!newLine(bounds))
-						continue;
-					// Ran out of space to display string
-					break;
-				}
-			} else {
-				// Found word break, find end of previous word 
-				while (displayEnd > _displayString && (*displayEnd & 0x7f) == ' ')
-					--displayEnd;
-			}
-		}
-
-		// Main character display loop
-		while (_displayString <= displayEnd) {
-			char c = getNextChar();
-			
-			if (c == ' ') {
-				_writePos.x += _fontReduced ? 3 : 4;
-			} else if (c == '\r') {
-				fillRect(bounds, _bgColor);
-				_writePos = Common::Point(bounds.left, bounds.top);
-			} else if (c == 1) {
-				// Turn off reduced font mode
-				_fontReduced = false;
-			} else if (c == 2) {
-				// Turn on reduced font mode
-				_fontReduced = true;
-			} else if (c == 3) {
-				// Justify text
-				c = getNextChar();
-				if (c == 'r')
-					_fontJustify = JUSTIFY_RIGHT;
-				else if (c == 'c')
-					_fontJustify = JUSTIFY_CENTER;
-				else
-					_fontJustify = JUSTIFY_NONE;
-			} else if (c == 4) {
-				// Draw an empty box of a given width
-				int w = fontAtoi();
-				Common::Point pt = _writePos;
-				if (_fontJustify == JUSTIFY_RIGHT)
-					pt.x -= w;
-				fillRect(Common::Rect(pt.x, pt.y, pt.x + w, pt.y + (_fontReduced ? 9 : 10)),
-					_bgColor);
-			} else if (c == 5) {
-				continue;
-			} else if (c == 6) {
-				// Non-breakable space
-				writeChar(' ');
-			} else if (c == 7) {
-				// Set text background color
-				int c = fontAtoi();
-				_bgColor = (c < 0 || c > 255) ? DEFAULT_BG_COLOR : c;
-			} else if (c == 8) {
-				// Draw a character outline
-				c = getNextChar();
-				if (c == ' ') {
-					c = '\0';
-					_writePos.x -= 3;
-				} else {
-					if (c == 6)
-						c = ' ';
-					byte charSize = _fontData[0x1000 + (int)c + (_fontReduced ? 0x80 : 0)];
-					_writePos.x -= charSize;
-				}
-
-				if (_writePos.x < bounds.left)
-					_writePos.x = bounds.left;
-
-				if (c) {
-					int oldX = _writePos.x;
-					byte oldColor[4];
-					Common::copy(&_textColors[0], &_textColors[4], &oldColor[0]);
-
-					_textColors[1] = _textColors[2] = _textColors[3] = _bgColor;
-					writeChar(c);
-
-					Common::copy(&oldColor[0], &oldColor[4], &_textColors[0]);
-					_writePos.x = oldX;
-				}
-			} else if (c == 9) {
-				// Skip x position
-				int xp = fontAtoi();
-				_writePos.x = MIN(bounds.left + xp, (int)bounds.right);
-			} else if (c == 10) {
-				// Newline
-				if (newLine(bounds))
-					break;
-			} else if (c == 11) {
-				// Skip y position
-				int yp = fontAtoi(	);
-				_writePos.y = MIN(bounds.top + yp, (int)bounds.bottom);
-			} else if (c == 12) {
-				// Set text colors
-				int idx = fontAtoi();
-				if (idx < 0)
-					idx = 0;
-				setTextColor(idx);
-			} else if (c < ' ') {
-				// Invalid command
-				displayEnd = nullptr;
-				break;
-			} else {
-				// Standard character - write it out
-				writeChar(c);
-			}
-		}
-
-		if (_displayString > displayEnd && _fontJustify != JUSTIFY_RIGHT && _msgWraps
-				&& newLine(bounds))
-			break;
-	}
-
-	return Common::String(_displayString);
-}
-
-/**
- * Wrie a character to the surface
- */
-void XSurface::writeChar(char c) {
-	error("TODO");
-}
-
-/**
- * Return the next pending character to display
- */
-char XSurface::getNextChar() {
-	return  *_displayString++ & 0x7f;
-}
-
-/**
-* Return the width of a given character
-*/
-bool XSurface::getNextCharWidth(int &total) {
-	char c = getNextChar();
-
-	if (c > ' ') {
-		total += _fontData[0x1000 + (int)c + (_fontReduced ? 0x80 : 0)];
-		return false;
-	} else if (c == ' ') {
-		total += 4;
-		return false;
-	} else if (c == 8) {
-		c = getNextChar();
-		if (c == ' ') {
-			total -= 2;
-			return false;
-		} else {
-			_displayString -= 2;
-			return true;
-		}
-	} else if (c == 12) {
-		c = getNextChar();
-		if (c != 'd')
-			getNextChar();
-		return false;
-	} else {
-		--_displayString;
-		return true;
-	}
-}
-
-bool XSurface::newLine(const Common::Rect &bounds) {
-	// Move past any spaces currently being pointed to
-	while ((*_displayString & 0x7f) == ' ')
-		++_displayString;
-
-	_msgWraps = false;
-	_writePos.x = bounds.left;
-	
-	int h = _fontReduced ? 9 : 10;
-	_writePos.y += h;
-
-	return ((_writePos.y + h - 1) > bounds.bottom);
-}
-
-int XSurface::fontAtoi(int len) {
-	int total = 0;
-	for (int i = 0; i < len; ++i) {
-		char c = getNextChar();
-		if (c == ' ')
-			c = '0';
-
-		int digit = c - '0';
-		if (digit < 0 || digit > 9)
-			return -1;
-
-		total = total * 10 + digit;
-	}
-
-	return total;
-}
-
-void XSurface::setTextColor(int idx) {
-	const byte *colP = &TEXT_COLORS[idx][0];
-	Common::copy(colP, colP + 4, &_textColors[0]);
-}
-
 } // End of namespace Xeen
diff --git a/engines/xeen/xsurface.h b/engines/xeen/xsurface.h
index 6e88ae9..64cdab0 100644
--- a/engines/xeen/xsurface.h
+++ b/engines/xeen/xsurface.h
@@ -30,33 +30,7 @@
 
 namespace Xeen {
 
-#define FONT_WIDTH 8
-#define FONT_HEIGHT 8
-#define DEFAULT_BG_COLOR 0x99
-
-enum Justify { JUSTIFY_NONE = 0, JUSTIFY_CENTER = 1, JUSTIFY_RIGHT = 2 };
-
 class XSurface: public Graphics::Surface {
-private:
-	const char *_displayString;
-	bool _msgWraps;
-
-	char getNextChar();
-
-	bool getNextCharWidth(int &total);
-
-	bool newLine(const Common::Rect &bounds);
-
-	int fontAtoi(int len = 3);
-
-	void setTextColor(int idx);
-public:
-	static const byte *_fontData;
-	Common::Point _writePos;
-	byte _textColors[4];
-	byte _bgColor;
-	bool _fontReduced;
-	Justify _fontJustify;
 public:
 	virtual void addDirtyRect(const Common::Rect &r) {}
 public:
@@ -75,12 +49,6 @@ public:
 	void blitTo(XSurface &dest) const;
 
 	bool empty() const { return getPixels() == nullptr; }
-
-	void writeSymbol(int symbolId);
-
-	Common::String writeString(const Common::String &s, const Common::Rect &bounds);
-
-	void writeChar(char c);
 };
 
 } // End of namespace Xeen


Commit: 6e587578c64a7439c330dff09ee1205a97c5b24a
    https://github.com/scummvm/scummvm/commit/6e587578c64a7439c330dff09ee1205a97c5b24a
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2014-12-31T16:38:17-10:00

Commit Message:
XEEN: Implemented writeChar

Changed paths:
    engines/xeen/font.cpp



diff --git a/engines/xeen/font.cpp b/engines/xeen/font.cpp
index 2894bce..dd1b4dc 100644
--- a/engines/xeen/font.cpp
+++ b/engines/xeen/font.cpp
@@ -20,6 +20,7 @@
  *
  */
 
+#include "common/endian.h"
 #include "xeen/font.h"
 #include "xeen/resdata.h"
 
@@ -307,7 +308,29 @@ void FontSurface::setTextColor(int idx) {
  * Wrie a character to the surface
  */
 void FontSurface::writeChar(char c) {
-	error("TODO");
+	// Get y position, handling kerning
+	int y = _writePos.y;
+	if (c == 'g' || c == 'p' || c == 'q' || c == 'y')
+		++y;
+
+	// Get pointers into font data and surface to write pixels to
+	int charIndex = (int)c + (_fontReduced ? 0x80 : 0);
+	const byte *srcP = &_fontData[charIndex * 16];
+
+	for (int yp = 0; yp < FONT_HEIGHT; ++yp, ++y) {
+		uint16 lineData = READ_LE_UINT16(srcP); srcP += 2;
+		byte *destP = (byte *)getBasePtr(_writePos.x, y);
+
+		for (int xp = 0; xp < FONT_WIDTH; ++xp, ++destP) {
+			int colIndex = lineData & 3;
+			lineData >>= 2;
+
+			if (colIndex)
+				*destP = _textColors[colIndex];
+		}
+	}
+
+	_writePos.x += _fontData[0x1000 + charIndex];
 }
 
 } // End of namespace Xeen


Commit: 9eb229273668b96f63162cabfd769035f95e8a8b
    https://github.com/scummvm/scummvm/commit/9eb229273668b96f63162cabfd769035f95e8a8b
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2014-12-31T16:54:14-10:00

Commit Message:
XEEN: Compilation fixes

Changed paths:
    engines/xeen/menus.h
    engines/xeen/worldofxeen/worldofxeen_game.cpp
    engines/xeen/xeen.cpp



diff --git a/engines/xeen/menus.h b/engines/xeen/menus.h
index 07a7bb7..8cc004a 100644
--- a/engines/xeen/menus.h
+++ b/engines/xeen/menus.h
@@ -51,7 +51,7 @@ protected:
 	Common::Array<DialogButton> _buttons;
 	char _key;
 
-	virtual void doScroll(bool drawFlag, bool doFade) = 0;
+	virtual void doScroll(bool drawFlag, bool doFade);
 
 	void checkEvents();
 public:
@@ -78,7 +78,7 @@ private:
 protected:
 	OptionsMenu(XeenEngine *vm) : SettingsBaseDialog(vm) {}
 protected:
-	virtual void startup(Common::String &title1, Common::String &title2);
+	virtual void startup(Common::String &title1, Common::String &title2) = 0;
 
 	virtual void setBackground() {}
 
@@ -96,8 +96,6 @@ public:
 class CloudsOptionsMenu : public OptionsMenu {
 protected:
 	virtual void startup(Common::String &title1, Common::String &title2);
-
-	virtual void doScroll(bool drawFlag, bool doFade);
 public:
 	CloudsOptionsMenu(XeenEngine *vm) : OptionsMenu(vm) {}
 };
diff --git a/engines/xeen/worldofxeen/worldofxeen_game.cpp b/engines/xeen/worldofxeen/worldofxeen_game.cpp
index 8057331..bcfbaa1 100644
--- a/engines/xeen/worldofxeen/worldofxeen_game.cpp
+++ b/engines/xeen/worldofxeen/worldofxeen_game.cpp
@@ -30,15 +30,7 @@ WorldOfXeenEngine::WorldOfXeenEngine(OSystem *syst, const XeenGameDescription *g
 }
 
 void WorldOfXeenEngine::playGame () {
-	_screen->loadPalette("mm4.pal");
-	_screen->fadeIn(4);
-
-	//darkSideIntro();
-	_events->setCursor(0);
-	_events->showCursor();
-	while (!shouldQuit()) {
-		_events->pollEventsAndWait();
-	}
+	XeenEngine::playGame();
 }
 
 } // End of namespace Xeen
diff --git a/engines/xeen/xeen.cpp b/engines/xeen/xeen.cpp
index 505d9bd..372bbb1 100644
--- a/engines/xeen/xeen.cpp
+++ b/engines/xeen/xeen.cpp
@@ -28,6 +28,7 @@
 #include "graphics/scaler.h"
 #include "graphics/thumbnail.h"
 #include "xeen/xeen.h"
+#include "xeen/menus.h"
 #include "xeen/resources.h"
 
 namespace Xeen {
@@ -219,8 +220,7 @@ void XeenEngine::writeSavegameHeader(Common::OutSaveFile *out, XeenSavegameHeade
 }
 
 void XeenEngine::playGame() {
-	//showIntro();
-	
+	OptionsMenu::show(this);
 }
 
 } // End of namespace Xeen


Commit: 4a953b06619aae4eded66f868c0f48fb2330d8fa
    https://github.com/scummvm/scummvm/commit/4a953b06619aae4eded66f868c0f48fb2330d8fa
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2014-12-31T21:09:13-10:00

Commit Message:
XEEN: Startup fixes; options menu buttons now showing

Changed paths:
    engines/xeen/events.cpp
    engines/xeen/font.cpp
    engines/xeen/menus.cpp
    engines/xeen/menus.h
    engines/xeen/screen.cpp
    engines/xeen/screen.h
    engines/xeen/xeen.cpp
    engines/xeen/xsurface.cpp
    engines/xeen/xsurface.h



diff --git a/engines/xeen/events.cpp b/engines/xeen/events.cpp
index fd0871e..285005a 100644
--- a/engines/xeen/events.cpp
+++ b/engines/xeen/events.cpp
@@ -55,6 +55,7 @@ void EventsManager::setCursor(int cursorId) {
 	_sprites.draw(cursor, cursorId);
 
 	CursorMan.replaceCursor(cursor.getPixels(), cursor.w, cursor.h, 0, 0, 0);
+	showCursor();
 }
 
 /**
diff --git a/engines/xeen/font.cpp b/engines/xeen/font.cpp
index dd1b4dc..018536b 100644
--- a/engines/xeen/font.cpp
+++ b/engines/xeen/font.cpp
@@ -124,6 +124,7 @@ Common::String FontSurface::writeString(const Common::String &s, const Common::R
 				_writePos.x += _fontReduced ? 3 : 4;
 			} else if (c == '\r') {
 				fillRect(bounds, _bgColor);
+				addDirtyRect(bounds);
 				_writePos = Common::Point(bounds.left, bounds.top);
 			} else if (c == 1) {
 				// Turn off reduced font mode
@@ -146,8 +147,9 @@ Common::String FontSurface::writeString(const Common::String &s, const Common::R
 				Common::Point pt = _writePos;
 				if (_fontJustify == JUSTIFY_RIGHT)
 					pt.x -= w;
-				fillRect(Common::Rect(pt.x, pt.y, pt.x + w, pt.y + (_fontReduced ? 9 : 10)),
-					_bgColor);
+
+				Common::Rect r(pt.x, pt.y, pt.x + w, pt.y + (_fontReduced ? 9 : 10));
+				fillRect(r, _bgColor);
 			} else if (c == 5) {
 				continue;
 			} else if (c == 6) {
@@ -194,7 +196,7 @@ Common::String FontSurface::writeString(const Common::String &s, const Common::R
 					break;
 			} else if (c == 11) {
 				// Skip y position
-				int yp = fontAtoi(	);
+				int yp = fontAtoi();
 				_writePos.y = MIN(bounds.top + yp, (int)bounds.bottom);
 			} else if (c == 12) {
 				// Set text colors
@@ -330,6 +332,8 @@ void FontSurface::writeChar(char c) {
 		}
 	}
 
+	addDirtyRect(Common::Rect(_writePos.x, _writePos.y, _writePos.x + FONT_WIDTH,
+		_writePos.y + FONT_HEIGHT));
 	_writePos.x += _fontData[0x1000 + charIndex];
 }
 
diff --git a/engines/xeen/menus.cpp b/engines/xeen/menus.cpp
index 0a7b030..4e22268 100644
--- a/engines/xeen/menus.cpp
+++ b/engines/xeen/menus.cpp
@@ -43,8 +43,8 @@ void Dialog::restoreButtons() {
 	_buttons = _savedButtons.pop();
 }
 
-void Dialog::addButton(const Common::Rect &bounds, char c, SpriteResource *sprites, bool d) {
-	_buttons.push_back(DialogButton(bounds, c, sprites, d));
+void Dialog::addButton(const Common::Rect &bounds, char c, SpriteResource *sprites, bool draw = true) {
+	_buttons.push_back(DialogButton(bounds, c, sprites, draw));
 }
 
 void Dialog::checkEvents() {
@@ -118,9 +118,9 @@ void OptionsMenu::execute() {
 	startup(title1, title2);
 	SpriteResource title1Sprites(title1), title2Sprites(title2);
 
-	bool firstTime = true;
+	bool firstTime = true, doFade = true;
 	while (!_vm->shouldQuit()) {
-		setBackground();
+		setBackground(doFade);
 		events.setCursor(0);
 
 		if (firstTime) {
@@ -128,7 +128,7 @@ void OptionsMenu::execute() {
 			warning("TODO: Read existing save file");
 		}
 
-		for (;;) {
+		while (!_vm->shouldQuit()) {
 			showTitles1(title1Sprites);
 			showTitles2();
 
@@ -199,17 +199,17 @@ void OptionsMenu::showTitles2() {
 }
 
 void OptionsMenu::setupButtons(SpriteResource *buttons) {
-	addButton(Common::Rect(124, 87, 124 + 53, 87 + 10), 'S', buttons, true);
-	addButton(Common::Rect(126, 98, 126 + 47, 98 + 10), 'L', buttons, true);
-	addButton(Common::Rect(91, 110, 91 + 118, 110 + 10), 'C', buttons, true);
-	addButton(Common::Rect(85, 121, 85 + 131, 121 + 10), 'O', buttons, true);
+	addButton(Common::Rect(124, 87, 124 + 53, 87 + 10), 'S', buttons, false);
+	addButton(Common::Rect(126, 98, 126 + 47, 98 + 10), 'L', buttons, false);
+	addButton(Common::Rect(91, 110, 91 + 118, 110 + 10), 'C', buttons, false);
+	addButton(Common::Rect(85, 121, 85 + 131, 121 + 10), 'O', buttons, false);
 }
 
 void WorldOptionsMenu::setupButtons(SpriteResource *buttons) {
-	addButton(Common::Rect(93, 53, 93 + 134, 53 + 20), 'S', buttons, false);
-	addButton(Common::Rect(93, 78, 93 + 134, 78 + 20), 'L', buttons, false);
-	addButton(Common::Rect(93, 103, 93 + 134, 103 + 20), 'C', buttons, false);
-	addButton(Common::Rect(93, 128, 93 + 134, 128 + 20), 'O', buttons, false);
+	addButton(Common::Rect(93, 53, 93 + 134, 53 + 20), 'S', buttons, true);
+	addButton(Common::Rect(93, 78, 93 + 134, 78 + 20), 'L', buttons, true);
+	addButton(Common::Rect(93, 103, 93 + 134, 103 + 20), 'C', buttons, true);
+	addButton(Common::Rect(93, 128, 93 + 134, 128 + 20), 'O', buttons, true);
 }
 
 /*------------------------------------------------------------------------*/
@@ -337,15 +337,16 @@ void WorldOptionsMenu::startup(Common::String &title1, Common::String &title2) {
 	Screen &screen = *_vm->_screen;
 	screen.fadeOut(4);
 	screen.loadPalette("dark.pal");
-	screen.fadeIn(0x81);
 	_vm->_events->clearEvents();
 }
 
-void WorldOptionsMenu::setBackground() {
+void WorldOptionsMenu::setBackground(bool doFade) {
 	Screen &screen = *_vm->_screen;
 	screen.loadBackground("world.raw");
 	screen.saveBackground();
-	screen.fadeIn(4);	
+
+	if (doFade)
+		screen.fadeIn(4);	
 }
 
 void WorldOptionsMenu::openWindow() {
@@ -368,7 +369,7 @@ void WorldOptionsMenu::showContents(SpriteResource &title1, bool waitFlag) {
 
 	for (uint btnIndex = 0; btnIndex < _buttons.size(); ++btnIndex) {
 		DialogButton &btn = _buttons[btnIndex];
-		if (btn._d) {
+		if (btn._draw) {
 			btn._sprites->draw(screen._windows[0], btnIndex * 2,
 				Common::Point(btn._bounds.left, btn._bounds.top));
 		}
diff --git a/engines/xeen/menus.h b/engines/xeen/menus.h
index 8cc004a..65e3553 100644
--- a/engines/xeen/menus.h
+++ b/engines/xeen/menus.h
@@ -35,12 +35,12 @@ public:
 	Common::Rect _bounds;
 	SpriteResource *_sprites;
 	char _c;
-	bool _d;
+	bool _draw;
 
-	DialogButton(const Common::Rect &bounds, char c, SpriteResource *sprites, bool d) :
-		_bounds(bounds), _c(c), _sprites(sprites), _d(d) {}
+	DialogButton(const Common::Rect &bounds, char c, SpriteResource *sprites, bool draw) :
+		_bounds(bounds), _c(c), _sprites(sprites), _draw(draw) {}
 
-	DialogButton() : _c('\0'), _sprites(nullptr), _d(false) {}
+	DialogButton() : _c('\0'), _sprites(nullptr), _draw(false) {}
 };
 
 class Dialog {
@@ -63,7 +63,7 @@ public:
 
 	void restoreButtons();
 
-	void addButton(const Common::Rect &bounds, char c, SpriteResource *sprites, bool d);
+	void addButton(const Common::Rect &bounds, char c, SpriteResource *sprites, bool draw);
 };
 
 class SettingsBaseDialog : public Dialog {
@@ -80,7 +80,7 @@ protected:
 protected:
 	virtual void startup(Common::String &title1, Common::String &title2) = 0;
 
-	virtual void setBackground() {}
+	virtual void setBackground(bool doFade) {}
 
 	virtual void showTitles1(SpriteResource &sprites);
 
@@ -115,7 +115,7 @@ private:
 protected:
 	virtual void startup(Common::String &title1, Common::String &title2);
 
-	virtual void setBackground();
+	virtual void setBackground(bool doFade);
 
 	virtual void showTitles2() {}
 
diff --git a/engines/xeen/screen.cpp b/engines/xeen/screen.cpp
index 757251a..7b1dd1b 100644
--- a/engines/xeen/screen.cpp
+++ b/engines/xeen/screen.cpp
@@ -29,7 +29,7 @@
 
 namespace Xeen {
 
-Window::Window() : _vm(nullptr), _enabled(false), _a(0), _border(0),
+Window::Window() : _vm(nullptr),  _enabled(false), _a(0), _border(0),
 	_xLo(0), _xHi(0), _ycL(0), _ycH(0) {
 }
 
@@ -38,6 +38,7 @@ Window::Window(XeenEngine *vm, const Common::Rect &bounds, int a, int border,
 		_vm(vm), _enabled(false), _a(a), _border(border), 
 		_xLo(xLo), _ycL(ycL), _xHi(xHi), _ycH(ycH) {
 	setBounds(bounds);
+	create(_vm->_screen, Common::Rect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT));
 }
 
 void Window::setBounds(const Common::Rect &r) {
@@ -48,6 +49,7 @@ void Window::setBounds(const Common::Rect &r) {
 
 void Window::open() {
 	if (!_enabled) {
+		_enabled = true;
 		_vm->_screen->_windowStack.push_back(this);
 		open2();
 	}
@@ -58,10 +60,9 @@ void Window::open() {
 }
 
 void Window::open2() {
-	create(_bounds.width(), _bounds.height());
-	copyRectToSurface(*_vm->_screen, 0, 0, _bounds);
 	_dirtyRects.push(_bounds);
 	frame();
+	fill();
 }
 
 void Window::frame() {
@@ -173,7 +174,8 @@ void Window::writeString(const Common::String &s) {
 Screen::Screen(XeenEngine *vm) : _vm(vm) {
 	_fadeIn = false;
 	create(SCREEN_WIDTH, SCREEN_HEIGHT);
-	setupWindows();
+	Common::fill(&_tempPalette[0], &_tempPalette[PALETTE_SIZE], 0);
+	Common::fill(&_mainPalette[0], &_mainPalette[PALETTE_SIZE], 0);
 
 	// Load font data for the screen
 	File f("fnt");
@@ -257,6 +259,7 @@ void Screen::update() {
 }
 
 void Screen::addDirtyRect(const Common::Rect &r) {
+	assert(r.isValidRect() && r.width() > 0 && r.height() > 0);
 	_dirtyRects.push_back(r);
 }
 
@@ -304,7 +307,7 @@ bool Screen::unionRectangle(Common::Rect &destRect, const Common::Rect &src1, co
 void Screen::loadPalette(const Common::String &name) {
 	File f(name);
 	for (int i = 0; i < PALETTE_SIZE; ++i)
-		_tempPaltte[i] = f.readByte() << 2;
+		_tempPalette[i] = f.readByte() << 2;
 }
 
 /**
@@ -411,7 +414,7 @@ void Screen::fadeInner(int step) {
 		} else {
 			// Create a scaled palette from the temporary one
 			for (int i = 0; i < PALETTE_SIZE; ++i) {
-				_mainPalette[i] = (_tempPaltte[i] * val * 2) >> 8;
+				_mainPalette[i] = (_tempPalette[i] * val * 2) >> 8;
 			}
 
 			updatePalette();
@@ -438,7 +441,6 @@ void Screen::restoreBackground(int slot) {
 	assert(slot > 0 && slot < 10);
 
 	_savedScreens[slot - 1].blitTo(*this);
-	_savedScreens[slot - 1].free();
 }
 
 
diff --git a/engines/xeen/screen.h b/engines/xeen/screen.h
index 4fd19d1..41b2821 100644
--- a/engines/xeen/screen.h
+++ b/engines/xeen/screen.h
@@ -81,13 +81,11 @@ private:
 	XeenEngine *_vm;
 	Common::List<Common::Rect> _dirtyRects;
 	byte _mainPalette[PALETTE_SIZE];
-	byte _tempPaltte[PALETTE_SIZE];
+	byte _tempPalette[PALETTE_SIZE];
 	XSurface _pages[2];
 	XSurface _savedScreens[10];
 	bool _fadeIn;
 
-	void setupWindows();
-
 	void mergeDirtyRects();
 
 	bool unionRectangle(Common::Rect &destRect, const Common::Rect &src1, const Common::Rect &src2);
@@ -110,6 +108,8 @@ public:
 
 	virtual ~Screen();
 
+	void setupWindows();
+
 	void closeWindows();
 
 	void update();
@@ -132,9 +132,9 @@ public:
 
 	void fadeOut(int step);
 
-	void saveBackground(int slot = 0);
+	void saveBackground(int slot = 1);
 
-	void restoreBackground(int slot = 0);
+	void restoreBackground(int slot = 1);
 };
 
 } // End of namespace Xeen
diff --git a/engines/xeen/xeen.cpp b/engines/xeen/xeen.cpp
index 372bbb1..1027572 100644
--- a/engines/xeen/xeen.cpp
+++ b/engines/xeen/xeen.cpp
@@ -62,6 +62,7 @@ void XeenEngine::initialize() {
 	_debugger = new Debugger(this);
 	_events = new EventsManager(this);
 	_screen = new Screen(this);
+	_screen->setupWindows();
 	_sound = new SoundManager(this);
 
 	File f("029.obj");
diff --git a/engines/xeen/xsurface.cpp b/engines/xeen/xsurface.cpp
index cd21a58..dc42a6f 100644
--- a/engines/xeen/xsurface.cpp
+++ b/engines/xeen/xsurface.cpp
@@ -27,21 +27,34 @@
 
 namespace Xeen {
 
-XSurface::XSurface() : Graphics::Surface() {
+XSurface::XSurface() : Graphics::Surface(), _freeFlag(false) {
 }
 
-XSurface::XSurface(int w, int h) : Graphics::Surface() {
+XSurface::XSurface(int w, int h) : Graphics::Surface(), _freeFlag(false) {
 	create(w, h);
 }
 
 XSurface::~XSurface() {
-	free();
+	if (_freeFlag)
+		free();
 }
 
 void XSurface::create(uint16 w, uint16 h) {
 	Graphics::Surface::create(w, h, Graphics::PixelFormat::createFormatCLUT8());
+	_freeFlag = true;
 }
 
+void XSurface::create(XSurface *s, const Common::Rect &bounds) {
+	pixels = (byte *)s->getBasePtr(bounds.left, bounds.top);
+	format = Graphics::PixelFormat::createFormatCLUT8();
+	pitch = s->pitch;
+	w = bounds.width();
+	h = bounds.height();
+
+	_freeFlag = false;
+}
+
+
 void XSurface::transBlitTo(XSurface &dest) const {
 	transBlitTo(dest, Common::Point());
 }
@@ -78,7 +91,7 @@ void XSurface::blitTo(XSurface &dest, const Common::Point &destPos) const {
 		Common::copy(srcP, srcP + w, destP);
 	}
 
-	dest.addDirtyRect(Common::Rect(destPos.x, destPos.y, destPos.x + w, destPos.y));
+	dest.addDirtyRect(Common::Rect(destPos.x, destPos.y, destPos.x + w, destPos.y + h));
 }
 
 } // End of namespace Xeen
diff --git a/engines/xeen/xsurface.h b/engines/xeen/xsurface.h
index 64cdab0..263ea53 100644
--- a/engines/xeen/xsurface.h
+++ b/engines/xeen/xsurface.h
@@ -31,6 +31,8 @@
 namespace Xeen {
 
 class XSurface: public Graphics::Surface {
+private:
+	bool _freeFlag;
 public:
 	virtual void addDirtyRect(const Common::Rect &r) {}
 public:
@@ -40,6 +42,8 @@ public:
 
 	void create(uint16 w, uint16 h);
 
+	void create(XSurface *s, const Common::Rect &bounds);
+
 	void transBlitTo(XSurface &dest) const;
 
 	void transBlitTo(XSurface &dest, const Common::Point &destPos) const;


Commit: fb6e8054f7d669e6f2812b07e8d9bc7412c242f7
    https://github.com/scummvm/scummvm/commit/fb6e8054f7d669e6f2812b07e8d9bc7412c242f7
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2014-12-31T22:55:10-10:00

Commit Message:
XEEN: Fixes for text display

Changed paths:
    engines/xeen/font.cpp
    engines/xeen/menus.cpp
    engines/xeen/screen.cpp



diff --git a/engines/xeen/font.cpp b/engines/xeen/font.cpp
index 018536b..8b80ec2 100644
--- a/engines/xeen/font.cpp
+++ b/engines/xeen/font.cpp
@@ -76,22 +76,24 @@ Common::String FontSurface::writeString(const Common::String &s, const Common::R
 	assert(_fontData);
 
 	for (;;) {
+		const char *msgStartP = _displayString;
 		_msgWraps = false;
 		
-		// Get the size of the string that can be displayed on the likne
-		int xp = _fontJustify ? bounds.left : _writePos.x;
+		// Get the size of the string that can be displayed on the line
+		int xp = _fontJustify == JUSTIFY_CENTER ? bounds.left : _writePos.x;
 		while (!getNextCharWidth(xp)) {
 			if (xp >= bounds.right) {
 				--_displayString;
 				_msgWraps = true;
+				break;
 			}
 		}
 
 		// Get the end point of the text that can be displayed
 		const char *displayEnd = _displayString;
-		_displayString = s.c_str();
+		_displayString = msgStartP;
 
-		if (*displayEnd && _fontJustify != JUSTIFY_RIGHT && xp >= bounds.right) {
+		if (_msgWraps && _fontJustify != JUSTIFY_RIGHT && xp >= bounds.right) {
 			// Need to handle justification of text
 			// First, move backwards to find the end of the previous word
 			// for a convenient point to break the line at
@@ -116,6 +118,34 @@ Common::String FontSurface::writeString(const Common::String &s, const Common::R
 			}
 		}
 
+		// Justification adjustment
+		if (_fontJustify != JUSTIFY_NONE) {
+			// Figure out the width of the selected portion of the string
+			int totalWidth = 0;
+			while (!getNextCharWidth(totalWidth)) {
+				if (_displayString > displayEnd && *displayEnd == ' ') {
+					// Don't include any ending space as part of the total
+					totalWidth -= _fontReduced ? 4 : 5;
+				}
+			}
+
+			// Reset starting position back to the start of the string portion
+			_displayString = msgStartP;
+
+			if (_fontJustify == JUSTIFY_RIGHT) {
+				// Right aligned
+				if (_writePos.x == bounds.left)
+					_writePos.x = bounds.right;
+				_writePos.x -= totalWidth + 1;
+			} else {
+				// Center aligned
+				if (_writePos.x == bounds.left)
+					_writePos.x = (bounds.left + bounds.right + 1 - totalWidth) / 2;
+				else
+					_writePos.x = (_writePos.x * 2 - totalWidth) / 2;
+ 			}
+		}
+
 		// Main character display loop
 		while (_displayString <= displayEnd) {
 			char c = getNextChar();
@@ -195,18 +225,18 @@ Common::String FontSurface::writeString(const Common::String &s, const Common::R
 				if (newLine(bounds))
 					break;
 			} else if (c == 11) {
-				// Skip y position
+				// Set y position
 				int yp = fontAtoi();
 				_writePos.y = MIN(bounds.top + yp, (int)bounds.bottom);
 			} else if (c == 12) {
 				// Set text colors
-				int idx = fontAtoi();
+				int idx = fontAtoi(2);
 				if (idx < 0)
 					idx = 0;
 				setTextColor(idx);
 			} else if (c < ' ') {
-				// Invalid command
-				displayEnd = nullptr;
+				// End of string or invalid command
+				_displayString = nullptr;
 				break;
 			} else {
 				// Standard character - write it out
@@ -214,7 +244,9 @@ Common::String FontSurface::writeString(const Common::String &s, const Common::R
 			}
 		}
 
-		if (_displayString > displayEnd && _fontJustify != JUSTIFY_RIGHT && _msgWraps
+		if (!_displayString)
+			break;
+		if ( _displayString > displayEnd && _fontJustify != JUSTIFY_RIGHT && _msgWraps
 				&& newLine(bounds))
 			break;
 	}
diff --git a/engines/xeen/menus.cpp b/engines/xeen/menus.cpp
index 4e22268..ea2904a 100644
--- a/engines/xeen/menus.cpp
+++ b/engines/xeen/menus.cpp
@@ -362,9 +362,9 @@ void WorldOptionsMenu::showContents(SpriteResource &title1, bool waitFlag) {
 	title1.draw(screen._windows[0], 0);
 	screen._windows[28].frame();
 
-	screen._windows[28].writeString("\r\x01\x03c\fdMight and Magic Options\n"
+	screen._windows[28].writeString("\x0D\x01\003c\014dMight and Magic Options\n"
 		"World of Xeen\x02\n"
-		"117Copyright (c) 1993 NWC, Inc.\n"
+		"\v117Copyright (c) 1993 NWC, Inc.\n"
 		"All Rights Reserved\x01");
 
 	for (uint btnIndex = 0; btnIndex < _buttons.size(); ++btnIndex) {
diff --git a/engines/xeen/screen.cpp b/engines/xeen/screen.cpp
index 7b1dd1b..6d5caae 100644
--- a/engines/xeen/screen.cpp
+++ b/engines/xeen/screen.cpp
@@ -259,7 +259,8 @@ void Screen::update() {
 }
 
 void Screen::addDirtyRect(const Common::Rect &r) {
-	assert(r.isValidRect() && r.width() > 0 && r.height() > 0);
+	assert(r.isValidRect() && r.width() > 0 && r.height() > 0
+		&& r.right <= SCREEN_WIDTH && r.bottom <= SCREEN_HEIGHT);
 	_dirtyRects.push_back(r);
 }
 


Commit: 4dd8c68df227654329601dc06ba5eccdcafa45f0
    https://github.com/scummvm/scummvm/commit/4dd8c68df227654329601dc06ba5eccdcafa45f0
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2014-12-31T23:13:49-10:00

Commit Message:
XEEN: Fix background animation for Options menu

Changed paths:
    engines/xeen/menus.cpp



diff --git a/engines/xeen/menus.cpp b/engines/xeen/menus.cpp
index ea2904a..68ef87a 100644
--- a/engines/xeen/menus.cpp
+++ b/engines/xeen/menus.cpp
@@ -75,9 +75,7 @@ void Dialog::checkEvents() {
 /*------------------------------------------------------------------------*/
 
 void SettingsBaseDialog::showContents(SpriteResource &title1, bool waitFlag) {
-	while (!_vm->shouldQuit() && _key == Common::KEYCODE_INVALID) {
-		checkEvents();
-	}
+	checkEvents();
 }
 
 /*------------------------------------------------------------------------*/
@@ -138,8 +136,11 @@ void OptionsMenu::execute() {
 			openWindow();
 
 			while (!_vm->shouldQuit()) {
-				showContents(title1Sprites, true);
-				
+				// Show the dialog with a continually animating background
+				while (!_vm->shouldQuit() && _key == Common::KEYCODE_INVALID)
+					showContents(title1Sprites, true);
+				if (_vm->shouldQuit())
+					return;
 			}
 		}
 	}
@@ -157,7 +158,7 @@ void OptionsMenu::showTitles1(SpriteResource &sprites) {
 		screen.restoreBackground();
 		sprites.draw(screen, frameNum);
 
-		while (events.timeElapsed() == 0)
+		while (events.timeElapsed() < 4)
 			events.pollEventsAndWait();
 	}
 }
@@ -356,12 +357,14 @@ void WorldOptionsMenu::openWindow() {
 void WorldOptionsMenu::showContents(SpriteResource &title1, bool waitFlag) {
 	Screen &screen = *_vm->_screen;
 	EventsManager &events = *_vm->_events;
-	
 	events.updateGameCounter();
+	
+	// Draw the background frame in a continous cycle
 	_bgFrame = ++_bgFrame % 5;
-	title1.draw(screen._windows[0], 0);
-	screen._windows[28].frame();
+	title1.draw(screen._windows[0], _bgFrame);
 
+	// Draw the basic frame for the optitons menu and title text
+	screen._windows[28].frame();
 	screen._windows[28].writeString("\x0D\x01\003c\014dMight and Magic Options\n"
 		"World of Xeen\x02\n"
 		"\v117Copyright (c) 1993 NWC, Inc.\n"
@@ -377,7 +380,11 @@ void WorldOptionsMenu::showContents(SpriteResource &title1, bool waitFlag) {
 
 	if (waitFlag) {
 		screen._windows[0].update();
-		SettingsBaseDialog::showContents(title1, true);
+
+		while (!_vm->shouldQuit() && _key == Common::KEYCODE_INVALID &&
+				events.timeElapsed() < 3) {
+			checkEvents();
+		}
 	}
 }
 


Commit: def7e9f098436f64887bdc14944c6235e0a12cc1
    https://github.com/scummvm/scummvm/commit/def7e9f098436f64887bdc14944c6235e0a12cc1
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-01-01T00:18:38-10:00

Commit Message:
XEEN: Fix clicking to have Options menu appear

Changed paths:
    engines/xeen/menus.cpp



diff --git a/engines/xeen/menus.cpp b/engines/xeen/menus.cpp
index 68ef87a..92badb9 100644
--- a/engines/xeen/menus.cpp
+++ b/engines/xeen/menus.cpp
@@ -158,8 +158,7 @@ void OptionsMenu::showTitles1(SpriteResource &sprites) {
 		screen.restoreBackground();
 		sprites.draw(screen, frameNum);
 
-		while (events.timeElapsed() < 4)
-			events.pollEventsAndWait();
+		events.wait(4, true);
 	}
 }
 


Commit: 64ccc21cefefa585fe9227f453b5e370e6a62b8b
    https://github.com/scummvm/scummvm/commit/64ccc21cefefa585fe9227f453b5e370e6a62b8b
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-01-01T09:50:14-10:00

Commit Message:
XEEN: Fix options menu to show correct buttons

Changed paths:
    engines/xeen/resources.cpp



diff --git a/engines/xeen/resources.cpp b/engines/xeen/resources.cpp
index 4da84c1..ba2889f 100644
--- a/engines/xeen/resources.cpp
+++ b/engines/xeen/resources.cpp
@@ -195,13 +195,10 @@ bool CCArchive::getHeaderEntry(const Common::String &resourceName, CCEntry &ccEn
 void Resources::init(XeenEngine *vm) {
 	Common::File f;
 
-	const char *ARCHIVES[3] = { "xeen", "dark", "intro" };
-	for (int i = 0; i < 3; ++i) {
-		Common::String filename = Common::String::format("%s.cc", ARCHIVES[i]);
-		if (f.exists(filename)) {
-			SearchMan.add(ARCHIVES[i], new CCArchive(filename));
-		}
-	}
+	if (vm->getGameID() != GType_Clouds)
+		SearchMan.add("dark", new CCArchive("dark.cc"));
+	SearchMan.add("xeen", new CCArchive("xeen.cc"));
+	SearchMan.add("intro", new CCArchive("intro.cc"));
 }
 
 /*------------------------------------------------------------------------*/


Commit: fe48af7de5207cdc8a3e2ad769f6722b345b2877
    https://github.com/scummvm/scummvm/commit/fe48af7de5207cdc8a3e2ad769f6722b345b2877
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-01-01T11:10:26-10:00

Commit Message:
XEEN: Split up menus file into dialogs and dialogs_options

Changed paths:
  A engines/xeen/dialogs.cpp
  A engines/xeen/dialogs.h
  A engines/xeen/dialogs_options.cpp
  A engines/xeen/dialogs_options.h
  R engines/xeen/menus.cpp
  R engines/xeen/menus.h
    engines/xeen/module.mk
    engines/xeen/xeen.cpp



diff --git a/engines/xeen/dialogs.cpp b/engines/xeen/dialogs.cpp
new file mode 100644
index 0000000..1342353
--- /dev/null
+++ b/engines/xeen/dialogs.cpp
@@ -0,0 +1,83 @@
+/* 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.h"
+
+namespace Xeen {
+
+/**
+ * Saves the current list of buttons
+ */
+void Dialog::saveButtons() {
+	_savedButtons.push(_buttons);
+}
+
+/*
+ * Clears the current list of defined buttons
+ */
+void Dialog::clearButtons() {
+	_buttons.clear();
+}
+
+void Dialog::restoreButtons() {
+	_buttons = _savedButtons.pop();
+}
+
+void Dialog::addButton(const Common::Rect &bounds, char c, SpriteResource *sprites, bool draw = true) {
+	_buttons.push_back(DialogButton(bounds, c, sprites, draw));
+}
+
+void Dialog::checkEvents() {
+	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)) {
+				_key = _buttons[i]._c;
+				return;
+			}
+		}
+	} else if (events.isKeyPending()) {
+		Common::KeyState keyState;
+		events.getKey(keyState);
+		if (keyState.ascii >= 32 && keyState.ascii <= 127) {
+			_key = keyState.ascii;
+			return;
+		}
+	}
+}
+
+/*------------------------------------------------------------------------*/
+
+void SettingsBaseDialog::showContents(SpriteResource &title1, bool waitFlag) {
+	checkEvents();
+}
+
+/*------------------------------------------------------------------------*/
+
+} // End of namespace Xeen
diff --git a/engines/xeen/dialogs.h b/engines/xeen/dialogs.h
new file mode 100644
index 0000000..21bf57c
--- /dev/null
+++ b/engines/xeen/dialogs.h
@@ -0,0 +1,78 @@
+/* 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_H
+#define XEEN_DIALOGS_H
+
+#include "common/array.h"
+#include "common/stack.h"
+#include "common/rect.h"
+#include "xeen/xeen.h"
+
+namespace Xeen {
+
+class DialogButton {
+public:
+	Common::Rect _bounds;
+	SpriteResource *_sprites;
+	char _c;
+	bool _draw;
+
+	DialogButton(const Common::Rect &bounds, char c, SpriteResource *sprites, bool draw) :
+		_bounds(bounds), _c(c), _sprites(sprites), _draw(draw) {}
+
+	DialogButton() : _c('\0'), _sprites(nullptr), _draw(false) {}
+};
+
+class Dialog {
+private:
+	Common::Stack< Common::Array<DialogButton> > _savedButtons;
+protected:
+	XeenEngine *_vm;
+	Common::Array<DialogButton> _buttons;
+	char _key;
+
+	virtual void doScroll(bool drawFlag, bool doFade);
+
+	void checkEvents();
+public:
+	Dialog(XeenEngine *vm): _vm(vm), _key('\0') {}
+
+	void saveButtons();
+
+	void clearButtons();
+
+	void restoreButtons();
+
+	void addButton(const Common::Rect &bounds, char c, SpriteResource *sprites, bool draw);
+};
+
+class SettingsBaseDialog : public Dialog {
+protected:
+	virtual void showContents(SpriteResource &title1, bool mode);
+public:
+	SettingsBaseDialog(XeenEngine *vm) : Dialog(vm) {}
+};
+
+} // End of namespace Xeen
+
+#endif /* XEEN_DIALOGS_H */
diff --git a/engines/xeen/dialogs_options.cpp b/engines/xeen/dialogs_options.cpp
new file mode 100644
index 0000000..e4ebf27
--- /dev/null
+++ b/engines/xeen/dialogs_options.cpp
@@ -0,0 +1,343 @@
+/* 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_options.h"
+
+namespace Xeen {
+
+void OptionsMenu::show(XeenEngine *vm) {
+	OptionsMenu *menu;
+
+	switch (vm->getGameID()) {
+	case GType_Clouds:
+		menu = new CloudsOptionsMenu(vm);
+		break;
+	case GType_DarkSide:
+		menu = new DarkSideOptionsMenu(vm);
+		break;
+	case GType_WorldOfXeen:
+		menu = new WorldOptionsMenu(vm);
+		break;
+	default:
+		error("Unsupported game");
+		break;
+	}
+
+	menu->execute();
+	delete menu;
+}
+
+void OptionsMenu::execute() {
+	SpriteResource special("special.icn");
+	Screen &screen = *_vm->_screen;
+	EventsManager &events = *_vm->_events;
+	
+	File newBright("newbrigh.m");
+	_vm->_sound->playMusic(newBright);
+
+	screen._windows[28].setBounds(Common::Rect(72, 25, 248, 175));
+
+	Common::String title1, title2;
+	startup(title1, title2);
+	SpriteResource title1Sprites(title1), title2Sprites(title2);
+
+	bool firstTime = true, doFade = true;
+	while (!_vm->shouldQuit()) {
+		setBackground(doFade);
+		events.setCursor(0);
+
+		if (firstTime) {
+			firstTime = false;
+			warning("TODO: Read existing save file");
+		}
+
+		showTitles1(title1Sprites);
+		showTitles2();
+
+		clearButtons();
+		setupButtons(&title2Sprites);
+		openWindow();
+
+		while (!_vm->shouldQuit()) {
+			// Show the dialog with a continually animating background
+			while (!_vm->shouldQuit() && _key == '\0')
+				showContents(title1Sprites, true);
+			if (_vm->shouldQuit())
+				return;
+
+			// Handle keypress
+			switch (toupper(_key)) {
+			case 'C':
+			case 'V':
+				// Show credits
+				break;
+			default:
+				break;
+			}
+			_key = '\0';
+		}
+	}
+}
+
+void OptionsMenu::showTitles1(SpriteResource &sprites) {
+	Screen &screen = *_vm->_screen;
+	EventsManager &events = *_vm->_events;
+
+	int frameNum = 0;
+	while (!_vm->shouldQuit() && !events.isKeyMousePressed()) {
+		events.updateGameCounter();
+
+		frameNum = ++frameNum % (_vm->getGameID() == GType_WorldOfXeen ? 5 : 10);
+		screen.restoreBackground();
+		sprites.draw(screen, frameNum);
+
+		events.wait(4, true);
+	}
+}
+
+void OptionsMenu::showTitles2() {
+	Screen &screen = *_vm->_screen;
+	EventsManager &events = *_vm->_events;
+	SoundManager &sound = *_vm->_sound;
+
+	File voc("elect.voc");
+	SpriteResource titleSprites("title2b.raw");
+	SpriteResource kludgeSprites("kludge.int");
+	SpriteResource title2Sprites[8] = {
+		SpriteResource("title2b.int"), SpriteResource("title2c.int"),
+		SpriteResource("title2d.int"), SpriteResource("title2e.int"),
+		SpriteResource("title2f.int"), SpriteResource("title2g.int"),
+		SpriteResource("title2h.int"), SpriteResource("title2i.int"),
+	};
+
+	kludgeSprites.draw(screen, 0);
+	screen.saveBackground();
+	sound.playSample(&voc, 0);
+
+	for (int i = 0; i < 30 && !_vm->shouldQuit(); ++i) {
+		events.updateGameCounter();
+		screen.restoreBackground();
+		title2Sprites[i / 4].draw(screen, i % 4);
+		screen._windows[0].update();
+
+		if (i == 19)
+			sound.playSample(nullptr, 0);
+
+		while (!_vm->shouldQuit() && events.timeElapsed() < 2)
+			events.pollEventsAndWait();
+	}
+
+	screen.restoreBackground();
+	screen._windows[0].update();
+}
+
+void OptionsMenu::setupButtons(SpriteResource *buttons) {
+	addButton(Common::Rect(124, 87, 124 + 53, 87 + 10), 'S', buttons, false);
+	addButton(Common::Rect(126, 98, 126 + 47, 98 + 10), 'L', buttons, false);
+	addButton(Common::Rect(91, 110, 91 + 118, 110 + 10), 'C', buttons, false);
+	addButton(Common::Rect(85, 121, 85 + 131, 121 + 10), 'O', buttons, false);
+}
+
+void WorldOptionsMenu::setupButtons(SpriteResource *buttons) {
+	addButton(Common::Rect(93, 53, 93 + 134, 53 + 20), 'S', buttons, true);
+	addButton(Common::Rect(93, 78, 93 + 134, 78 + 20), 'L', buttons, true);
+	addButton(Common::Rect(93, 103, 93 + 134, 103 + 20), 'C', buttons, true);
+	addButton(Common::Rect(93, 128, 93 + 134, 128 + 20), 'O', buttons, true);
+}
+
+/*------------------------------------------------------------------------*/
+
+void CloudsOptionsMenu::startup(Common::String &title1, Common::String &title2) {
+	title1 = "title1.int";
+	title2 = "title1a.int";
+}
+
+/**
+* Draws the scroll in the background
+*/
+void Dialog::doScroll(bool drawFlag, bool doFade) {
+	Screen &screen = *_vm->_screen;
+	EventsManager &events = *_vm->_events;
+	const int SCROLL_L[8] = { 29, 23, 15, 251, 245, 233, 207, 185 };
+	const int SCROLL_R[8] = { 165, 171, 198, 218, 228, 245, 264, 281 };
+
+	saveButtons();
+	clearButtons();
+	screen.saveBackground();
+
+	// Load hand vga files
+	SpriteResource *hand[16];
+	for (int i = 0; i < 16; ++i) {
+		Common::String name = Common::String::format("hand%02u.vga");
+		hand[i] = new SpriteResource(name);
+	}
+
+	// Load marb vga files
+	SpriteResource *marb[5];
+	for (int i = 1; i < 5; ++i) {
+		Common::String name = Common::String::format("marb%02u.vga");
+		marb[i] = new SpriteResource(name);
+	}
+
+	if (drawFlag) {
+		for (int i = 22; i > 0; --i) {
+			events.updateGameCounter();
+			screen.restoreBackground();
+
+			if (i > 0 && i <= 14) {
+				hand[i - 1]->draw(screen, 0);
+			} else {
+				// TODO: Check '800h'.. horizontal reverse maybe?
+				hand[14]->draw(screen, 0, Common::Point(SCROLL_L[i - 14], 0));
+				marb[15]->draw(screen, 0, Common::Point(SCROLL_R[i - 14], 0));
+			}
+
+			if (i <= 20) {
+				marb[i / 5]->draw(screen, i % 5);
+			}
+
+			while (!_vm->shouldQuit() && _vm->_events->timeElapsed() == 0)
+				_vm->_events->pollEventsAndWait();
+
+			screen._windows[0].update();
+			if (i == 0 && doFade)
+				screen.fadeIn(2);
+		}
+	} else {
+		for (int i = 0; i < 22 && !events.isKeyMousePressed(); ++i) {
+			events.updateGameCounter();
+			screen.restoreBackground();
+
+			if (i < 14) {
+				hand[i]->draw(screen, 0);
+			}
+			else {
+				// TODO: Check '800h'.. horizontal reverse maybe?
+				hand[14]->draw(screen, 0, Common::Point(SCROLL_L[i - 7], 0));
+				marb[15]->draw(screen, 0, Common::Point(SCROLL_R[i - 7], 0));
+			}
+
+			if (i < 20) {
+				marb[i / 5]->draw(screen, i % 5);
+			}
+
+			while (!_vm->shouldQuit() && _vm->_events->timeElapsed() == 0)
+				_vm->_events->pollEventsAndWait();
+
+			screen._windows[0].update();
+			if (i == 0 && doFade)
+				screen.fadeIn(2);
+		}
+	}
+
+	if (drawFlag) {
+		hand[0]->draw(screen, 0);
+		marb[0]->draw(screen, 0);
+	} else {
+		screen.restoreBackground();
+	}
+
+	screen._windows[0].update();
+	restoreButtons();
+
+	// Free resources
+	for (int i = 1; i < 5; ++i)
+		delete marb[i];
+	for (int i = 0; i < 16; ++i)
+		delete hand[i];
+}
+
+/*------------------------------------------------------------------------*/
+
+void DarkSideOptionsMenu::startup(Common::String &title1, Common::String &title2) {
+	title1 = "title2.int";
+	title2 = "title2a.int";
+}
+
+/**
+* Draws the scroll in the background
+*/
+void DarkSideOptionsMenu::doScroll(bool drawFlag, bool doFade) {
+	if (doFade) {
+		_vm->_screen->fadeIn(2);
+	}
+}
+
+void WorldOptionsMenu::startup(Common::String &title1, Common::String &title2) {
+	title1 = "world.int";
+	title2 = "start.icn";
+
+	Screen &screen = *_vm->_screen;
+	screen.fadeOut(4);
+	screen.loadPalette("dark.pal");
+	_vm->_events->clearEvents();
+}
+
+void WorldOptionsMenu::setBackground(bool doFade) {
+	Screen &screen = *_vm->_screen;
+	screen.loadBackground("world.raw");
+	screen.saveBackground();
+
+	if (doFade)
+		screen.fadeIn(4);	
+}
+
+void WorldOptionsMenu::openWindow() {
+	_vm->_screen->_windows[28].open();
+}
+
+void WorldOptionsMenu::showContents(SpriteResource &title1, bool waitFlag) {
+	Screen &screen = *_vm->_screen;
+	EventsManager &events = *_vm->_events;
+	events.updateGameCounter();
+	
+	// Draw the background frame in a continous cycle
+	_bgFrame = ++_bgFrame % 5;
+	title1.draw(screen._windows[0], _bgFrame);
+
+	// Draw the basic frame for the optitons menu and title text
+	screen._windows[28].frame();
+	screen._windows[28].writeString("\x0D\x01\003c\014dMight and Magic Options\n"
+		"World of Xeen\x02\n"
+		"\v117Copyright (c) 1993 NWC, Inc.\n"
+		"All Rights Reserved\x01");
+
+	for (uint btnIndex = 0; btnIndex < _buttons.size(); ++btnIndex) {
+		DialogButton &btn = _buttons[btnIndex];
+		if (btn._draw) {
+			btn._sprites->draw(screen._windows[0], btnIndex * 2,
+				Common::Point(btn._bounds.left, btn._bounds.top));
+		}
+	}
+
+	if (waitFlag) {
+		screen._windows[0].update();
+
+		while (!_vm->shouldQuit() && _key == Common::KEYCODE_INVALID &&
+				events.timeElapsed() < 3) {
+			checkEvents();
+		}
+	}
+}
+
+} // End of namespace Xeen
diff --git a/engines/xeen/dialogs_options.h b/engines/xeen/dialogs_options.h
new file mode 100644
index 0000000..591ab5e
--- /dev/null
+++ b/engines/xeen/dialogs_options.h
@@ -0,0 +1,89 @@
+/* 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_OPTIONS_H
+#define XEEN_DIALOGS_OPTIONS_H
+
+#include "xeen/xeen.h"
+#include "xeen/dialogs.h"
+
+namespace Xeen {
+
+class OptionsMenu : public SettingsBaseDialog {
+private:
+	void execute();
+protected:
+	OptionsMenu(XeenEngine *vm) : SettingsBaseDialog(vm) {}
+protected:
+	virtual void startup(Common::String &title1, Common::String &title2) = 0;
+
+	virtual void setBackground(bool doFade) {}
+
+	virtual void showTitles1(SpriteResource &sprites);
+
+	virtual void showTitles2();
+
+	virtual void setupButtons(SpriteResource *buttons);
+
+	virtual void openWindow() {}
+public:
+	static void show(XeenEngine *vm);
+};
+
+class CloudsOptionsMenu : public OptionsMenu {
+protected:
+	virtual void startup(Common::String &title1, Common::String &title2);
+public:
+	CloudsOptionsMenu(XeenEngine *vm) : OptionsMenu(vm) {}
+};
+
+class DarkSideOptionsMenu : public OptionsMenu {
+protected:
+	virtual void startup(Common::String &title1, Common::String &title2);
+
+	virtual void doScroll(bool drawFlag, bool doFade);
+public:
+	DarkSideOptionsMenu(XeenEngine *vm) : OptionsMenu(vm) {}
+};
+
+class WorldOptionsMenu : public DarkSideOptionsMenu {
+private:
+	int _bgFrame;
+protected:
+	virtual void startup(Common::String &title1, Common::String &title2);
+
+	virtual void setBackground(bool doFade);
+
+	virtual void showTitles2() {}
+
+	virtual void setupButtons(SpriteResource *buttons);
+
+	virtual void openWindow();
+
+	virtual void showContents(SpriteResource &title1, bool mode);
+public:
+	WorldOptionsMenu(XeenEngine *vm) : DarkSideOptionsMenu(vm), _bgFrame(0) {}
+};
+
+} // End of namespace Xeen
+
+#endif /* XEEN_DIALOGS_H */
diff --git a/engines/xeen/menus.cpp b/engines/xeen/menus.cpp
deleted file mode 100644
index 92badb9..0000000
--- a/engines/xeen/menus.cpp
+++ /dev/null
@@ -1,390 +0,0 @@
-/* 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/menus.h"
-
-namespace Xeen {
-
-/**
- * Saves the current list of buttons
- */
-void Dialog::saveButtons() {
-	_savedButtons.push(_buttons);
-}
-
-/*
- * Clears the current list of defined buttons
- */
-void Dialog::clearButtons() {
-	_buttons.clear();
-}
-
-void Dialog::restoreButtons() {
-	_buttons = _savedButtons.pop();
-}
-
-void Dialog::addButton(const Common::Rect &bounds, char c, SpriteResource *sprites, bool draw = true) {
-	_buttons.push_back(DialogButton(bounds, c, sprites, draw));
-}
-
-void Dialog::checkEvents() {
-	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)) {
-				_key = _buttons[i]._c;
-				return;
-			}
-		}
-	} else if (events.isKeyPending()) {
-		Common::KeyState keyState;
-		events.getKey(keyState);
-		if (keyState.ascii >= 32 && keyState.ascii <= 127) {
-			_key = keyState.ascii;
-			return;
-		}
-	}
-}
-
-/*------------------------------------------------------------------------*/
-
-void SettingsBaseDialog::showContents(SpriteResource &title1, bool waitFlag) {
-	checkEvents();
-}
-
-/*------------------------------------------------------------------------*/
-
-void OptionsMenu::show(XeenEngine *vm) {
-	OptionsMenu *menu;
-
-	switch (vm->getGameID()) {
-	case GType_Clouds:
-		menu = new CloudsOptionsMenu(vm);
-		break;
-	case GType_DarkSide:
-		menu = new DarkSideOptionsMenu(vm);
-		break;
-	case GType_WorldOfXeen:
-		menu = new WorldOptionsMenu(vm);
-		break;
-	default:
-		error("Unsupported game");
-		break;
-	}
-
-	menu->execute();
-	delete menu;
-}
-
-void OptionsMenu::execute() {
-	SpriteResource special("special.icn");
-	Screen &screen = *_vm->_screen;
-	EventsManager &events = *_vm->_events;
-	
-	File newBright("newbrigh.m");
-	_vm->_sound->playMusic(newBright);
-
-	screen._windows[28].setBounds(Common::Rect(72, 25, 248, 175));
-
-	Common::String title1, title2;
-	startup(title1, title2);
-	SpriteResource title1Sprites(title1), title2Sprites(title2);
-
-	bool firstTime = true, doFade = true;
-	while (!_vm->shouldQuit()) {
-		setBackground(doFade);
-		events.setCursor(0);
-
-		if (firstTime) {
-			firstTime = false;
-			warning("TODO: Read existing save file");
-		}
-
-		while (!_vm->shouldQuit()) {
-			showTitles1(title1Sprites);
-			showTitles2();
-
-		reopen:
-			clearButtons();
-			setupButtons(&title2Sprites);
-			openWindow();
-
-			while (!_vm->shouldQuit()) {
-				// Show the dialog with a continually animating background
-				while (!_vm->shouldQuit() && _key == Common::KEYCODE_INVALID)
-					showContents(title1Sprites, true);
-				if (_vm->shouldQuit())
-					return;
-			}
-		}
-	}
-}
-
-void OptionsMenu::showTitles1(SpriteResource &sprites) {
-	Screen &screen = *_vm->_screen;
-	EventsManager &events = *_vm->_events;
-
-	int frameNum = 0;
-	while (!_vm->shouldQuit() && !events.isKeyMousePressed()) {
-		events.updateGameCounter();
-
-		frameNum = ++frameNum % (_vm->getGameID() == GType_WorldOfXeen ? 5 : 10);
-		screen.restoreBackground();
-		sprites.draw(screen, frameNum);
-
-		events.wait(4, true);
-	}
-}
-
-void OptionsMenu::showTitles2() {
-	Screen &screen = *_vm->_screen;
-	EventsManager &events = *_vm->_events;
-	SoundManager &sound = *_vm->_sound;
-
-	File voc("elect.voc");
-	SpriteResource titleSprites("title2b.raw");
-	SpriteResource kludgeSprites("kludge.int");
-	SpriteResource title2Sprites[8] = {
-		SpriteResource("title2b.int"), SpriteResource("title2c.int"),
-		SpriteResource("title2d.int"), SpriteResource("title2e.int"),
-		SpriteResource("title2f.int"), SpriteResource("title2g.int"),
-		SpriteResource("title2h.int"), SpriteResource("title2i.int"),
-	};
-
-	kludgeSprites.draw(screen, 0);
-	screen.saveBackground();
-	sound.playSample(&voc, 0);
-
-	for (int i = 0; i < 30 && !_vm->shouldQuit(); ++i) {
-		events.updateGameCounter();
-		screen.restoreBackground();
-		title2Sprites[i / 4].draw(screen, i % 4);
-		screen._windows[0].update();
-
-		if (i == 19)
-			sound.playSample(nullptr, 0);
-
-		while (!_vm->shouldQuit() && events.timeElapsed() < 2)
-			events.pollEventsAndWait();
-	}
-
-	screen.restoreBackground();
-	screen._windows[0].update();
-}
-
-void OptionsMenu::setupButtons(SpriteResource *buttons) {
-	addButton(Common::Rect(124, 87, 124 + 53, 87 + 10), 'S', buttons, false);
-	addButton(Common::Rect(126, 98, 126 + 47, 98 + 10), 'L', buttons, false);
-	addButton(Common::Rect(91, 110, 91 + 118, 110 + 10), 'C', buttons, false);
-	addButton(Common::Rect(85, 121, 85 + 131, 121 + 10), 'O', buttons, false);
-}
-
-void WorldOptionsMenu::setupButtons(SpriteResource *buttons) {
-	addButton(Common::Rect(93, 53, 93 + 134, 53 + 20), 'S', buttons, true);
-	addButton(Common::Rect(93, 78, 93 + 134, 78 + 20), 'L', buttons, true);
-	addButton(Common::Rect(93, 103, 93 + 134, 103 + 20), 'C', buttons, true);
-	addButton(Common::Rect(93, 128, 93 + 134, 128 + 20), 'O', buttons, true);
-}
-
-/*------------------------------------------------------------------------*/
-
-void CloudsOptionsMenu::startup(Common::String &title1, Common::String &title2) {
-	title1 = "title1.int";
-	title2 = "title1a.int";
-}
-
-/**
-* Draws the scroll in the background
-*/
-void Dialog::doScroll(bool drawFlag, bool doFade) {
-	Screen &screen = *_vm->_screen;
-	EventsManager &events = *_vm->_events;
-	const int SCROLL_L[8] = { 29, 23, 15, 251, 245, 233, 207, 185 };
-	const int SCROLL_R[8] = { 165, 171, 198, 218, 228, 245, 264, 281 };
-
-	saveButtons();
-	clearButtons();
-	screen.saveBackground();
-
-	// Load hand vga files
-	SpriteResource *hand[16];
-	for (int i = 0; i < 16; ++i) {
-		Common::String name = Common::String::format("hand%02u.vga");
-		hand[i] = new SpriteResource(name);
-	}
-
-	// Load marb vga files
-	SpriteResource *marb[5];
-	for (int i = 1; i < 5; ++i) {
-		Common::String name = Common::String::format("marb%02u.vga");
-		marb[i] = new SpriteResource(name);
-	}
-
-	if (drawFlag) {
-		for (int i = 22; i > 0; --i) {
-			events.updateGameCounter();
-			screen.restoreBackground();
-
-			if (i > 0 && i <= 14) {
-				hand[i - 1]->draw(screen, 0);
-			} else {
-				// TODO: Check '800h'.. horizontal reverse maybe?
-				hand[14]->draw(screen, 0, Common::Point(SCROLL_L[i - 14], 0));
-				marb[15]->draw(screen, 0, Common::Point(SCROLL_R[i - 14], 0));
-			}
-
-			if (i <= 20) {
-				marb[i / 5]->draw(screen, i % 5);
-			}
-
-			while (!_vm->shouldQuit() && _vm->_events->timeElapsed() == 0)
-				_vm->_events->pollEventsAndWait();
-
-			screen._windows[0].update();
-			if (i == 0 && doFade)
-				screen.fadeIn(2);
-		}
-	} else {
-		for (int i = 0; i < 22 && !events.isKeyMousePressed(); ++i) {
-			events.updateGameCounter();
-			screen.restoreBackground();
-
-			if (i < 14) {
-				hand[i]->draw(screen, 0);
-			}
-			else {
-				// TODO: Check '800h'.. horizontal reverse maybe?
-				hand[14]->draw(screen, 0, Common::Point(SCROLL_L[i - 7], 0));
-				marb[15]->draw(screen, 0, Common::Point(SCROLL_R[i - 7], 0));
-			}
-
-			if (i < 20) {
-				marb[i / 5]->draw(screen, i % 5);
-			}
-
-			while (!_vm->shouldQuit() && _vm->_events->timeElapsed() == 0)
-				_vm->_events->pollEventsAndWait();
-
-			screen._windows[0].update();
-			if (i == 0 && doFade)
-				screen.fadeIn(2);
-		}
-	}
-
-	if (drawFlag) {
-		hand[0]->draw(screen, 0);
-		marb[0]->draw(screen, 0);
-	} else {
-		screen.restoreBackground();
-	}
-
-	screen._windows[0].update();
-	restoreButtons();
-
-	// Free resources
-	for (int i = 1; i < 5; ++i)
-		delete marb[i];
-	for (int i = 0; i < 16; ++i)
-		delete hand[i];
-}
-
-/*------------------------------------------------------------------------*/
-
-void DarkSideOptionsMenu::startup(Common::String &title1, Common::String &title2) {
-	title1 = "title2.int";
-	title2 = "title2a.int";
-}
-
-/**
-* Draws the scroll in the background
-*/
-void DarkSideOptionsMenu::doScroll(bool drawFlag, bool doFade) {
-	if (doFade) {
-		_vm->_screen->fadeIn(2);
-	}
-}
-
-void WorldOptionsMenu::startup(Common::String &title1, Common::String &title2) {
-	title1 = "world.int";
-	title2 = "start.icn";
-
-	Screen &screen = *_vm->_screen;
-	screen.fadeOut(4);
-	screen.loadPalette("dark.pal");
-	_vm->_events->clearEvents();
-}
-
-void WorldOptionsMenu::setBackground(bool doFade) {
-	Screen &screen = *_vm->_screen;
-	screen.loadBackground("world.raw");
-	screen.saveBackground();
-
-	if (doFade)
-		screen.fadeIn(4);	
-}
-
-void WorldOptionsMenu::openWindow() {
-	_vm->_screen->_windows[28].open();
-}
-
-void WorldOptionsMenu::showContents(SpriteResource &title1, bool waitFlag) {
-	Screen &screen = *_vm->_screen;
-	EventsManager &events = *_vm->_events;
-	events.updateGameCounter();
-	
-	// Draw the background frame in a continous cycle
-	_bgFrame = ++_bgFrame % 5;
-	title1.draw(screen._windows[0], _bgFrame);
-
-	// Draw the basic frame for the optitons menu and title text
-	screen._windows[28].frame();
-	screen._windows[28].writeString("\x0D\x01\003c\014dMight and Magic Options\n"
-		"World of Xeen\x02\n"
-		"\v117Copyright (c) 1993 NWC, Inc.\n"
-		"All Rights Reserved\x01");
-
-	for (uint btnIndex = 0; btnIndex < _buttons.size(); ++btnIndex) {
-		DialogButton &btn = _buttons[btnIndex];
-		if (btn._draw) {
-			btn._sprites->draw(screen._windows[0], btnIndex * 2,
-				Common::Point(btn._bounds.left, btn._bounds.top));
-		}
-	}
-
-	if (waitFlag) {
-		screen._windows[0].update();
-
-		while (!_vm->shouldQuit() && _key == Common::KEYCODE_INVALID &&
-				events.timeElapsed() < 3) {
-			checkEvents();
-		}
-	}
-}
-
-} // End of namespace Xeen
diff --git a/engines/xeen/menus.h b/engines/xeen/menus.h
deleted file mode 100644
index 65e3553..0000000
--- a/engines/xeen/menus.h
+++ /dev/null
@@ -1,133 +0,0 @@
-/* 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_MENUS_H
-#define XEEN_MENUS_H
-
-#include "common/array.h"
-#include "common/stack.h"
-#include "common/rect.h"
-#include "xeen/xeen.h"
-
-namespace Xeen {
-
-class DialogButton {
-public:
-	Common::Rect _bounds;
-	SpriteResource *_sprites;
-	char _c;
-	bool _draw;
-
-	DialogButton(const Common::Rect &bounds, char c, SpriteResource *sprites, bool draw) :
-		_bounds(bounds), _c(c), _sprites(sprites), _draw(draw) {}
-
-	DialogButton() : _c('\0'), _sprites(nullptr), _draw(false) {}
-};
-
-class Dialog {
-private:
-	Common::Stack< Common::Array<DialogButton> > _savedButtons;
-protected:
-	XeenEngine *_vm;
-	Common::Array<DialogButton> _buttons;
-	char _key;
-
-	virtual void doScroll(bool drawFlag, bool doFade);
-
-	void checkEvents();
-public:
-	Dialog(XeenEngine *vm): _vm(vm), _key('\0') {}
-
-	void saveButtons();
-
-	void clearButtons();
-
-	void restoreButtons();
-
-	void addButton(const Common::Rect &bounds, char c, SpriteResource *sprites, bool draw);
-};
-
-class SettingsBaseDialog : public Dialog {
-protected:
-	virtual void showContents(SpriteResource &title1, bool mode);
-public:
-	SettingsBaseDialog(XeenEngine *vm) : Dialog(vm) {}
-};
-class OptionsMenu : public SettingsBaseDialog {
-private:
-	void execute();
-protected:
-	OptionsMenu(XeenEngine *vm) : SettingsBaseDialog(vm) {}
-protected:
-	virtual void startup(Common::String &title1, Common::String &title2) = 0;
-
-	virtual void setBackground(bool doFade) {}
-
-	virtual void showTitles1(SpriteResource &sprites);
-
-	virtual void showTitles2();
-
-	virtual void setupButtons(SpriteResource *buttons);
-
-	virtual void openWindow() {}
-public:
-	static void show(XeenEngine *vm);
-};
-
-class CloudsOptionsMenu : public OptionsMenu {
-protected:
-	virtual void startup(Common::String &title1, Common::String &title2);
-public:
-	CloudsOptionsMenu(XeenEngine *vm) : OptionsMenu(vm) {}
-};
-
-class DarkSideOptionsMenu : public OptionsMenu {
-protected:
-	virtual void startup(Common::String &title1, Common::String &title2);
-
-	virtual void doScroll(bool drawFlag, bool doFade);
-public:
-	DarkSideOptionsMenu(XeenEngine *vm) : OptionsMenu(vm) {}
-};
-
-class WorldOptionsMenu : public DarkSideOptionsMenu {
-private:
-	int _bgFrame;
-protected:
-	virtual void startup(Common::String &title1, Common::String &title2);
-
-	virtual void setBackground(bool doFade);
-
-	virtual void showTitles2() {}
-
-	virtual void setupButtons(SpriteResource *buttons);
-
-	virtual void openWindow();
-
-	virtual void showContents(SpriteResource &title1, bool mode);
-public:
-	WorldOptionsMenu(XeenEngine *vm) : DarkSideOptionsMenu(vm), _bgFrame(0) {}
-};
-
-} // End of namespace Xeen
-
-#endif /* XEEN_MENUS_H */
diff --git a/engines/xeen/module.mk b/engines/xeen/module.mk
index 9d7b0eb..99eb981 100644
--- a/engines/xeen/module.mk
+++ b/engines/xeen/module.mk
@@ -6,9 +6,10 @@ MODULE_OBJS := \
 	worldofxeen\worldofxeen_game.o \
 	debugger.o \
 	detection.o \
+	dialogs.o \
+	dialogs_options.o \
 	events.o \
 	font.o \
-	menus.o \
 	resdata.o \
 	resources.o \
 	screen.o \
diff --git a/engines/xeen/xeen.cpp b/engines/xeen/xeen.cpp
index 1027572..cbdb6f3 100644
--- a/engines/xeen/xeen.cpp
+++ b/engines/xeen/xeen.cpp
@@ -28,7 +28,7 @@
 #include "graphics/scaler.h"
 #include "graphics/thumbnail.h"
 #include "xeen/xeen.h"
-#include "xeen/menus.h"
+#include "xeen/dialogs_options.h"
 #include "xeen/resources.h"
 
 namespace Xeen {


Commit: aa3965cd5dcdf0d774f4798b003c8089e3bcdc7e
    https://github.com/scummvm/scummvm/commit/aa3965cd5dcdf0d774f4798b003c8089e3bcdc7e
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-01-01T11:32:56-10:00

Commit Message:
XEEN: Beginnings of credits screen

Changed paths:
    engines/xeen/dialogs.cpp
    engines/xeen/dialogs.h
    engines/xeen/dialogs_options.cpp
    engines/xeen/resdata.cpp
    engines/xeen/resdata.h



diff --git a/engines/xeen/dialogs.cpp b/engines/xeen/dialogs.cpp
index 1342353..b550cf2 100644
--- a/engines/xeen/dialogs.cpp
+++ b/engines/xeen/dialogs.cpp
@@ -22,6 +22,7 @@
 
 #include "common/scummsys.h"
 #include "xeen/dialogs.h"
+#include "xeen/resdata.h"
 
 namespace Xeen {
 
@@ -80,4 +81,33 @@ void SettingsBaseDialog::showContents(SpriteResource &title1, bool waitFlag) {
 
 /*------------------------------------------------------------------------*/
 
+void CreditsScreen::show(XeenEngine *vm) {
+	CreditsScreen *dlg = new CreditsScreen(vm);
+	dlg->execute();
+	delete dlg;
+}
+
+void CreditsScreen::execute() {
+	Screen &screen = *_vm->_screen;
+	EventsManager &events = *_vm->_events;
+	
+	// Handle drawing the credits screen
+	doScroll(true, false);
+	screen._windows[28].close();
+
+	screen.loadBackground("marb.raw");
+	screen._windows[0].writeString(CREDITS);
+	doScroll(false, false);
+	
+	events.setCursor(0);
+	screen._windows[0].update();
+	clearButtons();
+
+	// Wait for keypress
+	while (!events.isKeyMousePressed())
+		events.pollEventsAndWait();
+
+	doScroll(true, false);
+}
+
 } // End of namespace Xeen
diff --git a/engines/xeen/dialogs.h b/engines/xeen/dialogs.h
index 21bf57c..9810380 100644
--- a/engines/xeen/dialogs.h
+++ b/engines/xeen/dialogs.h
@@ -73,6 +73,15 @@ public:
 	SettingsBaseDialog(XeenEngine *vm) : Dialog(vm) {}
 };
 
+class CreditsScreen: public Dialog {
+private:
+	CreditsScreen(XeenEngine *vm) : Dialog(vm) {}
+
+	void execute();
+public:
+	static void show(XeenEngine *vm);
+};
+
 } // End of namespace Xeen
 
 #endif /* XEEN_DIALOGS_H */
diff --git a/engines/xeen/dialogs_options.cpp b/engines/xeen/dialogs_options.cpp
index e4ebf27..e7f296c 100644
--- a/engines/xeen/dialogs_options.cpp
+++ b/engines/xeen/dialogs_options.cpp
@@ -22,6 +22,7 @@
 
 #include "common/scummsys.h"
 #include "xeen/dialogs_options.h"
+#include "xeen/resdata.h"
 
 namespace Xeen {
 
@@ -86,14 +87,13 @@ void OptionsMenu::execute() {
 				return;
 
 			// Handle keypress
-			switch (toupper(_key)) {
-			case 'C':
-			case 'V':
+			char key = toupper(_key);
+			if (key == 'C' || key == 'V') {
 				// Show credits
-				break;
-			default:
+				CreditsScreen::show(_vm);
 				break;
 			}
+			
 			_key = '\0';
 		}
 	}
@@ -188,7 +188,7 @@ void Dialog::doScroll(bool drawFlag, bool doFade) {
 	// Load hand vga files
 	SpriteResource *hand[16];
 	for (int i = 0; i < 16; ++i) {
-		Common::String name = Common::String::format("hand%02u.vga");
+		Common::String name = Common::String::format("hand%02u.vga", i);
 		hand[i] = new SpriteResource(name);
 	}
 
@@ -317,10 +317,7 @@ void WorldOptionsMenu::showContents(SpriteResource &title1, bool waitFlag) {
 
 	// Draw the basic frame for the optitons menu and title text
 	screen._windows[28].frame();
-	screen._windows[28].writeString("\x0D\x01\003c\014dMight and Magic Options\n"
-		"World of Xeen\x02\n"
-		"\v117Copyright (c) 1993 NWC, Inc.\n"
-		"All Rights Reserved\x01");
+	screen._windows[28].writeString(OPTIONS_TITLE);
 
 	for (uint btnIndex = 0; btnIndex < _buttons.size(); ++btnIndex) {
 		DialogButton &btn = _buttons[btnIndex];
diff --git a/engines/xeen/resdata.cpp b/engines/xeen/resdata.cpp
index 1cdd3ac..b9309b4 100644
--- a/engines/xeen/resdata.cpp
+++ b/engines/xeen/resdata.cpp
@@ -25,6 +25,47 @@
 
 namespace Xeen {
 
+const char *const CREDITS =
+	"\013012\010000\003c\01435Designed and Directed By:\n"
+	"\01417Jon Van Caneghem\003l\n"
+	"\n"
+	"\t025\01435Programming:\n"
+	"\t035\01417Mark Caldwell\n"
+	"\t035Dave Hathaway\n"
+	"\n"
+	"\t025\01435Sound System & FX:\n"
+	"\t035\01417Mike Heilemann\n"
+	"\n"
+	"\t025\01435Music & Speech:\n"
+	"\t035\01417Tim Tully\n"
+	"\n"
+	"\t025\01435Writing:\n"
+	"\t035\01417Paul Rattner\n"
+	"\t035Debbie Van Caneghem\n"
+	"\t035Jon Van Caneghem\013012\n"
+	"\n"
+	"\n"
+	"\t180\01435Graphics:\n"
+	"\t190\01417Jonathan P. Gwyn\n"
+	"\t190Bonita Long-Hemsath\n"
+	"\t190Julia Ulano\n"
+	"\t190Ricardo Barrera\n"
+	"\n"
+	"\t180\01435Testing:\n"
+	"\t190\01417Benjamin Bent\n"
+	"\t190Christian Dailey\n"
+	"\t190Mario Escamilla\n"
+	"\t190Marco Hunter\n"
+	"\t190Robert J. Lupo\n"
+	"\t190Clayton Retzer\n"
+	"\t190David Vela\003c";
+
+const char *const OPTIONS_TITLE = 
+	"\x0D\x01\003c\014dMight and Magic Options\n"
+	"World of Xeen\x02\n"
+	"\v117Copyright (c) 1993 NWC, Inc.\n"
+	"All Rights Reserved\x01";
+
 const byte SYMBOLS[20][64] = {
 	{ // 0
 		0x00, 0x00, 0xA8, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0x00, 0xA8, 0x9E, 0x9C, 0x9C, 0x9E, 0x9E, 0x9E,
diff --git a/engines/xeen/resdata.h b/engines/xeen/resdata.h
index deb6e58..3c549fc 100644
--- a/engines/xeen/resdata.h
+++ b/engines/xeen/resdata.h
@@ -28,6 +28,10 @@
 
 namespace Xeen {
 
+extern const char *const CREDITS;
+
+extern const char *const OPTIONS_TITLE;
+
 extern const byte SYMBOLS[20][64];
 
 extern const byte TEXT_COLORS[40][4];


Commit: b2f1282aeb7f405f265afac3d601459f4cfebf6d
    https://github.com/scummvm/scummvm/commit/b2f1282aeb7f405f265afac3d601459f4cfebf6d
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-01-01T11:46:22-10:00

Commit Message:
XEEN: Credits screen now working

Changed paths:
    engines/xeen/dialogs.cpp
    engines/xeen/dialogs.h
    engines/xeen/dialogs_options.cpp
    engines/xeen/dialogs_options.h
    engines/xeen/screen.cpp
    engines/xeen/screen.h



diff --git a/engines/xeen/dialogs.cpp b/engines/xeen/dialogs.cpp
index b550cf2..cdc6d5b 100644
--- a/engines/xeen/dialogs.cpp
+++ b/engines/xeen/dialogs.cpp
@@ -73,6 +73,111 @@ void Dialog::checkEvents() {
 	}
 }
 
+
+/**
+* Draws the scroll in the background
+*/
+void Dialog::doScroll(bool drawFlag, bool doFade) {
+	Screen &screen = *_vm->_screen;
+	EventsManager &events = *_vm->_events;
+
+	if (_vm->getGameID() != GType_Clouds) {
+		if (doFade) {
+			_vm->_screen->fadeIn(2);
+		}
+		return;
+	}
+
+	const int SCROLL_L[8] = { 29, 23, 15, 251, 245, 233, 207, 185 };
+	const int SCROLL_R[8] = { 165, 171, 198, 218, 228, 245, 264, 281 };
+
+	saveButtons();
+	clearButtons();
+	screen.saveBackground();
+
+	// Load hand vga files
+	SpriteResource *hand[16];
+	for (int i = 0; i < 16; ++i) {
+		Common::String name = Common::String::format("hand%02u.vga", i);
+		hand[i] = new SpriteResource(name);
+	}
+
+	// Load marb vga files
+	SpriteResource *marb[5];
+	for (int i = 1; i < 5; ++i) {
+		Common::String name = Common::String::format("marb%02u.vga");
+		marb[i] = new SpriteResource(name);
+	}
+
+	if (drawFlag) {
+		for (int i = 22; i > 0; --i) {
+			events.updateGameCounter();
+			screen.restoreBackground();
+
+			if (i > 0 && i <= 14) {
+				hand[i - 1]->draw(screen, 0);
+			}
+			else {
+				// TODO: Check '800h'.. horizontal reverse maybe?
+				hand[14]->draw(screen, 0, Common::Point(SCROLL_L[i - 14], 0));
+				marb[15]->draw(screen, 0, Common::Point(SCROLL_R[i - 14], 0));
+			}
+
+			if (i <= 20) {
+				marb[i / 5]->draw(screen, i % 5);
+			}
+
+			while (!_vm->shouldQuit() && _vm->_events->timeElapsed() == 0)
+				_vm->_events->pollEventsAndWait();
+
+			screen._windows[0].update();
+			if (i == 0 && doFade)
+				screen.fadeIn(2);
+		}
+	} else {
+		for (int i = 0; i < 22 && !events.isKeyMousePressed(); ++i) {
+			events.updateGameCounter();
+			screen.restoreBackground();
+
+			if (i < 14) {
+				hand[i]->draw(screen, 0);
+			} else {
+				// TODO: Check '800h'.. horizontal reverse maybe?
+				hand[14]->draw(screen, 0, Common::Point(SCROLL_L[i - 7], 0));
+				marb[15]->draw(screen, 0, Common::Point(SCROLL_R[i - 7], 0));
+			}
+
+			if (i < 20) {
+				marb[i / 5]->draw(screen, i % 5);
+			}
+
+			while (!_vm->shouldQuit() && _vm->_events->timeElapsed() == 0)
+				_vm->_events->pollEventsAndWait();
+
+			screen._windows[0].update();
+			if (i == 0 && doFade)
+				screen.fadeIn(2);
+		}
+	}
+
+	if (drawFlag) {
+		hand[0]->draw(screen, 0);
+		marb[0]->draw(screen, 0);
+	}
+	else {
+		screen.restoreBackground();
+	}
+
+	screen._windows[0].update();
+	restoreButtons();
+
+	// Free resources
+	for (int i = 1; i < 5; ++i)
+		delete marb[i];
+	for (int i = 0; i < 16; ++i)
+		delete hand[i];
+}
+
 /*------------------------------------------------------------------------*/
 
 void SettingsBaseDialog::showContents(SpriteResource &title1, bool waitFlag) {
diff --git a/engines/xeen/dialogs.h b/engines/xeen/dialogs.h
index 9810380..1f8f2fb 100644
--- a/engines/xeen/dialogs.h
+++ b/engines/xeen/dialogs.h
@@ -51,7 +51,7 @@ protected:
 	Common::Array<DialogButton> _buttons;
 	char _key;
 
-	virtual void doScroll(bool drawFlag, bool doFade);
+	void doScroll(bool drawFlag, bool doFade);
 
 	void checkEvents();
 public:
diff --git a/engines/xeen/dialogs_options.cpp b/engines/xeen/dialogs_options.cpp
index e7f296c..a92fd59 100644
--- a/engines/xeen/dialogs_options.cpp
+++ b/engines/xeen/dialogs_options.cpp
@@ -88,13 +88,13 @@ void OptionsMenu::execute() {
 
 			// Handle keypress
 			char key = toupper(_key);
+			_key = '\0';
+
 			if (key == 'C' || key == 'V') {
 				// Show credits
 				CreditsScreen::show(_vm);
 				break;
 			}
-			
-			_key = '\0';
 		}
 	}
 }
@@ -172,101 +172,6 @@ void CloudsOptionsMenu::startup(Common::String &title1, Common::String &title2)
 	title2 = "title1a.int";
 }
 
-/**
-* Draws the scroll in the background
-*/
-void Dialog::doScroll(bool drawFlag, bool doFade) {
-	Screen &screen = *_vm->_screen;
-	EventsManager &events = *_vm->_events;
-	const int SCROLL_L[8] = { 29, 23, 15, 251, 245, 233, 207, 185 };
-	const int SCROLL_R[8] = { 165, 171, 198, 218, 228, 245, 264, 281 };
-
-	saveButtons();
-	clearButtons();
-	screen.saveBackground();
-
-	// Load hand vga files
-	SpriteResource *hand[16];
-	for (int i = 0; i < 16; ++i) {
-		Common::String name = Common::String::format("hand%02u.vga", i);
-		hand[i] = new SpriteResource(name);
-	}
-
-	// Load marb vga files
-	SpriteResource *marb[5];
-	for (int i = 1; i < 5; ++i) {
-		Common::String name = Common::String::format("marb%02u.vga");
-		marb[i] = new SpriteResource(name);
-	}
-
-	if (drawFlag) {
-		for (int i = 22; i > 0; --i) {
-			events.updateGameCounter();
-			screen.restoreBackground();
-
-			if (i > 0 && i <= 14) {
-				hand[i - 1]->draw(screen, 0);
-			} else {
-				// TODO: Check '800h'.. horizontal reverse maybe?
-				hand[14]->draw(screen, 0, Common::Point(SCROLL_L[i - 14], 0));
-				marb[15]->draw(screen, 0, Common::Point(SCROLL_R[i - 14], 0));
-			}
-
-			if (i <= 20) {
-				marb[i / 5]->draw(screen, i % 5);
-			}
-
-			while (!_vm->shouldQuit() && _vm->_events->timeElapsed() == 0)
-				_vm->_events->pollEventsAndWait();
-
-			screen._windows[0].update();
-			if (i == 0 && doFade)
-				screen.fadeIn(2);
-		}
-	} else {
-		for (int i = 0; i < 22 && !events.isKeyMousePressed(); ++i) {
-			events.updateGameCounter();
-			screen.restoreBackground();
-
-			if (i < 14) {
-				hand[i]->draw(screen, 0);
-			}
-			else {
-				// TODO: Check '800h'.. horizontal reverse maybe?
-				hand[14]->draw(screen, 0, Common::Point(SCROLL_L[i - 7], 0));
-				marb[15]->draw(screen, 0, Common::Point(SCROLL_R[i - 7], 0));
-			}
-
-			if (i < 20) {
-				marb[i / 5]->draw(screen, i % 5);
-			}
-
-			while (!_vm->shouldQuit() && _vm->_events->timeElapsed() == 0)
-				_vm->_events->pollEventsAndWait();
-
-			screen._windows[0].update();
-			if (i == 0 && doFade)
-				screen.fadeIn(2);
-		}
-	}
-
-	if (drawFlag) {
-		hand[0]->draw(screen, 0);
-		marb[0]->draw(screen, 0);
-	} else {
-		screen.restoreBackground();
-	}
-
-	screen._windows[0].update();
-	restoreButtons();
-
-	// Free resources
-	for (int i = 1; i < 5; ++i)
-		delete marb[i];
-	for (int i = 0; i < 16; ++i)
-		delete hand[i];
-}
-
 /*------------------------------------------------------------------------*/
 
 void DarkSideOptionsMenu::startup(Common::String &title1, Common::String &title2) {
@@ -274,15 +179,6 @@ void DarkSideOptionsMenu::startup(Common::String &title1, Common::String &title2
 	title2 = "title2a.int";
 }
 
-/**
-* Draws the scroll in the background
-*/
-void DarkSideOptionsMenu::doScroll(bool drawFlag, bool doFade) {
-	if (doFade) {
-		_vm->_screen->fadeIn(2);
-	}
-}
-
 void WorldOptionsMenu::startup(Common::String &title1, Common::String &title2) {
 	title1 = "world.int";
 	title2 = "start.icn";
diff --git a/engines/xeen/dialogs_options.h b/engines/xeen/dialogs_options.h
index 591ab5e..7a933fd 100644
--- a/engines/xeen/dialogs_options.h
+++ b/engines/xeen/dialogs_options.h
@@ -59,8 +59,6 @@ public:
 class DarkSideOptionsMenu : public OptionsMenu {
 protected:
 	virtual void startup(Common::String &title1, Common::String &title2);
-
-	virtual void doScroll(bool drawFlag, bool doFade);
 public:
 	DarkSideOptionsMenu(XeenEngine *vm) : OptionsMenu(vm) {}
 };
diff --git a/engines/xeen/screen.cpp b/engines/xeen/screen.cpp
index 6d5caae..f3cbabc 100644
--- a/engines/xeen/screen.cpp
+++ b/engines/xeen/screen.cpp
@@ -60,7 +60,7 @@ void Window::open() {
 }
 
 void Window::open2() {
-	_dirtyRects.push(_bounds);
+	addDirtyRect(_bounds);
 	frame();
 	fill();
 }
@@ -125,7 +125,6 @@ void Window::close() {
 		// Update any remaining pending changes to the screen and free
 		// the window's internal surface storage
 		update();
-		free();
 
 		// Remove the window from the stack and flag it as now disabled
 		for (uint i = 0; i < _vm->_screen->_windowStack.size(); ++i) {
@@ -142,17 +141,18 @@ void Window::close() {
 }
 
 /**
- * Pushes any pending changes for the window to the screen
+ * Update the window
  */
 void Window::update() {
-	while (!_dirtyRects.empty()) {
-		Common::Rect r = _dirtyRects.pop();
-		blitTo(*_vm->_screen, Common::Point(_bounds.left, _bounds.top));
-	}
+	// Since all window drawing is done on the screen surface anyway,
+	// there's nothing that needs to be updated here
 }
 
+/**
+ * Adds an area that requires redrawing on the next frame update
+ */
 void Window::addDirtyRect(const Common::Rect &r) {
-	_dirtyRects.push(r);
+	_vm->_screen->addDirtyRect(r);
 }
 
 /**
@@ -319,6 +319,7 @@ void Screen::loadBackground(const Common::String &name) {
 
 	assert(f.size() == (SCREEN_WIDTH * SCREEN_HEIGHT));
 	f.read((byte *)getPixels(), SCREEN_WIDTH * SCREEN_HEIGHT);
+	addDirtyRect(Common::Rect(0, 0, this->w, this->h));
 }
 
 /**
diff --git a/engines/xeen/screen.h b/engines/xeen/screen.h
index 41b2821..fd8a509 100644
--- a/engines/xeen/screen.h
+++ b/engines/xeen/screen.h
@@ -26,7 +26,6 @@
 #include "common/scummsys.h"
 #include "common/system.h"
 #include "common/array.h"
-#include "common/queue.h"
 #include "common/rect.h"
 #include "xeen/font.h"
 #include "xeen/xsurface.h"
@@ -51,7 +50,6 @@ private:
 	int _xLo, _xHi;
 	int _ycL, _ycH;
 	bool _enabled;
-	Common::Queue<Common::Rect> _dirtyRects;
 
 	void open2();
 public:


Commit: 5135439bbd64289e4c6c780f4b4da03ce40e75be
    https://github.com/scummvm/scummvm/commit/5135439bbd64289e4c6c780f4b4da03ce40e75be
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-01-01T14:57:56-10:00

Commit Message:
XEEN: Reorganisation of resource, sprite, and cc file class files

Changed paths:
  A engines/xeen/files.cpp
  A engines/xeen/files.h
  A engines/xeen/sprites.cpp
  A engines/xeen/sprites.h
  R engines/xeen/resdata.cpp
  R engines/xeen/resdata.h
    engines/xeen/dialogs.cpp
    engines/xeen/dialogs_options.cpp
    engines/xeen/events.h
    engines/xeen/font.cpp
    engines/xeen/module.mk
    engines/xeen/resources.cpp
    engines/xeen/resources.h
    engines/xeen/sound.h
    engines/xeen/xeen.cpp
    engines/xeen/xsurface.cpp



diff --git a/engines/xeen/dialogs.cpp b/engines/xeen/dialogs.cpp
index cdc6d5b..4d1a876 100644
--- a/engines/xeen/dialogs.cpp
+++ b/engines/xeen/dialogs.cpp
@@ -22,7 +22,7 @@
 
 #include "common/scummsys.h"
 #include "xeen/dialogs.h"
-#include "xeen/resdata.h"
+#include "xeen/resources.h"
 
 namespace Xeen {
 
diff --git a/engines/xeen/dialogs_options.cpp b/engines/xeen/dialogs_options.cpp
index a92fd59..e85a4af 100644
--- a/engines/xeen/dialogs_options.cpp
+++ b/engines/xeen/dialogs_options.cpp
@@ -22,7 +22,7 @@
 
 #include "common/scummsys.h"
 #include "xeen/dialogs_options.h"
-#include "xeen/resdata.h"
+#include "xeen/resources.h"
 
 namespace Xeen {
 
@@ -94,6 +94,9 @@ void OptionsMenu::execute() {
 				// Show credits
 				CreditsScreen::show(_vm);
 				break;
+			} else if (key == 27) {
+				// Hide the options menu
+				break;
 			}
 		}
 	}
diff --git a/engines/xeen/events.h b/engines/xeen/events.h
index 6183b75..5a9faf1 100644
--- a/engines/xeen/events.h
+++ b/engines/xeen/events.h
@@ -25,7 +25,7 @@
 
 #include "common/scummsys.h"
 #include "common/events.h"
-#include "xeen/resources.h"
+#include "xeen/sprites.h"
 
 namespace Xeen {
 
diff --git a/engines/xeen/files.cpp b/engines/xeen/files.cpp
new file mode 100644
index 0000000..27bbf6e
--- /dev/null
+++ b/engines/xeen/files.cpp
@@ -0,0 +1,214 @@
+/* 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 "common/archive.h"
+#include "common/memstream.h"
+#include "common/textconsole.h"
+#include "xeen/xeen.h"
+#include "xeen/files.h"
+
+namespace Xeen {
+
+/**
+ * Xeen CC file implementation
+ */
+class CCArchive : public Common::Archive {
+private:
+	/**
+	 * Details of a single entry in a CC file index
+	 */
+	struct CCEntry {
+		uint16 _id;
+		uint32 _offset;
+		uint16 _size;
+
+		CCEntry() : _id(0), _offset(0), _size(0) {}
+		CCEntry(uint16 id, uint32 offset, uint32 size)
+			: _id(id), _offset(offset), _size(size) {
+		}
+	};
+
+	Common::Array<CCEntry> _index;
+	Common::String _filename;
+
+	uint16 convertNameToId(const Common::String &resourceName) const;
+
+	void loadIndex(Common::SeekableReadStream *stream);
+
+	bool getHeaderEntry(const Common::String &resourceName, CCEntry &ccEntry) const;
+public:
+	CCArchive(const Common::String &filename);
+	virtual ~CCArchive();
+
+	// Archive implementation
+	virtual bool hasFile(const Common::String &name) const;
+	virtual int listMembers(Common::ArchiveMemberList &list) const;
+	virtual const Common::ArchiveMemberPtr getMember(const Common::String &name) const;
+	virtual Common::SeekableReadStream *createReadStreamForMember(const Common::String &name) const;
+};
+
+CCArchive::CCArchive(const Common::String &filename): _filename(filename) {
+	File f(filename);
+	loadIndex(&f);
+}
+
+CCArchive::~CCArchive() {
+}
+
+// Archive implementation
+bool CCArchive::hasFile(const Common::String &name) const {
+	CCEntry ccEntry;
+	return getHeaderEntry(name, ccEntry);
+}
+
+int CCArchive::listMembers(Common::ArchiveMemberList &list) const {
+	// CC files don't maintain the original filenames, so we can't list it
+	return 0;
+}
+
+const Common::ArchiveMemberPtr CCArchive::getMember(const Common::String &name) const {
+	if (!hasFile(name))
+		return Common::ArchiveMemberPtr();
+
+	return Common::ArchiveMemberPtr(new Common::GenericArchiveMember(name, this));
+}
+
+Common::SeekableReadStream *CCArchive::createReadStreamForMember(const Common::String &name) const {
+	CCEntry ccEntry;
+
+	if (getHeaderEntry(name, ccEntry)) {
+		// Open the correct CC file
+		Common::File f;
+		if (!f.open(_filename))
+			error("Could not open CC file");
+
+		// Read in the data for the specific resource
+		f.seek(ccEntry._offset);
+		byte *data = new byte[ccEntry._size];
+		f.read(data, ccEntry._size);
+
+		// Decrypt the data
+		for (int i = 0; i < ccEntry._size; ++i)
+			data[i] ^= 0x35;
+
+		// Return the data as a stream
+		return new Common::MemoryReadStream(data, ccEntry._size, DisposeAfterUse::YES);
+	}
+
+	return nullptr;
+}
+
+/**
+ * Hash a given filename to produce the Id that represents it
+ */
+uint16 CCArchive::convertNameToId(const Common::String &resourceName) const {
+	if (resourceName.empty())
+		return 0xffff;
+
+	Common::String name = resourceName;
+	name.toUppercase();
+
+	const byte *msgP = (const byte *)name.c_str();
+	int total = *msgP++;
+	for (; *msgP; total += *msgP++) {
+		// Rotate the bits in 'total' right 7 places
+		total = (total & 0x007F) << 9 | (total & 0xFF80) >> 7;
+	}
+
+	return total;
+}
+
+/**
+ * Load the index of a given CC file
+ */
+void CCArchive::loadIndex(Common::SeekableReadStream *stream) {
+	int count = stream->readUint16LE();
+
+	// Read in the data for the archive's index
+	byte *rawIndex = new byte[count * 8];
+	stream->read(rawIndex, count * 8);
+
+	// Decrypt the index
+	int ah = 0xac;
+	for (int i = 0; i < count * 8; ++i) {
+		rawIndex[i] = (byte)(((rawIndex[i] << 2 | rawIndex[i] >> 6) + ah) & 0xff);
+		ah += 0x67;
+	}
+
+	// Extract the index data into entry structures
+	_index.reserve(count);
+	const byte *entryP = &rawIndex[0];
+	for (int i = 0; i < count; ++i, entryP += 8) {
+		CCEntry entry;
+		entry._id = READ_LE_UINT16(entryP);
+		entry._offset = READ_LE_UINT32(entryP + 2) & 0xffffff;
+		entry._size = READ_LE_UINT16(entryP + 5);
+		assert(!entryP[7]);
+
+		_index.push_back(entry);
+	}
+
+	delete[] rawIndex;
+}
+
+/**
+* Given a resource name, returns whether an entry exists, and returns
+* the header index data for that entry
+*/
+bool CCArchive::getHeaderEntry(const Common::String &resourceName, CCEntry &ccEntry) const {
+	uint16 id = convertNameToId(resourceName);
+
+	// Loop through the index
+	for (uint i = 0; i < _index.size(); ++i) {
+		if (_index[i]._id == id) {
+			ccEntry = _index[i];
+			return true;
+		}
+	}
+
+	// Could not find an entry
+	return false;
+}
+
+/*------------------------------------------------------------------------*/
+
+void FileManager::init(XeenEngine *vm) {
+	Common::File f;
+
+	if (vm->getGameID() != GType_Clouds)
+		SearchMan.add("dark", new CCArchive("dark.cc"));
+	SearchMan.add("xeen", new CCArchive("xeen.cc"));
+	SearchMan.add("intro", new CCArchive("intro.cc"));
+}
+
+/*------------------------------------------------------------------------*/
+
+/**
+ * Opens the given file, throwing an error if it can't be opened
+ */
+void File::openFile(const Common::String &filename) {
+	if (!Common::File::open(filename))
+		error("Could not open file - %s", filename.c_str());
+}
+
+} // End of namespace Xeen
diff --git a/engines/xeen/files.h b/engines/xeen/files.h
new file mode 100644
index 0000000..7ef126e
--- /dev/null
+++ b/engines/xeen/files.h
@@ -0,0 +1,58 @@
+/* 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_FILES_H
+#define XEEN_FILES_H
+
+#include "common/scummsys.h"
+#include "common/array.h"
+#include "common/file.h"
+#include "graphics/surface.h"
+#include "xeen/xsurface.h"
+
+namespace Xeen {
+
+class XeenEngine;
+
+class FileManager {
+public:
+	/**
+	 * Instantiates the resource manager
+	 */
+	static void init(XeenEngine *vm);
+};
+
+/**
+ * Derived file class
+ */
+class File : public Common::File {
+public:
+	File() : Common::File() {}
+	File(const Common::String &filename) { openFile(filename); }
+	virtual ~File() {}
+
+	void openFile(const Common::String &filename);
+};
+
+} // End of namespace Xeen
+
+#endif /* XEEN_FILES_H */
diff --git a/engines/xeen/font.cpp b/engines/xeen/font.cpp
index 8b80ec2..b5608d4 100644
--- a/engines/xeen/font.cpp
+++ b/engines/xeen/font.cpp
@@ -22,7 +22,7 @@
 
 #include "common/endian.h"
 #include "xeen/font.h"
-#include "xeen/resdata.h"
+#include "xeen/resources.h"
 
 namespace Xeen {
 
diff --git a/engines/xeen/module.mk b/engines/xeen/module.mk
index 99eb981..cdd8e54 100644
--- a/engines/xeen/module.mk
+++ b/engines/xeen/module.mk
@@ -9,11 +9,13 @@ MODULE_OBJS := \
 	dialogs.o \
 	dialogs_options.o \
 	events.o \
+	files.o \
 	font.o \
 	resdata.o \
 	resources.o \
 	screen.o \
 	sound.o \
+	sprites.o \
 	xeen.o \
 	xsurface.o
 
diff --git a/engines/xeen/resdata.cpp b/engines/xeen/resdata.cpp
deleted file mode 100644
index b9309b4..0000000
--- a/engines/xeen/resdata.cpp
+++ /dev/null
@@ -1,235 +0,0 @@
-/* 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/resdata.h"
-
-namespace Xeen {
-
-const char *const CREDITS =
-	"\013012\010000\003c\01435Designed and Directed By:\n"
-	"\01417Jon Van Caneghem\003l\n"
-	"\n"
-	"\t025\01435Programming:\n"
-	"\t035\01417Mark Caldwell\n"
-	"\t035Dave Hathaway\n"
-	"\n"
-	"\t025\01435Sound System & FX:\n"
-	"\t035\01417Mike Heilemann\n"
-	"\n"
-	"\t025\01435Music & Speech:\n"
-	"\t035\01417Tim Tully\n"
-	"\n"
-	"\t025\01435Writing:\n"
-	"\t035\01417Paul Rattner\n"
-	"\t035Debbie Van Caneghem\n"
-	"\t035Jon Van Caneghem\013012\n"
-	"\n"
-	"\n"
-	"\t180\01435Graphics:\n"
-	"\t190\01417Jonathan P. Gwyn\n"
-	"\t190Bonita Long-Hemsath\n"
-	"\t190Julia Ulano\n"
-	"\t190Ricardo Barrera\n"
-	"\n"
-	"\t180\01435Testing:\n"
-	"\t190\01417Benjamin Bent\n"
-	"\t190Christian Dailey\n"
-	"\t190Mario Escamilla\n"
-	"\t190Marco Hunter\n"
-	"\t190Robert J. Lupo\n"
-	"\t190Clayton Retzer\n"
-	"\t190David Vela\003c";
-
-const char *const OPTIONS_TITLE = 
-	"\x0D\x01\003c\014dMight and Magic Options\n"
-	"World of Xeen\x02\n"
-	"\v117Copyright (c) 1993 NWC, Inc.\n"
-	"All Rights Reserved\x01";
-
-const byte SYMBOLS[20][64] = {
-	{ // 0
-		0x00, 0x00, 0xA8, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0x00, 0xA8, 0x9E, 0x9C, 0x9C, 0x9E, 0x9E, 0x9E,
-		0xAC, 0x9C, 0xA4, 0xAC, 0xAC, 0x9A, 0x9A, 0x9A, 0xAC, 0x9E, 0xAC, 0xA8, 0xA8, 0xA6, 0x97, 0x98,
-		0xAC, 0xA0, 0xAC, 0xAC, 0xA4, 0xA6, 0x98, 0x99, 0x00, 0xAC, 0xA0, 0xA0, 0xA8, 0xAC, 0x9A, 0x9A,
-		0x00, 0x00, 0xAC, 0xAC, 0xAC, 0xA4, 0x9B, 0x9A, 0x00, 0x00, 0x00, 0x00, 0xAC, 0xA0, 0x9B, 0x9B,
-	},
-	{ // 1
-		0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E,
-		0x99, 0x9A, 0x9A, 0x99, 0x99, 0x99, 0x9A, 0x99, 0x98, 0x98, 0x98, 0x97, 0x97, 0x97, 0x97, 0x97,
-		0x99, 0x98, 0x98, 0x99, 0x98, 0x98, 0x99, 0x99, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A,
-		0x9A, 0x9B, 0x9B, 0x9C, 0x9B, 0x9A, 0x9C, 0x9A, 0x9B, 0x9A, 0x99, 0x99, 0x99, 0x9A, 0x9A, 0x9B,
-	},
-	{ // 2
-		0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E,
-		0x99, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x99, 0x98, 0x98, 0x99, 0x98, 0x98, 0x97, 0x98, 0x98,
-		0x99, 0x98, 0x98, 0x98, 0x99, 0x99, 0x98, 0x99, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A,
-		0x9B, 0x9B, 0x9C, 0x9C, 0x9B, 0x9B, 0x9B, 0x9B, 0x99, 0x9A, 0x9B, 0x9B, 0x9A, 0x9A, 0x99, 0x9A,
-	},
-	{ // 3
-		0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E,
-		0x99, 0x9A, 0x9A, 0x9A, 0x99, 0x99, 0x99, 0x9A, 0x98, 0x98, 0x97, 0x97, 0x98, 0x98, 0x98, 0x98,
-		0x99, 0x99, 0x98, 0x99, 0x98, 0x98, 0x99, 0x99, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A,
-		0x9B, 0x9C, 0x9B, 0x9B, 0x9C, 0x9C, 0x9C, 0x9C, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x99, 0x99, 0x9A,
-	},
-	{ // 4
-		0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E,
-		0x9A, 0x9A, 0x9A, 0x99, 0x99, 0x99, 0x99, 0x9A, 0x97, 0x97, 0x97, 0x97, 0x97, 0x98, 0x98, 0x98,
-		0x99, 0x99, 0x98, 0x99, 0x99, 0x98, 0x98, 0x98, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A,
-		0x9A, 0x9C, 0x9B, 0x9B, 0x9C, 0x9B, 0x9B, 0x9B, 0x9A, 0x99, 0x9B, 0x9B, 0x9A, 0x99, 0x9A, 0x9A,
-	},
-	{ // 5
-		0xA4, 0xA4, 0xA8, 0xA8, 0x00, 0x00, 0x00, 0x00, 0x9E, 0x9E, 0x9E, 0xA0, 0xA8, 0xAC, 0x00, 0x00,
-		0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9E, 0xAC, 0x00, 0x97, 0x97, 0x97, 0x98, 0x9C, 0x9C, 0xA0, 0xAC,
-		0x99, 0x98, 0x99, 0x99, 0x99, 0x9B, 0xA0, 0xAC, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9B, 0xA0, 0xAC,
-		0x9C, 0x9B, 0x9C, 0x9C, 0x9C, 0xA0, 0xAC, 0x00, 0x99, 0x9A, 0x9A, 0x9B, 0x9B, 0xA4, 0xAC, 0x00,
-	},
-	{ // 6
-		0x00, 0x00, 0x00, 0xAC, 0xA4, 0x9C, 0x99, 0x99, 0x00, 0x00, 0x00, 0xAC, 0xA0, 0x9C, 0x9B, 0x99,
-		0x00, 0x00, 0xAC, 0xA0, 0x9C, 0x99, 0x99, 0x99, 0x00, 0xAC, 0xA0, 0x9C, 0x99, 0x98, 0x99, 0x99,
-		0x00, 0xAC, 0xA0, 0x9C, 0x9C, 0xA0, 0x9C, 0x9A, 0x00, 0x00, 0xAC, 0xA4, 0xA0, 0x99, 0x99, 0x99,
-		0x00, 0xAC, 0xA0, 0x9C, 0x99, 0x99, 0x99, 0x99, 0x00, 0xAC, 0xA4, 0x9C, 0x99, 0x99, 0x99, 0x99,
-	},
-	{ // 7
-		0xAC, 0xA0, 0x9C, 0x99, 0x99, 0x99, 0x99, 0x99, 0xAC, 0xA4, 0x9C, 0x99, 0x99, 0x99, 0x99, 0x99,
-		0x00, 0xAC, 0xA0, 0x9C, 0x99, 0x99, 0x99, 0x99, 0x00, 0x00, 0xAC, 0xA4, 0x9C, 0x9C, 0x99, 0x99,
-		0x00, 0x00, 0xAC, 0xA0, 0x9C, 0x99, 0x99, 0x99, 0x00, 0x00, 0x00, 0xAC, 0xA4, 0x9C, 0x99, 0x99,
-		0x00, 0x00, 0xAC, 0xA0, 0x9B, 0xA0, 0x9E, 0x9C, 0x00, 0xAC, 0xA4, 0x9C, 0x99, 0x9C, 0x99, 0x99,
-	},
-	{ // 8
-		0x00, 0xAC, 0xA0, 0x9C, 0x99, 0x99, 0x9B, 0x99, 0xAC, 0xA4, 0x9C, 0x99, 0x99, 0x99, 0x99, 0x99,
-		0xAC, 0xA0, 0x9C, 0x99, 0x99, 0x99, 0x99, 0x99, 0xAC, 0xA4, 0x9C, 0x99, 0x99, 0x99, 0x99, 0x99,
-		0x00, 0xAC, 0xA4, 0x9C, 0x99, 0x99, 0x99, 0x99, 0xAC, 0xA0, 0x9C, 0x99, 0x99, 0x99, 0x99, 0x99,
-		0x00, 0xAC, 0xA0, 0x9C, 0x99, 0x99, 0x9C, 0x99, 0x00, 0xAC, 0xA4, 0x9C, 0x99, 0x9E, 0x9C, 0x99,
-	},
-	{ // 9
-		0x00, 0x00, 0xAC, 0xA4, 0xA0, 0x9C, 0x99, 0x99, 0x00, 0xAC, 0xA0, 0x9C, 0x9C, 0xA0, 0x9C, 0x9A,
-		0xAC, 0xA4, 0x9C, 0x9A, 0x99, 0x99, 0x99, 0x99, 0xAC, 0xA0, 0x9C, 0x99, 0x99, 0x99, 0x99, 0x99,
-		0xAC, 0xA4, 0x9C, 0x99, 0x99, 0x99, 0x99, 0x99, 0x00, 0xAC, 0xA0, 0x9C, 0x99, 0x99, 0x99, 0x99,
-		0x00, 0xAC, 0xA4, 0x9C, 0x9A, 0x9C, 0x99, 0x99, 0x00, 0x00, 0xAC, 0xA0, 0x9C, 0x9A, 0x99, 0x99,
-	},
-	{ // 10
-		0x99, 0x99, 0x99, 0x9A, 0xA0, 0xAC, 0x00, 0x00, 0x99, 0x99, 0x99, 0x9C, 0xA0, 0xAC, 0x00, 0x00,
-		0x99, 0x99, 0x9C, 0x9E, 0xA4, 0xAC, 0x00, 0x00, 0x99, 0x99, 0x9C, 0x99, 0x9C, 0xA4, 0xAC, 0x00,
-		0x99, 0x99, 0x99, 0x99, 0x9C, 0xA0, 0xAC, 0x00, 0x99, 0x99, 0x99, 0x9C, 0xA0, 0xAC, 0x00, 0x00,
-		0x99, 0x99, 0x99, 0xA0, 0xA4, 0xAC, 0x00, 0x00, 0x9A, 0x9B, 0x9E, 0x9C, 0x9C, 0xA4, 0xAC, 0x00,
-	},
-	{ // 11
-		0x99, 0x99, 0x99, 0x99, 0x9C, 0xA0, 0xAC, 0x00, 0x99, 0x99, 0x99, 0x99, 0x99, 0x9C, 0x9E, 0xAC,
-		0x99, 0x99, 0x99, 0x99, 0x9C, 0xA0, 0xAC, 0x00, 0x99, 0x99, 0x99, 0x99, 0x9C, 0xA0, 0xAC, 0x00,
-		0x99, 0x99, 0x99, 0x99, 0x99, 0x9C, 0xA4, 0xAC, 0x99, 0x99, 0x99, 0x99, 0x99, 0x9C, 0xA0, 0xAC,
-		0x9C, 0x99, 0x99, 0x99, 0x9C, 0x9C, 0xA4, 0xAC, 0x99, 0x9E, 0x9E, 0x9C, 0x9C, 0xA0, 0xAC, 0x00,
-	},
-	{ // 12
-		0x99, 0x99, 0x9C, 0xA0, 0xA4, 0xAC, 0x00, 0x00, 0x9B, 0x9C, 0x9E, 0x9C, 0x9C, 0xA4, 0xAC, 0x00,
-		0x99, 0x99, 0x99, 0x99, 0x99, 0xA0, 0xAC, 0x00, 0x99, 0x99, 0x99, 0x99, 0x99, 0x9C, 0xA0, 0xAC,
-		0x99, 0x99, 0x99, 0x99, 0x9C, 0x9C, 0xA4, 0xAC, 0x99, 0x99, 0x99, 0x9C, 0xA0, 0xA4, 0xAC, 0x00,
-		0x99, 0x99, 0x9C, 0x99, 0x99, 0x9C, 0xA0, 0xAC, 0x99, 0x99, 0x99, 0x99, 0x99, 0x9C, 0xA0, 0xAC,
-	},
-	{ // 13
-		0x99, 0x99, 0x99, 0x99, 0x9C, 0xA0, 0xAC, 0x00, 0x99, 0x99, 0x99, 0x9C, 0xA0, 0xAC, 0x00, 0x00,
-		0x99, 0x9B, 0x9C, 0xA0, 0xA4, 0xAC, 0x00, 0x00, 0x99, 0x99, 0x9A, 0x99, 0x9C, 0xA0, 0xAC, 0x00,
-		0x99, 0x99, 0x99, 0x99, 0x99, 0x9C, 0xA4, 0xAC, 0x99, 0x99, 0x99, 0x99, 0x99, 0x9C, 0xA0, 0xAC,
-		0x99, 0x99, 0x99, 0x99, 0x9A, 0x9C, 0xA4, 0xAC, 0x99, 0x99, 0x99, 0x9A, 0x9C, 0xA4, 0xAC, 0x00,
-	},
-	{ // 14
-		0x00, 0x00, 0xAC, 0x9E, 0x9C, 0x9C, 0x9C, 0x9B, 0x00, 0xAC, 0x9C, 0xA0, 0x9E, 0xA4, 0xA4, 0xA4,
-		0xAC, 0x9C, 0xA4, 0xAC, 0xAC, 0xAC, 0x9C, 0x9E, 0xAC, 0xA0, 0xAC, 0xA8, 0x9E, 0xA8, 0xAC, 0x99,
-		0xAC, 0x9E, 0xAC, 0xA8, 0xAC, 0x9E, 0xA4, 0xAC, 0xAC, 0xA4, 0xA0, 0xAC, 0xAC, 0xA0, 0xA4, 0xAC,
-		0x00, 0xAC, 0xA4, 0xA0, 0xA0, 0xA4, 0xAC, 0xA4, 0x00, 0x00, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC,
-	},
-	{ // 15
-		0x9C, 0x9C, 0x9C, 0x9B, 0x9C, 0x9C, 0x9C, 0x9B, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4,
-		0x9E, 0x9E, 0x9E, 0x9C, 0x9E, 0x9E, 0x9E, 0x9E, 0x99, 0x99, 0x99, 0x99, 0x99, 0x98, 0x99, 0x98,
-		0x9C, 0x9C, 0x9B, 0x9B, 0x9B, 0x9C, 0x9C, 0x9C, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0x9E, 0x9E, 0xA0,
-		0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC,
-	},
-	{ // 16
-		0x9B, 0x9B, 0x9B, 0x9B, 0x9C, 0x9B, 0x9C, 0x9C, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4,
-		0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9E, 0x98, 0x98, 0x98, 0x98, 0x99, 0x99, 0x99, 0x99,
-		0x9C, 0x9B, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0xA0, 0xA0, 0xA0, 0x9E, 0xA0, 0x9E, 0x9E, 0xA0,
-		0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC,
-	},
-	{ // 17
-		0x9C, 0x9C, 0x9C, 0x9B, 0x9B, 0x9B, 0x9C, 0x9B, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4,
-		0x9E, 0x9E, 0x9E, 0x9C, 0x9C, 0x9C, 0x9E, 0x9E, 0x98, 0x98, 0x98, 0x99, 0x9A, 0x9A, 0x99, 0x98,
-		0x9C, 0x9B, 0x9C, 0x9C, 0x9C, 0x9B, 0x9B, 0x9C, 0xA0, 0x9E, 0x9E, 0xA0, 0xA0, 0xA0, 0xA0, 0x9E,
-		0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC,
-	},
-	{ // 18
-		0x9B, 0x9B, 0x9C, 0x9C, 0x9C, 0x9B, 0x9B, 0x9B, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4,
-		0x9E, 0x9E, 0x9E, 0x9E, 0x9C, 0x9C, 0x9C, 0x9E, 0x98, 0x98, 0x98, 0x98, 0x9A, 0x9A, 0x98, 0x99,
-		0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9B, 0x9C, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0xA0, 0xA0, 0xA0,
-		0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC,
-	},
-	{ // 19
-		0x9C, 0x9B, 0x9C, 0x9C, 0xA0, 0xA4, 0xAC, 0x00, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xAC, 0x00, 0x00,
-		0x9E, 0x9E, 0x9C, 0x9C, 0x9E, 0xA0, 0xAC, 0x00, 0x99, 0x98, 0x98, 0x99, 0x9A, 0x9A, 0xA0, 0xAC,
-		0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0xA0, 0xAC, 0xA0, 0xA0, 0x9E, 0xA0, 0xA0, 0xA0, 0xA0, 0xAC,
-		0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xAC, 0x00, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0x00, 0x00,
-	}
-};
-
-const byte TEXT_COLORS[40][4] = {
-	{ 0x00, 0x19, 0x19, 0x19 },
-	{ 0x00, 0x08, 0x08, 0x08 },
-	{ 0x00, 0x0F, 0x0F, 0x0F },
-	{ 0x00, 0x15, 0x15, 0x15 },
-	{ 0x00, 0x01, 0x01, 0x01 },
-	{ 0x00, 0x21, 0x21, 0x21 },
-	{ 0x00, 0x26, 0x26, 0x26 },
-	{ 0x00, 0x2B, 0x2B, 0x2B },
-	{ 0x00, 0x31, 0x31, 0x31 },
-	{ 0x00, 0x36, 0x36, 0x36 },
-	{ 0x00, 0x3D, 0x3D, 0x3D },
-	{ 0x00, 0x41, 0x41, 0x41 },
-	{ 0x00, 0x46, 0x46, 0x46 },
-	{ 0x00, 0x4C, 0x4C, 0x4C },
-	{ 0x00, 0x50, 0x50, 0x50 },
-	{ 0x00, 0x55, 0x55, 0x55 },
-	{ 0x00, 0x5D, 0x5D, 0x5D },
-	{ 0x00, 0x60, 0x60, 0x60 },
-	{ 0x00, 0x65, 0x65, 0x65 },
-	{ 0x00, 0x6C, 0x6C, 0x6C },
-	{ 0x00, 0x70, 0x70, 0x70 },
-	{ 0x00, 0x75, 0x75, 0x75 },
-	{ 0x00, 0x7B, 0x7B, 0x7B },
-	{ 0x00, 0x80, 0x80, 0x80 },
-	{ 0x00, 0x85, 0x85, 0x85 },
-	{ 0x00, 0x8D, 0x8D, 0x8D },
-	{ 0x00, 0x90, 0x90, 0x90 },
-	{ 0x00, 0x97, 0x97, 0x97 },
-	{ 0x00, 0x9D, 0x9D, 0x9D },
-	{ 0x00, 0xA4, 0xA4, 0xA4 },
-	{ 0x00, 0xAB, 0xAB, 0xAB },
-	{ 0x00, 0xB0, 0xB0, 0xB0 },
-	{ 0x00, 0xB6, 0xB6, 0xB6 },
-	{ 0x00, 0xBD, 0xBD, 0xBD },
-	{ 0x00, 0xC0, 0xC0, 0xC0 },
-	{ 0x00, 0xC6, 0xC6, 0xC6 },
-	{ 0x00, 0xCD, 0xCD, 0xCD },
-	{ 0x00, 0xD0, 0xD0, 0xD0 },
-	{ 0x00, 0xD6, 0xD6, 0xD6 },
-	{ 0x00, 0xDB, 0xDB, 0xDB },
-};
-
-} // End of namespace Xeen
diff --git a/engines/xeen/resdata.h b/engines/xeen/resdata.h
deleted file mode 100644
index 3c549fc..0000000
--- a/engines/xeen/resdata.h
+++ /dev/null
@@ -1,41 +0,0 @@
-/* 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_RESDATA_H
-#define XEEN_RESDATA_H
-
-#include "common/scummsys.h"
-#include "gui/debugger.h"
-
-namespace Xeen {
-
-extern const char *const CREDITS;
-
-extern const char *const OPTIONS_TITLE;
-
-extern const byte SYMBOLS[20][64];
-
-extern const byte TEXT_COLORS[40][4];
-
-} // End of namespace Xeen
-
-#endif	/* XEEN_RESDATA_H */
diff --git a/engines/xeen/resources.cpp b/engines/xeen/resources.cpp
index ba2889f..d1177da 100644
--- a/engines/xeen/resources.cpp
+++ b/engines/xeen/resources.cpp
@@ -8,12 +8,12 @@
  * 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.
@@ -21,365 +21,215 @@
  */
 
 #include "common/scummsys.h"
-#include "common/archive.h"
-#include "common/memstream.h"
-#include "common/textconsole.h"
-#include "xeen/xeen.h"
 #include "xeen/resources.h"
 
 namespace Xeen {
 
-/**
- * Xeen CC file implementation
- */
-class CCArchive : public Common::Archive {
-private:
-	/**
-	 * Details of a single entry in a CC file index
-	 */
-	struct CCEntry {
-		uint16 _id;
-		uint32 _offset;
-		uint16 _size;
-
-		CCEntry() : _id(0), _offset(0), _size(0) {}
-		CCEntry(uint16 id, uint32 offset, uint32 size)
-			: _id(id), _offset(offset), _size(size) {
-		}
-	};
-
-	Common::Array<CCEntry> _index;
-	Common::String _filename;
-
-	uint16 convertNameToId(const Common::String &resourceName) const;
-
-	void loadIndex(Common::SeekableReadStream *stream);
-
-	bool getHeaderEntry(const Common::String &resourceName, CCEntry &ccEntry) const;
-public:
-	CCArchive(const Common::String &filename);
-	virtual ~CCArchive();
-
-	// Archive implementation
-	virtual bool hasFile(const Common::String &name) const;
-	virtual int listMembers(Common::ArchiveMemberList &list) const;
-	virtual const Common::ArchiveMemberPtr getMember(const Common::String &name) const;
-	virtual Common::SeekableReadStream *createReadStreamForMember(const Common::String &name) const;
-};
-
-CCArchive::CCArchive(const Common::String &filename): _filename(filename) {
-	File f(filename);
-	loadIndex(&f);
-}
-
-CCArchive::~CCArchive() {
-}
-
-// Archive implementation
-bool CCArchive::hasFile(const Common::String &name) const {
-	CCEntry ccEntry;
-	return getHeaderEntry(name, ccEntry);
-}
-
-int CCArchive::listMembers(Common::ArchiveMemberList &list) const {
-	// CC files don't maintain the original filenames, so we can't list it
-	return 0;
-}
-
-const Common::ArchiveMemberPtr CCArchive::getMember(const Common::String &name) const {
-	if (!hasFile(name))
-		return Common::ArchiveMemberPtr();
-
-	return Common::ArchiveMemberPtr(new Common::GenericArchiveMember(name, this));
-}
-
-Common::SeekableReadStream *CCArchive::createReadStreamForMember(const Common::String &name) const {
-	CCEntry ccEntry;
-
-	if (getHeaderEntry(name, ccEntry)) {
-		// Open the correct CC file
-		Common::File f;
-		if (!f.open(_filename))
-			error("Could not open CC file");
-
-		// Read in the data for the specific resource
-		f.seek(ccEntry._offset);
-		byte *data = new byte[ccEntry._size];
-		f.read(data, ccEntry._size);
-
-		// Decrypt the data
-		for (int i = 0; i < ccEntry._size; ++i)
-			data[i] ^= 0x35;
-
-		// Return the data as a stream
-		return new Common::MemoryReadStream(data, ccEntry._size, DisposeAfterUse::YES);
-	}
-
-	return nullptr;
-}
-
-/**
- * Hash a given filename to produce the Id that represents it
- */
-uint16 CCArchive::convertNameToId(const Common::String &resourceName) const {
-	if (resourceName.empty())
-		return 0xffff;
-
-	Common::String name = resourceName;
-	name.toUppercase();
-
-	const byte *msgP = (const byte *)name.c_str();
-	int total = *msgP++;
-	for (; *msgP; total += *msgP++) {
-		// Rotate the bits in 'total' right 7 places
-		total = (total & 0x007F) << 9 | (total & 0xFF80) >> 7;
-	}
-
-	return total;
-}
-
-/**
- * Load the index of a given CC file
- */
-void CCArchive::loadIndex(Common::SeekableReadStream *stream) {
-	int count = stream->readUint16LE();
-
-	// Read in the data for the archive's index
-	byte *rawIndex = new byte[count * 8];
-	stream->read(rawIndex, count * 8);
-
-	// Decrypt the index
-	int ah = 0xac;
-	for (int i = 0; i < count * 8; ++i) {
-		rawIndex[i] = (byte)(((rawIndex[i] << 2 | rawIndex[i] >> 6) + ah) & 0xff);
-		ah += 0x67;
-	}
-
-	// Extract the index data into entry structures
-	_index.reserve(count);
-	const byte *entryP = &rawIndex[0];
-	for (int i = 0; i < count; ++i, entryP += 8) {
-		CCEntry entry;
-		entry._id = READ_LE_UINT16(entryP);
-		entry._offset = READ_LE_UINT32(entryP + 2) & 0xffffff;
-		entry._size = READ_LE_UINT16(entryP + 5);
-		assert(!entryP[7]);
-
-		_index.push_back(entry);
-	}
-
-	delete[] rawIndex;
-}
-
-/**
-* Given a resource name, returns whether an entry exists, and returns
-* the header index data for that entry
-*/
-bool CCArchive::getHeaderEntry(const Common::String &resourceName, CCEntry &ccEntry) const {
-	uint16 id = convertNameToId(resourceName);
-
-	// Loop through the index
-	for (uint i = 0; i < _index.size(); ++i) {
-		if (_index[i]._id == id) {
-			ccEntry = _index[i];
-			return true;
-		}
-	}
-
-	// Could not find an entry
-	return false;
-}
-
-/*------------------------------------------------------------------------*/
-
-void Resources::init(XeenEngine *vm) {
-	Common::File f;
-
-	if (vm->getGameID() != GType_Clouds)
-		SearchMan.add("dark", new CCArchive("dark.cc"));
-	SearchMan.add("xeen", new CCArchive("xeen.cc"));
-	SearchMan.add("intro", new CCArchive("intro.cc"));
-}
-
-/*------------------------------------------------------------------------*/
-
-/**
- * Opens the given file, throwing an error if it can't be opened
- */
-void File::openFile(const Common::String &filename) {
-	if (!Common::File::open(filename))
-		error("Could not open file - %s", filename.c_str());
-}
-
-/*------------------------------------------------------------------------*/
-
-GraphicResource::GraphicResource(const Common::String &filename) {
-	// Open the resource
-	File f(filename);
-
-	// Read in a copy of the file
-	_filesize = f.size();
-	_data = new byte[_filesize];
-	f.seek(0);
-	f.read(_data, _filesize);
-}
-
-GraphicResource::~GraphicResource() {
-	delete[] _data;
-}
-
-int GraphicResource::size() const {
-	return READ_LE_UINT16(_data);
-}
-
-void GraphicResource::drawOffset(XSurface &dest, uint16 offset, const Common::Point &destPos) const {
-	// Get cell header
-	Common::MemoryReadStream f(_data, _filesize);
-	f.seek(offset);
-	int xOffset = f.readUint16LE();
-	int width = f.readUint16LE();
-	int yOffset = f.readUint16LE();
-	int height = f.readUint16LE();
-
-	if (dest.w < (xOffset + width) || dest.h < (yOffset + height))
-		dest.create(xOffset + width, yOffset + height);
-
-	// The pattern steps used in the pattern command
-	const int patternSteps[] = { 0, 1, 1, 1, 2, 2, 3, 3, 0, -1, -1, -1, -2, -2, -3, -3 };
-
-	// Main loop
-	int opr1, opr2;
-	int32 pos;
-	for (int yPos = yOffset, byteCount = 0; yPos < height + yOffset; yPos++, byteCount = 0) {
-		// The number of bytes in this scan line
-		int lineLength = f.readByte();
-
-		if (lineLength == 0) {
-			// Skip the specified number of scan lines
-			yPos += f.readByte();
-		} else {
-			// Skip the transparent pixels at the beginning of the scan line
-			int xPos = f.readByte() + xOffset; ++byteCount;
-			byte *destP = (byte *)dest.getBasePtr(destPos.x + xPos, destPos.y + yPos);
-
-			while (byteCount < lineLength) {
-				// The next byte is an opcode that determines what 
-				// operators are to follow and how to interpret them.
-				int opcode = f.readByte(); ++byteCount;
-
-				// Decode the opcode
-				int len = opcode & 0x1F;
-				int cmd = (opcode & 0xE0) >> 5;
-
-				switch (cmd) {
-				case 0:   // The following len + 1 bytes are stored as indexes into the color table.
-				case 1:   // The following len + 33 bytes are stored as indexes into the color table.
-					for (int i = 0; i < opcode + 1; ++i, ++xPos) {
-						*destP++ = f.readByte(); ++byteCount;
-					}
-					break;
-
-				case 2:   // The following byte is an index into the color table, draw it len + 3 times.
-					opr1 = f.readByte(); ++byteCount;
-					for (int i = 0; i < len + 3; ++i, ++xPos)
-						*destP++ = opr1;
-					break;
-
-				case 3:   // Stream copy command.
-					opr1 = f.readUint16LE(); byteCount += 2;
-					pos = f.pos();
-					f.seek(-opr1, SEEK_CUR);
-
-					for (int i = 0; i < len + 4; ++i, ++xPos)
-						*destP++ = f.readByte();
-
-					f.seek(pos, SEEK_SET);
-					break;
-
-				case 4:   // The following two bytes are indexes into the color table, draw the pair len + 2 times.
-					opr1 = f.readByte(); ++byteCount;
-					opr2 = f.readByte(); ++byteCount;
-					for (int i = 0; i < len + 2; ++i, xPos += 2) {
-						*destP++ = opr1;
-						*destP++ = opr2;
-					}
-					break;
-
-				case 5:   // Skip len + 1 pixels filling them with the transparent color.
-					xPos += len + 1;
-					destP += len + 1;
-					break;
-
-				case 6:   // Pattern command.
-				case 7:
-					// The pattern command has a different opcode format
-					len = opcode & 0x07;
-					cmd = (opcode >> 2) & 0x0E;
-
-					opr1 = f.readByte(); ++byteCount;
-					for (int i = 0; i < len + 3; ++i, ++xPos) {
-						*destP++ = opr1;
-						opr1 += patternSteps[cmd + (i % 2)];
-					}
-					break;
-				default:
-					break;
-				}
-			}
-
-			assert(byteCount == lineLength);
-		}
+const char *const CREDITS =
+	"\013012\010000\003c\01435Designed and Directed By:\n"
+	"\01417Jon Van Caneghem\003l\n"
+	"\n"
+	"\t025\01435Programming:\n"
+	"\t035\01417Mark Caldwell\n"
+	"\t035Dave Hathaway\n"
+	"\n"
+	"\t025\01435Sound System & FX:\n"
+	"\t035\01417Mike Heilemann\n"
+	"\n"
+	"\t025\01435Music & Speech:\n"
+	"\t035\01417Tim Tully\n"
+	"\n"
+	"\t025\01435Writing:\n"
+	"\t035\01417Paul Rattner\n"
+	"\t035Debbie Van Caneghem\n"
+	"\t035Jon Van Caneghem\013012\n"
+	"\n"
+	"\n"
+	"\t180\01435Graphics:\n"
+	"\t190\01417Jonathan P. Gwyn\n"
+	"\t190Bonita Long-Hemsath\n"
+	"\t190Julia Ulano\n"
+	"\t190Ricardo Barrera\n"
+	"\n"
+	"\t180\01435Testing:\n"
+	"\t190\01417Benjamin Bent\n"
+	"\t190Christian Dailey\n"
+	"\t190Mario Escamilla\n"
+	"\t190Marco Hunter\n"
+	"\t190Robert J. Lupo\n"
+	"\t190Clayton Retzer\n"
+	"\t190David Vela\003c";
+
+const char *const OPTIONS_TITLE = 
+	"\x0D\x01\003c\014dMight and Magic Options\n"
+	"World of Xeen\x02\n"
+	"\v117Copyright (c) 1993 NWC, Inc.\n"
+	"All Rights Reserved\x01";
+
+const byte SYMBOLS[20][64] = {
+	{ // 0
+		0x00, 0x00, 0xA8, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0x00, 0xA8, 0x9E, 0x9C, 0x9C, 0x9E, 0x9E, 0x9E,
+		0xAC, 0x9C, 0xA4, 0xAC, 0xAC, 0x9A, 0x9A, 0x9A, 0xAC, 0x9E, 0xAC, 0xA8, 0xA8, 0xA6, 0x97, 0x98,
+		0xAC, 0xA0, 0xAC, 0xAC, 0xA4, 0xA6, 0x98, 0x99, 0x00, 0xAC, 0xA0, 0xA0, 0xA8, 0xAC, 0x9A, 0x9A,
+		0x00, 0x00, 0xAC, 0xAC, 0xAC, 0xA4, 0x9B, 0x9A, 0x00, 0x00, 0x00, 0x00, 0xAC, 0xA0, 0x9B, 0x9B,
+	},
+	{ // 1
+		0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E,
+		0x99, 0x9A, 0x9A, 0x99, 0x99, 0x99, 0x9A, 0x99, 0x98, 0x98, 0x98, 0x97, 0x97, 0x97, 0x97, 0x97,
+		0x99, 0x98, 0x98, 0x99, 0x98, 0x98, 0x99, 0x99, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A,
+		0x9A, 0x9B, 0x9B, 0x9C, 0x9B, 0x9A, 0x9C, 0x9A, 0x9B, 0x9A, 0x99, 0x99, 0x99, 0x9A, 0x9A, 0x9B,
+	},
+	{ // 2
+		0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E,
+		0x99, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x99, 0x98, 0x98, 0x99, 0x98, 0x98, 0x97, 0x98, 0x98,
+		0x99, 0x98, 0x98, 0x98, 0x99, 0x99, 0x98, 0x99, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A,
+		0x9B, 0x9B, 0x9C, 0x9C, 0x9B, 0x9B, 0x9B, 0x9B, 0x99, 0x9A, 0x9B, 0x9B, 0x9A, 0x9A, 0x99, 0x9A,
+	},
+	{ // 3
+		0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E,
+		0x99, 0x9A, 0x9A, 0x9A, 0x99, 0x99, 0x99, 0x9A, 0x98, 0x98, 0x97, 0x97, 0x98, 0x98, 0x98, 0x98,
+		0x99, 0x99, 0x98, 0x99, 0x98, 0x98, 0x99, 0x99, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A,
+		0x9B, 0x9C, 0x9B, 0x9B, 0x9C, 0x9C, 0x9C, 0x9C, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x99, 0x99, 0x9A,
+	},
+	{ // 4
+		0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E,
+		0x9A, 0x9A, 0x9A, 0x99, 0x99, 0x99, 0x99, 0x9A, 0x97, 0x97, 0x97, 0x97, 0x97, 0x98, 0x98, 0x98,
+		0x99, 0x99, 0x98, 0x99, 0x99, 0x98, 0x98, 0x98, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A,
+		0x9A, 0x9C, 0x9B, 0x9B, 0x9C, 0x9B, 0x9B, 0x9B, 0x9A, 0x99, 0x9B, 0x9B, 0x9A, 0x99, 0x9A, 0x9A,
+	},
+	{ // 5
+		0xA4, 0xA4, 0xA8, 0xA8, 0x00, 0x00, 0x00, 0x00, 0x9E, 0x9E, 0x9E, 0xA0, 0xA8, 0xAC, 0x00, 0x00,
+		0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9E, 0xAC, 0x00, 0x97, 0x97, 0x97, 0x98, 0x9C, 0x9C, 0xA0, 0xAC,
+		0x99, 0x98, 0x99, 0x99, 0x99, 0x9B, 0xA0, 0xAC, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9B, 0xA0, 0xAC,
+		0x9C, 0x9B, 0x9C, 0x9C, 0x9C, 0xA0, 0xAC, 0x00, 0x99, 0x9A, 0x9A, 0x9B, 0x9B, 0xA4, 0xAC, 0x00,
+	},
+	{ // 6
+		0x00, 0x00, 0x00, 0xAC, 0xA4, 0x9C, 0x99, 0x99, 0x00, 0x00, 0x00, 0xAC, 0xA0, 0x9C, 0x9B, 0x99,
+		0x00, 0x00, 0xAC, 0xA0, 0x9C, 0x99, 0x99, 0x99, 0x00, 0xAC, 0xA0, 0x9C, 0x99, 0x98, 0x99, 0x99,
+		0x00, 0xAC, 0xA0, 0x9C, 0x9C, 0xA0, 0x9C, 0x9A, 0x00, 0x00, 0xAC, 0xA4, 0xA0, 0x99, 0x99, 0x99,
+		0x00, 0xAC, 0xA0, 0x9C, 0x99, 0x99, 0x99, 0x99, 0x00, 0xAC, 0xA4, 0x9C, 0x99, 0x99, 0x99, 0x99,
+	},
+	{ // 7
+		0xAC, 0xA0, 0x9C, 0x99, 0x99, 0x99, 0x99, 0x99, 0xAC, 0xA4, 0x9C, 0x99, 0x99, 0x99, 0x99, 0x99,
+		0x00, 0xAC, 0xA0, 0x9C, 0x99, 0x99, 0x99, 0x99, 0x00, 0x00, 0xAC, 0xA4, 0x9C, 0x9C, 0x99, 0x99,
+		0x00, 0x00, 0xAC, 0xA0, 0x9C, 0x99, 0x99, 0x99, 0x00, 0x00, 0x00, 0xAC, 0xA4, 0x9C, 0x99, 0x99,
+		0x00, 0x00, 0xAC, 0xA0, 0x9B, 0xA0, 0x9E, 0x9C, 0x00, 0xAC, 0xA4, 0x9C, 0x99, 0x9C, 0x99, 0x99,
+	},
+	{ // 8
+		0x00, 0xAC, 0xA0, 0x9C, 0x99, 0x99, 0x9B, 0x99, 0xAC, 0xA4, 0x9C, 0x99, 0x99, 0x99, 0x99, 0x99,
+		0xAC, 0xA0, 0x9C, 0x99, 0x99, 0x99, 0x99, 0x99, 0xAC, 0xA4, 0x9C, 0x99, 0x99, 0x99, 0x99, 0x99,
+		0x00, 0xAC, 0xA4, 0x9C, 0x99, 0x99, 0x99, 0x99, 0xAC, 0xA0, 0x9C, 0x99, 0x99, 0x99, 0x99, 0x99,
+		0x00, 0xAC, 0xA0, 0x9C, 0x99, 0x99, 0x9C, 0x99, 0x00, 0xAC, 0xA4, 0x9C, 0x99, 0x9E, 0x9C, 0x99,
+	},
+	{ // 9
+		0x00, 0x00, 0xAC, 0xA4, 0xA0, 0x9C, 0x99, 0x99, 0x00, 0xAC, 0xA0, 0x9C, 0x9C, 0xA0, 0x9C, 0x9A,
+		0xAC, 0xA4, 0x9C, 0x9A, 0x99, 0x99, 0x99, 0x99, 0xAC, 0xA0, 0x9C, 0x99, 0x99, 0x99, 0x99, 0x99,
+		0xAC, 0xA4, 0x9C, 0x99, 0x99, 0x99, 0x99, 0x99, 0x00, 0xAC, 0xA0, 0x9C, 0x99, 0x99, 0x99, 0x99,
+		0x00, 0xAC, 0xA4, 0x9C, 0x9A, 0x9C, 0x99, 0x99, 0x00, 0x00, 0xAC, 0xA0, 0x9C, 0x9A, 0x99, 0x99,
+	},
+	{ // 10
+		0x99, 0x99, 0x99, 0x9A, 0xA0, 0xAC, 0x00, 0x00, 0x99, 0x99, 0x99, 0x9C, 0xA0, 0xAC, 0x00, 0x00,
+		0x99, 0x99, 0x9C, 0x9E, 0xA4, 0xAC, 0x00, 0x00, 0x99, 0x99, 0x9C, 0x99, 0x9C, 0xA4, 0xAC, 0x00,
+		0x99, 0x99, 0x99, 0x99, 0x9C, 0xA0, 0xAC, 0x00, 0x99, 0x99, 0x99, 0x9C, 0xA0, 0xAC, 0x00, 0x00,
+		0x99, 0x99, 0x99, 0xA0, 0xA4, 0xAC, 0x00, 0x00, 0x9A, 0x9B, 0x9E, 0x9C, 0x9C, 0xA4, 0xAC, 0x00,
+	},
+	{ // 11
+		0x99, 0x99, 0x99, 0x99, 0x9C, 0xA0, 0xAC, 0x00, 0x99, 0x99, 0x99, 0x99, 0x99, 0x9C, 0x9E, 0xAC,
+		0x99, 0x99, 0x99, 0x99, 0x9C, 0xA0, 0xAC, 0x00, 0x99, 0x99, 0x99, 0x99, 0x9C, 0xA0, 0xAC, 0x00,
+		0x99, 0x99, 0x99, 0x99, 0x99, 0x9C, 0xA4, 0xAC, 0x99, 0x99, 0x99, 0x99, 0x99, 0x9C, 0xA0, 0xAC,
+		0x9C, 0x99, 0x99, 0x99, 0x9C, 0x9C, 0xA4, 0xAC, 0x99, 0x9E, 0x9E, 0x9C, 0x9C, 0xA0, 0xAC, 0x00,
+	},
+	{ // 12
+		0x99, 0x99, 0x9C, 0xA0, 0xA4, 0xAC, 0x00, 0x00, 0x9B, 0x9C, 0x9E, 0x9C, 0x9C, 0xA4, 0xAC, 0x00,
+		0x99, 0x99, 0x99, 0x99, 0x99, 0xA0, 0xAC, 0x00, 0x99, 0x99, 0x99, 0x99, 0x99, 0x9C, 0xA0, 0xAC,
+		0x99, 0x99, 0x99, 0x99, 0x9C, 0x9C, 0xA4, 0xAC, 0x99, 0x99, 0x99, 0x9C, 0xA0, 0xA4, 0xAC, 0x00,
+		0x99, 0x99, 0x9C, 0x99, 0x99, 0x9C, 0xA0, 0xAC, 0x99, 0x99, 0x99, 0x99, 0x99, 0x9C, 0xA0, 0xAC,
+	},
+	{ // 13
+		0x99, 0x99, 0x99, 0x99, 0x9C, 0xA0, 0xAC, 0x00, 0x99, 0x99, 0x99, 0x9C, 0xA0, 0xAC, 0x00, 0x00,
+		0x99, 0x9B, 0x9C, 0xA0, 0xA4, 0xAC, 0x00, 0x00, 0x99, 0x99, 0x9A, 0x99, 0x9C, 0xA0, 0xAC, 0x00,
+		0x99, 0x99, 0x99, 0x99, 0x99, 0x9C, 0xA4, 0xAC, 0x99, 0x99, 0x99, 0x99, 0x99, 0x9C, 0xA0, 0xAC,
+		0x99, 0x99, 0x99, 0x99, 0x9A, 0x9C, 0xA4, 0xAC, 0x99, 0x99, 0x99, 0x9A, 0x9C, 0xA4, 0xAC, 0x00,
+	},
+	{ // 14
+		0x00, 0x00, 0xAC, 0x9E, 0x9C, 0x9C, 0x9C, 0x9B, 0x00, 0xAC, 0x9C, 0xA0, 0x9E, 0xA4, 0xA4, 0xA4,
+		0xAC, 0x9C, 0xA4, 0xAC, 0xAC, 0xAC, 0x9C, 0x9E, 0xAC, 0xA0, 0xAC, 0xA8, 0x9E, 0xA8, 0xAC, 0x99,
+		0xAC, 0x9E, 0xAC, 0xA8, 0xAC, 0x9E, 0xA4, 0xAC, 0xAC, 0xA4, 0xA0, 0xAC, 0xAC, 0xA0, 0xA4, 0xAC,
+		0x00, 0xAC, 0xA4, 0xA0, 0xA0, 0xA4, 0xAC, 0xA4, 0x00, 0x00, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC,
+	},
+	{ // 15
+		0x9C, 0x9C, 0x9C, 0x9B, 0x9C, 0x9C, 0x9C, 0x9B, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4,
+		0x9E, 0x9E, 0x9E, 0x9C, 0x9E, 0x9E, 0x9E, 0x9E, 0x99, 0x99, 0x99, 0x99, 0x99, 0x98, 0x99, 0x98,
+		0x9C, 0x9C, 0x9B, 0x9B, 0x9B, 0x9C, 0x9C, 0x9C, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0x9E, 0x9E, 0xA0,
+		0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC,
+	},
+	{ // 16
+		0x9B, 0x9B, 0x9B, 0x9B, 0x9C, 0x9B, 0x9C, 0x9C, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4,
+		0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9E, 0x98, 0x98, 0x98, 0x98, 0x99, 0x99, 0x99, 0x99,
+		0x9C, 0x9B, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0xA0, 0xA0, 0xA0, 0x9E, 0xA0, 0x9E, 0x9E, 0xA0,
+		0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC,
+	},
+	{ // 17
+		0x9C, 0x9C, 0x9C, 0x9B, 0x9B, 0x9B, 0x9C, 0x9B, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4,
+		0x9E, 0x9E, 0x9E, 0x9C, 0x9C, 0x9C, 0x9E, 0x9E, 0x98, 0x98, 0x98, 0x99, 0x9A, 0x9A, 0x99, 0x98,
+		0x9C, 0x9B, 0x9C, 0x9C, 0x9C, 0x9B, 0x9B, 0x9C, 0xA0, 0x9E, 0x9E, 0xA0, 0xA0, 0xA0, 0xA0, 0x9E,
+		0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC,
+	},
+	{ // 18
+		0x9B, 0x9B, 0x9C, 0x9C, 0x9C, 0x9B, 0x9B, 0x9B, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4,
+		0x9E, 0x9E, 0x9E, 0x9E, 0x9C, 0x9C, 0x9C, 0x9E, 0x98, 0x98, 0x98, 0x98, 0x9A, 0x9A, 0x98, 0x99,
+		0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9B, 0x9C, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0xA0, 0xA0, 0xA0,
+		0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC,
+	},
+	{ // 19
+		0x9C, 0x9B, 0x9C, 0x9C, 0xA0, 0xA4, 0xAC, 0x00, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xAC, 0x00, 0x00,
+		0x9E, 0x9E, 0x9C, 0x9C, 0x9E, 0xA0, 0xAC, 0x00, 0x99, 0x98, 0x98, 0x99, 0x9A, 0x9A, 0xA0, 0xAC,
+		0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0xA0, 0xAC, 0xA0, 0xA0, 0x9E, 0xA0, 0xA0, 0xA0, 0xA0, 0xAC,
+		0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xAC, 0x00, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0x00, 0x00,
 	}
+};
 
-	dest.addDirtyRect(Common::Rect(destPos.x + xOffset, destPos.y + yOffset,
-		destPos.x + xOffset + width, destPos.y + yOffset + height));
-}
-
-/*------------------------------------------------------------------------*/
-
-FramesResource::FramesResource(const Common::String &filename) :
-		GraphicResource(filename) {
-	// Read in the index
-	Common::MemoryReadStream f(_data, _filesize);
-	int count = f.readUint16LE();
-	_index.resize(count);
-
-	for (int i = 0; i < count; ++i) {
-		_index[i] = f.readUint32LE();
-	}
-}
-
-void FramesResource::draw(XSurface &dest, int frame, const Common::Point &destPos) const {
-	drawOffset(dest, _index[frame], destPos);
-}
-
-void FramesResource::draw(XSurface &dest, int frame) const {
-	draw(dest, frame, Common::Point());
-}
-
-/*------------------------------------------------------------------------*/
-
-SpriteResource::SpriteResource(const Common::String &filename) : 
-		GraphicResource(filename) {
-	// Read in the index
-	Common::MemoryReadStream f(_data, _filesize);
-	int count = f.readUint16LE();
-	_index.resize(count);
-
-	for (int i = 0; i < count; ++i) {
-		_index[i]._offset1 = f.readUint16LE();
-		_index[i]._offset2 = f.readUint16LE();
-	}
-}
-
-void SpriteResource::draw(XSurface &dest, int frame, const Common::Point &destPos) const {
-	drawOffset(dest, _index[frame]._offset1, destPos);
-	if (_index[frame]._offset2)
-		drawOffset(dest, _index[frame]._offset2, destPos);
-}
-
-void SpriteResource::draw(XSurface &dest, int frame) const {
-	draw(dest, frame, Common::Point());
-}
+const byte TEXT_COLORS[40][4] = {
+	{ 0x00, 0x19, 0x19, 0x19 },
+	{ 0x00, 0x08, 0x08, 0x08 },
+	{ 0x00, 0x0F, 0x0F, 0x0F },
+	{ 0x00, 0x15, 0x15, 0x15 },
+	{ 0x00, 0x01, 0x01, 0x01 },
+	{ 0x00, 0x21, 0x21, 0x21 },
+	{ 0x00, 0x26, 0x26, 0x26 },
+	{ 0x00, 0x2B, 0x2B, 0x2B },
+	{ 0x00, 0x31, 0x31, 0x31 },
+	{ 0x00, 0x36, 0x36, 0x36 },
+	{ 0x00, 0x3D, 0x3D, 0x3D },
+	{ 0x00, 0x41, 0x41, 0x41 },
+	{ 0x00, 0x46, 0x46, 0x46 },
+	{ 0x00, 0x4C, 0x4C, 0x4C },
+	{ 0x00, 0x50, 0x50, 0x50 },
+	{ 0x00, 0x55, 0x55, 0x55 },
+	{ 0x00, 0x5D, 0x5D, 0x5D },
+	{ 0x00, 0x60, 0x60, 0x60 },
+	{ 0x00, 0x65, 0x65, 0x65 },
+	{ 0x00, 0x6C, 0x6C, 0x6C },
+	{ 0x00, 0x70, 0x70, 0x70 },
+	{ 0x00, 0x75, 0x75, 0x75 },
+	{ 0x00, 0x7B, 0x7B, 0x7B },
+	{ 0x00, 0x80, 0x80, 0x80 },
+	{ 0x00, 0x85, 0x85, 0x85 },
+	{ 0x00, 0x8D, 0x8D, 0x8D },
+	{ 0x00, 0x90, 0x90, 0x90 },
+	{ 0x00, 0x97, 0x97, 0x97 },
+	{ 0x00, 0x9D, 0x9D, 0x9D },
+	{ 0x00, 0xA4, 0xA4, 0xA4 },
+	{ 0x00, 0xAB, 0xAB, 0xAB },
+	{ 0x00, 0xB0, 0xB0, 0xB0 },
+	{ 0x00, 0xB6, 0xB6, 0xB6 },
+	{ 0x00, 0xBD, 0xBD, 0xBD },
+	{ 0x00, 0xC0, 0xC0, 0xC0 },
+	{ 0x00, 0xC6, 0xC6, 0xC6 },
+	{ 0x00, 0xCD, 0xCD, 0xCD },
+	{ 0x00, 0xD0, 0xD0, 0xD0 },
+	{ 0x00, 0xD6, 0xD6, 0xD6 },
+	{ 0x00, 0xDB, 0xDB, 0xDB },
+};
 
 } // End of namespace Xeen
diff --git a/engines/xeen/resources.h b/engines/xeen/resources.h
index 0476319..d24b1fe 100644
--- a/engines/xeen/resources.h
+++ b/engines/xeen/resources.h
@@ -8,12 +8,12 @@
  * 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.
@@ -24,84 +24,18 @@
 #define XEEN_RESOURCES_H
 
 #include "common/scummsys.h"
-#include "common/array.h"
-#include "common/file.h"
-#include "graphics/surface.h"
-#include "xeen/xsurface.h"
+#include "gui/debugger.h"
 
 namespace Xeen {
 
-class XeenEngine;
-
-class Resources {
-public:
-	/**
-	 * Instantiates the resource manager
-	 */
-	static void init(XeenEngine *vm);
-};
-
-/**
- * Derived file class
- */
-class File : public Common::File {
-public:
-	File() : Common::File() {}
-	File(const Common::String &filename) { openFile(filename); }
-	virtual ~File() {}
-
-	void openFile(const Common::String &filename);
-};
-
-class GraphicResource {
-protected:
-	int32 _filesize;
-	byte *_data;
-
-	void drawOffset(XSurface &dest, uint16 offset, const Common::Point &destPos) const;
-public:
-	GraphicResource(const Common::String &filename);
-
-	virtual ~GraphicResource();
-
-	int size() const;
-};
-
-/**
- * Defines a resource that Contains a list of singular sprite frames 
- */
-class FramesResource : public GraphicResource {
-private:
-	Common::Array<uint32> _index;
-public:
-	FramesResource(const Common::String &filename);
-	virtual ~FramesResource() {}
-
-	void draw(XSurface &dest, int frame, const Common::Point &destPos) const;
-
-	void draw(XSurface &dest, int frame) const;
-};
-
-/**
- * Defines a resource that contains sets of two layered sprites per frame
- */
-class SpriteResource : public GraphicResource {
-private:
-	struct IndexEntry {
-		uint16 _offset1, _offset2;
-	};
-	Common::Array<IndexEntry> _index;
-
-public:
-	SpriteResource(const Common::String &filename);
+extern const char *const CREDITS;
 
-	virtual ~SpriteResource() {}
+extern const char *const OPTIONS_TITLE;
 
-	void draw(XSurface &dest, int frame, const Common::Point &destPos) const;
+extern const byte SYMBOLS[20][64];
 
-	void draw(XSurface &dest, int frame) const;
-};
+extern const byte TEXT_COLORS[40][4];
 
 } // End of namespace Xeen
 
-#endif /* MADS_RESOURCES_H */
+#endif	/* XEEN_RESOURCES_H */
diff --git a/engines/xeen/sound.h b/engines/xeen/sound.h
index 73f5aa0..f375b98 100644
--- a/engines/xeen/sound.h
+++ b/engines/xeen/sound.h
@@ -25,7 +25,7 @@
 
 #include "common/scummsys.h"
 #include "common/system.h"
-#include "xeen/resources.h"
+#include "xeen/files.h"
 
 namespace Xeen {
 
diff --git a/engines/xeen/sprites.cpp b/engines/xeen/sprites.cpp
new file mode 100644
index 0000000..1b18e98
--- /dev/null
+++ b/engines/xeen/sprites.cpp
@@ -0,0 +1,201 @@
+/* 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 "common/archive.h"
+#include "common/memstream.h"
+#include "common/textconsole.h"
+#include "xeen/xeen.h"
+#include "xeen/sprites.h"
+
+namespace Xeen {
+
+GraphicResource::GraphicResource(const Common::String &filename) {
+	// Open the resource
+	File f(filename);
+
+	// Read in a copy of the file
+	_filesize = f.size();
+	_data = new byte[_filesize];
+	f.seek(0);
+	f.read(_data, _filesize);
+}
+
+GraphicResource::~GraphicResource() {
+	delete[] _data;
+}
+
+int GraphicResource::size() const {
+	return READ_LE_UINT16(_data);
+}
+
+void GraphicResource::drawOffset(XSurface &dest, uint16 offset, const Common::Point &destPos) const {
+	// Get cell header
+	Common::MemoryReadStream f(_data, _filesize);
+	f.seek(offset);
+	int xOffset = f.readUint16LE();
+	int width = f.readUint16LE();
+	int yOffset = f.readUint16LE();
+	int height = f.readUint16LE();
+
+	if (dest.w < (xOffset + width) || dest.h < (yOffset + height))
+		dest.create(xOffset + width, yOffset + height);
+
+	// The pattern steps used in the pattern command
+	const int patternSteps[] = { 0, 1, 1, 1, 2, 2, 3, 3, 0, -1, -1, -1, -2, -2, -3, -3 };
+
+	// Main loop
+	int opr1, opr2;
+	int32 pos;
+	for (int yPos = yOffset, byteCount = 0; yPos < height + yOffset; yPos++, byteCount = 0) {
+		// The number of bytes in this scan line
+		int lineLength = f.readByte();
+
+		if (lineLength == 0) {
+			// Skip the specified number of scan lines
+			yPos += f.readByte();
+		} else {
+			// Skip the transparent pixels at the beginning of the scan line
+			int xPos = f.readByte() + xOffset; ++byteCount;
+			byte *destP = (byte *)dest.getBasePtr(destPos.x + xPos, destPos.y + yPos);
+
+			while (byteCount < lineLength) {
+				// The next byte is an opcode that determines what 
+				// operators are to follow and how to interpret them.
+				int opcode = f.readByte(); ++byteCount;
+
+				// Decode the opcode
+				int len = opcode & 0x1F;
+				int cmd = (opcode & 0xE0) >> 5;
+
+				switch (cmd) {
+				case 0:   // The following len + 1 bytes are stored as indexes into the color table.
+				case 1:   // The following len + 33 bytes are stored as indexes into the color table.
+					for (int i = 0; i < opcode + 1; ++i, ++xPos) {
+						*destP++ = f.readByte(); ++byteCount;
+					}
+					break;
+
+				case 2:   // The following byte is an index into the color table, draw it len + 3 times.
+					opr1 = f.readByte(); ++byteCount;
+					for (int i = 0; i < len + 3; ++i, ++xPos)
+						*destP++ = opr1;
+					break;
+
+				case 3:   // Stream copy command.
+					opr1 = f.readUint16LE(); byteCount += 2;
+					pos = f.pos();
+					f.seek(-opr1, SEEK_CUR);
+
+					for (int i = 0; i < len + 4; ++i, ++xPos)
+						*destP++ = f.readByte();
+
+					f.seek(pos, SEEK_SET);
+					break;
+
+				case 4:   // The following two bytes are indexes into the color table, draw the pair len + 2 times.
+					opr1 = f.readByte(); ++byteCount;
+					opr2 = f.readByte(); ++byteCount;
+					for (int i = 0; i < len + 2; ++i, xPos += 2) {
+						*destP++ = opr1;
+						*destP++ = opr2;
+					}
+					break;
+
+				case 5:   // Skip len + 1 pixels filling them with the transparent color.
+					xPos += len + 1;
+					destP += len + 1;
+					break;
+
+				case 6:   // Pattern command.
+				case 7:
+					// The pattern command has a different opcode format
+					len = opcode & 0x07;
+					cmd = (opcode >> 2) & 0x0E;
+
+					opr1 = f.readByte(); ++byteCount;
+					for (int i = 0; i < len + 3; ++i, ++xPos) {
+						*destP++ = opr1;
+						opr1 += patternSteps[cmd + (i % 2)];
+					}
+					break;
+				default:
+					break;
+				}
+			}
+
+			assert(byteCount == lineLength);
+		}
+	}
+
+	dest.addDirtyRect(Common::Rect(destPos.x + xOffset, destPos.y + yOffset,
+		destPos.x + xOffset + width, destPos.y + yOffset + height));
+}
+
+/*------------------------------------------------------------------------*/
+
+FramesResource::FramesResource(const Common::String &filename) :
+		GraphicResource(filename) {
+	// Read in the index
+	Common::MemoryReadStream f(_data, _filesize);
+	int count = f.readUint16LE();
+	_index.resize(count);
+
+	for (int i = 0; i < count; ++i) {
+		_index[i] = f.readUint32LE();
+	}
+}
+
+void FramesResource::draw(XSurface &dest, int frame, const Common::Point &destPos) const {
+	drawOffset(dest, _index[frame], destPos);
+}
+
+void FramesResource::draw(XSurface &dest, int frame) const {
+	draw(dest, frame, Common::Point());
+}
+
+/*------------------------------------------------------------------------*/
+
+SpriteResource::SpriteResource(const Common::String &filename) : 
+		GraphicResource(filename) {
+	// Read in the index
+	Common::MemoryReadStream f(_data, _filesize);
+	int count = f.readUint16LE();
+	_index.resize(count);
+
+	for (int i = 0; i < count; ++i) {
+		_index[i]._offset1 = f.readUint16LE();
+		_index[i]._offset2 = f.readUint16LE();
+	}
+}
+
+void SpriteResource::draw(XSurface &dest, int frame, const Common::Point &destPos) const {
+	drawOffset(dest, _index[frame]._offset1, destPos);
+	if (_index[frame]._offset2)
+		drawOffset(dest, _index[frame]._offset2, destPos);
+}
+
+void SpriteResource::draw(XSurface &dest, int frame) const {
+	draw(dest, frame, Common::Point());
+}
+
+} // End of namespace Xeen
diff --git a/engines/xeen/sprites.h b/engines/xeen/sprites.h
new file mode 100644
index 0000000..6c01a9f
--- /dev/null
+++ b/engines/xeen/sprites.h
@@ -0,0 +1,87 @@
+/* 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_SPRITES_H
+#define XEEN_SPRITES_H
+
+#include "common/scummsys.h"
+#include "common/array.h"
+#include "common/file.h"
+#include "graphics/surface.h"
+#include "xeen/xsurface.h"
+
+namespace Xeen {
+
+class XeenEngine;
+
+class GraphicResource {
+protected:
+	int32 _filesize;
+	byte *_data;
+
+	void drawOffset(XSurface &dest, uint16 offset, const Common::Point &destPos) const;
+public:
+	GraphicResource(const Common::String &filename);
+
+	virtual ~GraphicResource();
+
+	int size() const;
+};
+
+/**
+ * Defines a resource that Contains a list of singular sprite frames 
+ */
+class FramesResource : public GraphicResource {
+private:
+	Common::Array<uint32> _index;
+public:
+	FramesResource(const Common::String &filename);
+	virtual ~FramesResource() {}
+
+	void draw(XSurface &dest, int frame, const Common::Point &destPos) const;
+
+	void draw(XSurface &dest, int frame) const;
+};
+
+/**
+ * Defines a resource that contains sets of two layered sprites per frame
+ */
+class SpriteResource : public GraphicResource {
+private:
+	struct IndexEntry {
+		uint16 _offset1, _offset2;
+	};
+	Common::Array<IndexEntry> _index;
+
+public:
+	SpriteResource(const Common::String &filename);
+
+	virtual ~SpriteResource() {}
+
+	void draw(XSurface &dest, int frame, const Common::Point &destPos) const;
+
+	void draw(XSurface &dest, int frame) const;
+};
+
+} // End of namespace Xeen
+
+#endif /* MADS_SPRITES_H */
diff --git a/engines/xeen/xeen.cpp b/engines/xeen/xeen.cpp
index cbdb6f3..b61d6a6 100644
--- a/engines/xeen/xeen.cpp
+++ b/engines/xeen/xeen.cpp
@@ -29,7 +29,7 @@
 #include "graphics/thumbnail.h"
 #include "xeen/xeen.h"
 #include "xeen/dialogs_options.h"
-#include "xeen/resources.h"
+#include "xeen/files.h"
 
 namespace Xeen {
 
@@ -58,7 +58,7 @@ void XeenEngine::initialize() {
 	DebugMan.addDebugChannel(kDebugSound, "sound", "Sound and Music handling");
 
 	// Create sub-objects of the engine
-	Resources::init(this);
+	FileManager::init(this);
 	_debugger = new Debugger(this);
 	_events = new EventsManager(this);
 	_screen = new Screen(this);
diff --git a/engines/xeen/xsurface.cpp b/engines/xeen/xsurface.cpp
index dc42a6f..698e478 100644
--- a/engines/xeen/xsurface.cpp
+++ b/engines/xeen/xsurface.cpp
@@ -23,7 +23,7 @@
 #include "common/algorithm.h"
 #include "common/util.h"
 #include "xeen/xsurface.h"
-#include "xeen/resdata.h"
+#include "xeen/resources.h"
 
 namespace Xeen {
 


Commit: 971a70a2b3cea2ab6d0d77b130c8300ad5f05ca7
    https://github.com/scummvm/scummvm/commit/971a70a2b3cea2ab6d0d77b130c8300ad5f05ca7
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-01-01T19:15:08-10:00

Commit Message:
XEEN: Implemented party and condition classes

Changed paths:
  A engines/xeen/items.cpp
  A engines/xeen/items.h
  A engines/xeen/saves.cpp
  A engines/xeen/saves.h
    engines/xeen/module.mk
    engines/xeen/xeen.cpp
    engines/xeen/xeen.h



diff --git a/engines/xeen/items.cpp b/engines/xeen/items.cpp
new file mode 100644
index 0000000..e22e865
--- /dev/null
+++ b/engines/xeen/items.cpp
@@ -0,0 +1,39 @@
+/* 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 "xeen/items.h"
+
+namespace Xeen {
+
+XeenItem::XeenItem() {
+	_material = _name = _bonusFlags = 0;
+	_equipped = false;
+}
+
+void XeenItem::synchronize(Common::Serializer &s) {
+	s.syncAsByte(_material);
+	s.syncAsByte(_name);
+	s.syncAsByte(_bonusFlags);
+	s.syncAsByte(_equipped);
+}
+
+} // End of namespace Xeen
diff --git a/engines/xeen/items.h b/engines/xeen/items.h
new file mode 100644
index 0000000..eba2354
--- /dev/null
+++ b/engines/xeen/items.h
@@ -0,0 +1,45 @@
+/* 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_ITEMS_H
+#define XEEN_ITEMS_H
+
+#include "common/scummsys.h"
+#include "common/serializer.h"
+
+namespace Xeen {
+
+class XeenItem {
+public:
+	int _material;
+	int _name;
+	int _bonusFlags;
+	bool _equipped;
+public:
+	XeenItem();
+
+	void synchronize(Common::Serializer &s);
+};
+
+} // End of namespace Xeen
+
+#endif	/* XEEN_ITEMS_H */
diff --git a/engines/xeen/module.mk b/engines/xeen/module.mk
index cdd8e54..2f5a092 100644
--- a/engines/xeen/module.mk
+++ b/engines/xeen/module.mk
@@ -11,8 +11,10 @@ MODULE_OBJS := \
 	events.o \
 	files.o \
 	font.o \
+	items.o \
 	resdata.o \
 	resources.o \
+	saves.o \
 	screen.o \
 	sound.o \
 	sprites.o \
diff --git a/engines/xeen/saves.cpp b/engines/xeen/saves.cpp
new file mode 100644
index 0000000..af74b58
--- /dev/null
+++ b/engines/xeen/saves.cpp
@@ -0,0 +1,292 @@
+/* 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 "common/algorithm.h"
+#include "xeen/saves.h"
+
+namespace Xeen {
+
+AttributePair::AttributePair() {
+	_temporary = _permanent = 0;
+}
+
+void AttributePair::synchronize(Common::Serializer &s) {
+	s.syncAsByte(_permanent);
+	s.syncAsByte(_temporary);
+}
+
+/*------------------------------------------------------------------------*/
+
+Roster::Roster() {
+	_partyCount = 0;
+	_realPartyCount = 0;
+	Common::fill(&_partyMembers[0], &_partyMembers[8], 0);
+	_mazeDirection = DIR_NORTH;
+	_mazeId = _priorMazeId = 0;
+	_levitateActive = false;
+	_automapOn = false;
+	_wizardEyeActive = false;
+	_clairvoyanceActive = false;
+	_walkOnWaterActive = false;
+	_blessedActive = false;
+	_powerShieldActive = false;
+	_holyBonusActive = false;
+	_heroismActive = false;
+	_difficulty = ADVENTURER;
+	_cloudsEnd = false;
+	_darkSideEnd = false;
+	_worldEnd = false;
+	hour_maybe = 0;
+	_day = 0;
+	_year = 0;
+	_minutes = 0;
+	_food = 0;
+	_lightCount = 0;
+	_torchCount = 0;
+	_fireResistence = 0;
+	_electricityResistence = 0;
+	_coldResistence = 0;
+	_poisonResistence = 0;
+	_deathCount = 0;
+	_winCount = 0;
+	_lossCount = 0;
+	_gold = 0;
+	_gems = 0;
+	_bankGold = 0;
+	_bankGems = 0;
+	_totalTime = 0;
+	_rested = false;
+	Common::fill(&_gameFlags[0], &_gameFlags[256], false);
+	Common::fill(&_autoNotes[0], &_autoNotes[128], false);
+	Common::fill(&_quests[0], &_quests[64], false);
+	Common::fill(&_questItems[0], &_questItems[65], 0);
+	Common::fill(&_characterFlags[0][0], &_characterFlags[30][24], false);
+}
+
+void Roster::synchronize(Common::Serializer &s) {
+	byte dummy[30];
+	Common::fill(&dummy[0], &dummy[30], 0);
+
+	s.syncAsByte(_partyCount);
+	s.syncAsByte(_realPartyCount);
+	for (int i = 0; i < 8; ++i)
+		s.syncAsByte(_partyMembers[i]);
+	s.syncAsByte(_mazeDirection);
+	s.syncAsByte(_mazePosition.x);
+	s.syncAsByte(_mazePosition.y);
+	s.syncAsByte(_mazeId);
+	
+	// Game configuration flags not used in this implementation
+	s.syncBytes(dummy, 3);
+
+	s.syncAsByte(_priorMazeId);
+	s.syncAsByte(_levitateActive);
+	s.syncAsByte(_automapOn);
+	s.syncAsByte(_wizardEyeActive);
+	s.syncAsByte(_clairvoyanceActive);
+	s.syncAsByte(_walkOnWaterActive);
+	s.syncAsByte(_blessedActive);
+	s.syncAsByte(_powerShieldActive);
+	s.syncAsByte(_holyBonusActive);
+	s.syncAsByte(_heroismActive);
+	s.syncAsByte(_difficulty);
+
+	for (int i = 0; ITEMS_COUNT; ++i)
+		_blacksmithWeapons[i].synchronize(s);
+	for (int i = 0; ITEMS_COUNT; ++i)
+		_blacksmithArmor[i].synchronize(s);
+	for (int i = 0; ITEMS_COUNT; ++i)
+		_blacksmithAccessories[i].synchronize(s);
+	for (int i = 0; ITEMS_COUNT; ++i)
+		_blacksmithMisc[i].synchronize(s);
+
+	s.syncAsUint16LE(_cloudsEnd);
+	s.syncAsUint16LE(_darkSideEnd);
+	s.syncAsUint16LE(_worldEnd);
+	s.syncAsUint16LE(hour_maybe);
+	s.syncAsUint16LE(_day);
+	s.syncAsUint16LE(_year);
+	s.syncAsUint16LE(_minutes);
+	s.syncAsUint16LE(_food);
+	s.syncAsUint16LE(_lightCount);
+	s.syncAsUint16LE(_torchCount);
+	s.syncAsUint16LE(_fireResistence);
+	s.syncAsUint16LE(_electricityResistence);
+	s.syncAsUint16LE(_coldResistence);
+	s.syncAsUint16LE(_poisonResistence);
+	s.syncAsUint16LE(_deathCount);
+	s.syncAsUint16LE(_winCount);
+	s.syncAsUint16LE(_lossCount);
+	s.syncAsUint32LE(_gold);
+	s.syncAsUint32LE(_gems);
+	s.syncAsUint32LE(_bankGold);
+	s.syncAsUint32LE(_bankGems);
+	s.syncAsUint32LE(_totalTime);
+	s.syncAsByte(_rested);
+	SavesManager::syncBitFlags(s, &_gameFlags[0], &_gameFlags[512]);
+	SavesManager::syncBitFlags(s, &_autoNotes[0], &_autoNotes[128]);
+	SavesManager::syncBitFlags(s, &_quests[0], &_quests[64]);
+	
+	for (int i = 0; i < 85; ++i)
+		s.syncAsByte(_questItems[i]);
+
+	for (int i = 0; ITEMS_COUNT; ++i)
+		_blacksmithWeapons2[i].synchronize(s);
+	for (int i = 0; ITEMS_COUNT; ++i)
+		_blacksmithArmor2[i].synchronize(s);
+	for (int i = 0; ITEMS_COUNT; ++i)
+		_blacksmithAccessories2[i].synchronize(s);
+	for (int i = 0; ITEMS_COUNT; ++i)
+		_blacksmithMisc2[i].synchronize(s);
+	
+	SavesManager::syncBitFlags(s, &_characterFlags[0][0], &_characterFlags[30][24]);
+	s.syncBytes(&dummy[0], 30);
+}
+
+/*------------------------------------------------------------------------*/
+
+PlayerStruct::PlayerStruct() {
+	_sex = MALE;
+	_race = HUMAN;
+	_xeenSide = 0;
+	_class = KNIGHT;
+	_ACTemp = 0;
+	_dbDay = 0;
+	_tempAge = 0;
+	Common::fill(&_skills[0], &_skills[18], 0);
+	Common::fill(&_awards[0], &_awards[64], false);
+	Common::fill(&_spells[9], &_spells[40], false);
+	_lloydMap = 0;
+	_hasSpells = false;
+	_currentSpell = 0;
+	_quickOption = 0;
+	_lloydSide = 0;
+	Common::fill(&_conditions[0], &_conditions[16], 0);
+	_townUnknown = 0;
+	_unknown2 = 0;
+	_currentHp = 0;
+	_currentSp = 0;
+	_ybDay = 0;
+	_experience = 0;
+	_currentAdventuringSpell = 0;
+	_currentCombatSpell = 0;
+}
+
+void PlayerStruct::synchronize(Common::Serializer &s) {
+	char name[16];
+	Common::fill(&name[0], &name[16], '\0');
+	strncpy(name, _name.c_str(), 16);
+	s.syncBytes((byte *)name, 16);
+
+	if (s.isLoading())
+		_name = Common::String(name);
+
+	s.syncAsByte(_sex);
+	s.syncAsByte(_race);
+	s.syncAsByte(_xeenSide);
+	s.syncAsByte(_class);
+
+	_might.synchronize(s);
+	_intellect.synchronize(s);
+	_personality.synchronize(s);
+	_endurance.synchronize(s);
+	_speed.synchronize(s);
+	_accuracy.synchronize(s);
+	_luck.synchronize(s);
+	s.syncAsByte(_ACTemp);
+	_level.synchronize(s);
+	s.syncAsByte(_dbDay);
+	s.syncAsByte(_tempAge);
+	
+	for (int i = 0; i < 18; ++i)
+		s.syncAsByte(_skills[i]);
+	SavesManager::syncBitFlags(s, &_awards[0], &_awards[64]);
+	SavesManager::syncBitFlags(s, &_spells[0], &_spells[40]);
+	
+	s.syncAsByte(_lloydMap);
+	s.syncAsByte(_lloydPosition.x);
+	s.syncAsByte(_lloydPosition.y);
+	s.syncAsByte(_hasSpells);
+	s.syncAsByte(_currentSpell);
+	s.syncAsByte(_quickOption);
+
+	for (int i = 0; i < 9; ++i)
+		_weapons[i].synchronize(s);
+	for (int i = 0; i < 9; ++i)
+		_armor[i].synchronize(s);
+	for (int i = 0; i < 9; ++i)
+		_accessories[i].synchronize(s);
+	for (int i = 0; i < 9; ++i)
+		_misc[i].synchronize(s);
+
+	s.syncAsByte(_lloydSide);
+	_fireResistence.synchronize(s);
+	_coldResistence.synchronize(s);
+	_electricityResistence.synchronize(s);
+	_poisonResistence.synchronize(s);
+	_energyResistence.synchronize(s);
+	_magicResistence.synchronize(s);
+	
+	for (int i = 0; i < 16; ++i)
+		s.syncAsByte(_conditions[i]);
+
+	s.syncAsUint16LE(_townUnknown);
+	s.syncAsByte(_unknown2);
+	s.syncAsUint16LE(_currentHp);
+	s.syncAsUint16LE(_currentSp);
+	s.syncAsUint16LE(_ybDay);
+	s.syncAsUint32LE(_experience);
+	s.syncAsByte(_currentAdventuringSpell);
+	s.syncAsByte(_currentCombatSpell);
+}
+
+/*------------------------------------------------------------------------*/
+
+/**
+ * Synchronizes a boolean array as a bitfield set
+ */
+void SavesManager::syncBitFlags(Common::Serializer &s, bool *startP, bool *endP) {
+	byte data = 0;
+
+	int bitCounter = 0;
+	for (bool *p = startP; p <= endP; ++p, ++bitCounter) {
+		if (bitCounter != 0 && (bitCounter % 8) == 0) {
+			s.syncAsByte(data);
+			if (p == endP)
+				break;
+
+			if (s.isSaving())
+				data = 0;
+		}
+
+		if (s.isLoading())
+			*p = (data >> bitCounter) != 0;
+		else if (*p)
+			data |= 1 << bitCounter;
+	}
+}
+
+/*------------------------------------------------------------------------*/
+
+
+} // End of namespace Xeen
diff --git a/engines/xeen/saves.h b/engines/xeen/saves.h
new file mode 100644
index 0000000..ef12efd
--- /dev/null
+++ b/engines/xeen/saves.h
@@ -0,0 +1,190 @@
+/* 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_SAVES_H
+#define XEEN_SAVES_H
+
+#include "common/scummsys.h"
+#include "common/rect.h"
+#include "common/savefile.h"
+#include "xeen/items.h"
+
+namespace Xeen {
+
+enum Direction { DIR_NORTH = 0, DIR_EAST = 1, DIR_SOUTH = 2, DIR_WEST = 3 };
+
+enum Difficulty { ADVENTURER = 0, WARRIOR = 1 };
+
+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 Skill { THIEVERY = 0, ARMS_MASTER = 1, ASTROLOGER = 2, BODYBUILDER = 3,
+	CARTOGRAPHER = 4, CRUSADER = 5, DIRECTION_SENSE = 6, LINGUIST = 7, 
+	MERCHANT = 8, MOUNTAINEER = 9, NAVIGATOR = 10, PATHFINDER = 11,
+	PRAYER_MASTER = 12, PRESTIDIGITATION = 13, SWIMMING = 14, TRACKING = 15,
+	SPOT_DOORS = 16, DANGER_SENSE = 17
+};
+
+enum Condition { CURSED = 0, HEART_BROKEN = 1, WEAK = 2, POISONED = 3,
+	DISEASED = 4, INSANE = 5, IN_LOVE = 6, DRUNK = 7, SLEEP = 8, 
+	DEPRESSED = 9, CONFUSED = 10, PARALYZED = 11
+};
+
+#define ITEMS_COUNT 36
+
+class Roster {
+public:
+	int _partyCount;
+	int _realPartyCount;
+	int _partyMembers[8];
+	Direction _mazeDirection;
+	Common::Point _mazePosition;
+	int _mazeId;
+	int _priorMazeId;
+	bool _levitateActive;
+	bool _automapOn;
+	bool _wizardEyeActive;
+	bool _clairvoyanceActive;
+	bool _walkOnWaterActive;
+	bool _blessedActive;
+	bool _powerShieldActive;
+	bool _holyBonusActive;
+	bool _heroismActive;
+	Difficulty _difficulty;
+	XeenItem _blacksmithWeapons[ITEMS_COUNT];
+	XeenItem _blacksmithArmor[ITEMS_COUNT];
+	XeenItem _blacksmithAccessories[ITEMS_COUNT];
+	XeenItem _blacksmithMisc[ITEMS_COUNT];
+	bool _cloudsEnd;
+	bool _darkSideEnd;
+	bool _worldEnd;
+	int hour_maybe;
+	int _day;
+	int _year;
+	int _minutes;
+	int _food;
+	int _lightCount;
+	int _torchCount;
+	int _fireResistence;
+	int _electricityResistence;
+	int _coldResistence;
+	int _poisonResistence;
+	int _deathCount;
+	int _winCount;
+	int _lossCount;
+	int _gold;
+	int _gems;
+	int _bankGold;
+	int _bankGems;
+	int _totalTime;
+	bool _rested;
+	bool _gameFlags[256];
+	bool _autoNotes[128];
+	bool _quests[64];
+	int _questItems[85];
+	XeenItem _blacksmithWeapons2[ITEMS_COUNT];
+	XeenItem _blacksmithArmor2[ITEMS_COUNT];
+	XeenItem _blacksmithAccessories2[ITEMS_COUNT];
+	XeenItem _blacksmithMisc2[ITEMS_COUNT];
+	bool _characterFlags[30][24];
+public:
+	Roster();
+
+	void synchronize(Common::Serializer &s);
+};
+
+class AttributePair {
+public:	
+	int _permanent;
+	int _temporary;
+public:
+	AttributePair();
+	void synchronize(Common::Serializer &s);
+};
+
+class PlayerStruct {
+public:
+	Common::String _name;
+	Sex _sex;
+	Race _race;
+	int _xeenSide;
+	CharacterClass _class;
+	AttributePair _might;
+	AttributePair _intellect;
+	AttributePair _personality;
+	AttributePair _endurance;
+	AttributePair _speed;
+	AttributePair _accuracy;
+	AttributePair _luck;
+	int _ACTemp;
+	AttributePair _level;
+	int _dbDay;
+	int _tempAge;
+	int _skills[18];
+	bool _awards[64];
+	bool _spells[40];
+	int _lloydMap;
+	Common::Point _lloydPosition;
+	bool _hasSpells;
+	int _currentSpell;
+	int _quickOption;
+	XeenItem _weapons[9];
+	XeenItem _armor[9];
+	XeenItem _accessories[9];
+	XeenItem _misc[9];
+	int _lloydSide;
+	AttributePair _fireResistence;
+	AttributePair _coldResistence;
+	AttributePair _electricityResistence;
+	AttributePair _poisonResistence;
+	AttributePair _energyResistence;
+	AttributePair _magicResistence;
+	int _conditions[16];
+	int _townUnknown;
+	int _unknown2;
+	int _currentHp;
+	int _currentSp;
+	int _ybDay;
+	uint32 _experience;
+	int _currentAdventuringSpell;
+	int _currentCombatSpell;
+public:
+	PlayerStruct();
+	void synchronize(Common::Serializer &s);
+};
+
+class SavesManager {
+public:
+	Roster _roster;
+	Common::Array<PlayerStruct> _conditions;
+public:
+	static void syncBitFlags(Common::Serializer &s, bool *startP, bool *endP);
+};
+
+} // End of namespace Xeen
+
+#endif	/* XEEN_SAVES_H */
diff --git a/engines/xeen/xeen.cpp b/engines/xeen/xeen.cpp
index b61d6a6..35b4188 100644
--- a/engines/xeen/xeen.cpp
+++ b/engines/xeen/xeen.cpp
@@ -82,6 +82,14 @@ void XeenEngine::initialize() {
 Common::Error XeenEngine::run() {
 	initialize();
 
+	showIntro();
+	if (shouldQuit())
+		return Common::kNoError;
+
+	showMainMenu();
+	if (shouldQuit())
+		return Common::kNoError;
+
 	playGame();
 
 	return Common::kNoError;
@@ -220,8 +228,21 @@ void XeenEngine::writeSavegameHeader(Common::OutSaveFile *out, XeenSavegameHeade
 //	out->writeUint32LE(_events->getFrameCounter());
 }
 
+void XeenEngine::showIntro() {
+
+}
+
+void XeenEngine::showMainMenu() {
+	//OptionsMenu::show(this);
+}
+
 void XeenEngine::playGame() {
-	OptionsMenu::show(this);
+
+}
+
+void XeenEngine::drawUI() {
+	SpriteResource sprites1("global.icn"), borderSprites("border.icn");
+
 }
 
 } // End of namespace Xeen
diff --git a/engines/xeen/xeen.h b/engines/xeen/xeen.h
index 1b99a85..2049888 100644
--- a/engines/xeen/xeen.h
+++ b/engines/xeen/xeen.h
@@ -88,6 +88,12 @@ private:
 	const XeenGameDescription *_gameDescription;
 	Common::RandomSource _randomSource;
 	int _loadSaveSlot;
+
+	void showIntro();
+
+	void showMainMenu();
+
+	void drawUI();
 protected:
 	/**
 	* Play the game


Commit: feacce66b92f17c655d70ec2cc233fc63feb517c
    https://github.com/scummvm/scummvm/commit/feacce66b92f17c655d70ec2cc233fc63feb517c
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-01-02T11:01:41-10:00

Commit Message:
XEEN: Implemented dynamic data loading for new games

Changed paths:
    engines/xeen/files.cpp
    engines/xeen/files.h
    engines/xeen/saves.cpp
    engines/xeen/saves.h
    engines/xeen/xeen.cpp
    engines/xeen/xeen.h



diff --git a/engines/xeen/files.cpp b/engines/xeen/files.cpp
index 27bbf6e..107cde4 100644
--- a/engines/xeen/files.cpp
+++ b/engines/xeen/files.cpp
@@ -29,45 +29,8 @@
 
 namespace Xeen {
 
-/**
- * Xeen CC file implementation
- */
-class CCArchive : public Common::Archive {
-private:
-	/**
-	 * Details of a single entry in a CC file index
-	 */
-	struct CCEntry {
-		uint16 _id;
-		uint32 _offset;
-		uint16 _size;
-
-		CCEntry() : _id(0), _offset(0), _size(0) {}
-		CCEntry(uint16 id, uint32 offset, uint32 size)
-			: _id(id), _offset(offset), _size(size) {
-		}
-	};
-
-	Common::Array<CCEntry> _index;
-	Common::String _filename;
-
-	uint16 convertNameToId(const Common::String &resourceName) const;
-
-	void loadIndex(Common::SeekableReadStream *stream);
-
-	bool getHeaderEntry(const Common::String &resourceName, CCEntry &ccEntry) const;
-public:
-	CCArchive(const Common::String &filename);
-	virtual ~CCArchive();
-
-	// Archive implementation
-	virtual bool hasFile(const Common::String &name) const;
-	virtual int listMembers(Common::ArchiveMemberList &list) const;
-	virtual const Common::ArchiveMemberPtr getMember(const Common::String &name) const;
-	virtual Common::SeekableReadStream *createReadStreamForMember(const Common::String &name) const;
-};
-
-CCArchive::CCArchive(const Common::String &filename): _filename(filename) {
+CCArchive::CCArchive(const Common::String &filename, bool encoded): 
+		_filename(filename), _encoded(encoded) {
 	File f(filename);
 	loadIndex(&f);
 }
@@ -107,9 +70,11 @@ Common::SeekableReadStream *CCArchive::createReadStreamForMember(const Common::S
 		byte *data = new byte[ccEntry._size];
 		f.read(data, ccEntry._size);
 
-		// Decrypt the data
-		for (int i = 0; i < ccEntry._size; ++i)
-			data[i] ^= 0x35;
+		if (_encoded) {
+			// Decrypt the data
+			for (int i = 0; i < ccEntry._size; ++i)
+				data[i] ^= 0x35;
+		}
 
 		// Return the data as a stream
 		return new Common::MemoryReadStream(data, ccEntry._size, DisposeAfterUse::YES);
@@ -192,6 +157,9 @@ bool CCArchive::getHeaderEntry(const Common::String &resourceName, CCEntry &ccEn
 
 /*------------------------------------------------------------------------*/
 
+/**
+ * Instantiates the resource manager
+ */
 void FileManager::init(XeenEngine *vm) {
 	Common::File f;
 
diff --git a/engines/xeen/files.h b/engines/xeen/files.h
index 7ef126e..8a028a9 100644
--- a/engines/xeen/files.h
+++ b/engines/xeen/files.h
@@ -33,11 +33,11 @@ namespace Xeen {
 
 class XeenEngine;
 
+/*
+ * Main resource manager
+ */
 class FileManager {
 public:
-	/**
-	 * Instantiates the resource manager
-	 */
 	static void init(XeenEngine *vm);
 };
 
@@ -53,6 +53,45 @@ public:
 	void openFile(const Common::String &filename);
 };
 
+/**
+* Xeen CC file implementation
+*/
+class CCArchive : public Common::Archive {
+private:
+	/**
+	* Details of a single entry in a CC file index
+	*/
+	struct CCEntry {
+		uint16 _id;
+		uint32 _offset;
+		uint16 _size;
+
+		CCEntry() : _id(0), _offset(0), _size(0) {}
+		CCEntry(uint16 id, uint32 offset, uint32 size)
+			: _id(id), _offset(offset), _size(size) {
+		}
+	};
+
+	Common::Array<CCEntry> _index;
+	Common::String _filename;
+	bool _encoded;
+
+	uint16 convertNameToId(const Common::String &resourceName) const;
+
+	void loadIndex(Common::SeekableReadStream *stream);
+
+	bool getHeaderEntry(const Common::String &resourceName, CCEntry &ccEntry) const;
+public:
+	CCArchive(const Common::String &filename, bool encoded = true);
+	virtual ~CCArchive();
+
+	// Archive implementation
+	virtual bool hasFile(const Common::String &name) const;
+	virtual int listMembers(Common::ArchiveMemberList &list) const;
+	virtual const Common::ArchiveMemberPtr getMember(const Common::String &name) const;
+	virtual Common::SeekableReadStream *createReadStreamForMember(const Common::String &name) const;
+};
+
 } // End of namespace Xeen
 
 #endif /* XEEN_FILES_H */
diff --git a/engines/xeen/saves.cpp b/engines/xeen/saves.cpp
index af74b58..771affc 100644
--- a/engines/xeen/saves.cpp
+++ b/engines/xeen/saves.cpp
@@ -23,6 +23,8 @@
 #include "common/scummsys.h"
 #include "common/algorithm.h"
 #include "xeen/saves.h"
+#include "xeen/files.h"
+#include "xeen/xeen.h"
 
 namespace Xeen {
 
@@ -37,7 +39,7 @@ void AttributePair::synchronize(Common::Serializer &s) {
 
 /*------------------------------------------------------------------------*/
 
-Roster::Roster() {
+Party::Party() {
 	_partyCount = 0;
 	_realPartyCount = 0;
 	Common::fill(&_partyMembers[0], &_partyMembers[8], 0);
@@ -76,14 +78,17 @@ Roster::Roster() {
 	_bankGems = 0;
 	_totalTime = 0;
 	_rested = false;
-	Common::fill(&_gameFlags[0], &_gameFlags[256], false);
+
+	Common::fill(&_gameFlags[0], &_gameFlags[512], false);
 	Common::fill(&_autoNotes[0], &_autoNotes[128], false);
 	Common::fill(&_quests[0], &_quests[64], false);
-	Common::fill(&_questItems[0], &_questItems[65], 0);
-	Common::fill(&_characterFlags[0][0], &_characterFlags[30][24], false);
+	Common::fill(&_questItems[0], &_questItems[85], 0);
+
+	for (int i = 0; i < TOTAL_CHARACTERS; ++i)
+		Common::fill(&_characterFlags[i][0], &_characterFlags[i][24], false);
 }
 
-void Roster::synchronize(Common::Serializer &s) {
+void Party::synchronize(Common::Serializer &s) {
 	byte dummy[30];
 	Common::fill(&dummy[0], &dummy[30], 0);
 
@@ -111,13 +116,13 @@ void Roster::synchronize(Common::Serializer &s) {
 	s.syncAsByte(_heroismActive);
 	s.syncAsByte(_difficulty);
 
-	for (int i = 0; ITEMS_COUNT; ++i)
+	for (int i = 0; i < ITEMS_COUNT; ++i)
 		_blacksmithWeapons[i].synchronize(s);
-	for (int i = 0; ITEMS_COUNT; ++i)
+	for (int i = 0; i < ITEMS_COUNT; ++i)
 		_blacksmithArmor[i].synchronize(s);
-	for (int i = 0; ITEMS_COUNT; ++i)
+	for (int i = 0; i < ITEMS_COUNT; ++i)
 		_blacksmithAccessories[i].synchronize(s);
-	for (int i = 0; ITEMS_COUNT; ++i)
+	for (int i = 0; i < ITEMS_COUNT; ++i)
 		_blacksmithMisc[i].synchronize(s);
 
 	s.syncAsUint16LE(_cloudsEnd);
@@ -150,16 +155,17 @@ void Roster::synchronize(Common::Serializer &s) {
 	for (int i = 0; i < 85; ++i)
 		s.syncAsByte(_questItems[i]);
 
-	for (int i = 0; ITEMS_COUNT; ++i)
+	for (int i = 0; i < ITEMS_COUNT; ++i)
 		_blacksmithWeapons2[i].synchronize(s);
-	for (int i = 0; ITEMS_COUNT; ++i)
+	for (int i = 0; i < ITEMS_COUNT; ++i)
 		_blacksmithArmor2[i].synchronize(s);
-	for (int i = 0; ITEMS_COUNT; ++i)
+	for (int i = 0; i < ITEMS_COUNT; ++i)
 		_blacksmithAccessories2[i].synchronize(s);
-	for (int i = 0; ITEMS_COUNT; ++i)
+	for (int i = 0; i < ITEMS_COUNT; ++i)
 		_blacksmithMisc2[i].synchronize(s);
 	
-	SavesManager::syncBitFlags(s, &_characterFlags[0][0], &_characterFlags[30][24]);
+	for (int i = 0; i < TOTAL_CHARACTERS; ++i)
+		SavesManager::syncBitFlags(s, &_characterFlags[i][0], &_characterFlags[i][24]);
 	s.syncBytes(&dummy[0], 30);
 }
 
@@ -174,8 +180,8 @@ PlayerStruct::PlayerStruct() {
 	_dbDay = 0;
 	_tempAge = 0;
 	Common::fill(&_skills[0], &_skills[18], 0);
-	Common::fill(&_awards[0], &_awards[64], false);
-	Common::fill(&_spells[9], &_spells[40], false);
+	Common::fill(&_awards[0], &_awards[512], false);
+	Common::fill(&_spells[9], &_spells[312], false);
 	_lloydMap = 0;
 	_hasSpells = false;
 	_currentSpell = 0;
@@ -220,8 +226,8 @@ void PlayerStruct::synchronize(Common::Serializer &s) {
 	
 	for (int i = 0; i < 18; ++i)
 		s.syncAsByte(_skills[i]);
-	SavesManager::syncBitFlags(s, &_awards[0], &_awards[64]);
-	SavesManager::syncBitFlags(s, &_spells[0], &_spells[40]);
+	SavesManager::syncBitFlags(s, &_awards[0], &_awards[512]);
+	SavesManager::syncBitFlags(s, &_spells[0], &_spells[312]);
 	
 	s.syncAsByte(_lloydMap);
 	s.syncAsByte(_lloydPosition.x);
@@ -262,6 +268,16 @@ void PlayerStruct::synchronize(Common::Serializer &s) {
 
 /*------------------------------------------------------------------------*/
 
+void Roster::synchronize(Common::Serializer &s) {
+	if (s.isLoading())
+		resize(30);
+
+	for (uint i = 0; i < 30; ++i)
+		(*this)[i].synchronize(s);
+}
+
+/*------------------------------------------------------------------------*/
+
 /**
  * Synchronizes a boolean array as a bitfield set
  */
@@ -269,9 +285,10 @@ void SavesManager::syncBitFlags(Common::Serializer &s, bool *startP, bool *endP)
 	byte data = 0;
 
 	int bitCounter = 0;
-	for (bool *p = startP; p <= endP; ++p, ++bitCounter) {
-		if (bitCounter != 0 && (bitCounter % 8) == 0) {
-			s.syncAsByte(data);
+	for (bool *p = startP; p <= endP; ++p, bitCounter = (bitCounter + 1) % 8) {
+		if (p == endP || bitCounter == 0) {
+			if (p != endP || s.isSaving())
+				s.syncAsByte(data);
 			if (p == endP)
 				break;
 
@@ -286,7 +303,22 @@ void SavesManager::syncBitFlags(Common::Serializer &s, bool *startP, bool *endP)
 	}
 }
 
-/*------------------------------------------------------------------------*/
+/**
+ * Sets up the dynamic data for the game for a new game
+ */
+void SavesManager::reset() {
+	Common::String name(_vm->getGameID() == GType_Clouds ? "xeen.cur" : "dark.cur");
+	CCArchive cur(name, false);
+	
+	Common::SeekableReadStream *chr = cur.createReadStreamForMember("maze.chr");
+	Common::Serializer sChr(chr, nullptr);
+	_roster.synchronize(sChr);
+	delete chr;
 
+	Common::SeekableReadStream *pty = cur.createReadStreamForMember("maze.pty");
+	Common::Serializer sPty(pty, nullptr);
+	_party.synchronize(sPty);
+	delete pty;
+}
 
 } // End of namespace Xeen
diff --git a/engines/xeen/saves.h b/engines/xeen/saves.h
index ef12efd..3d8978e 100644
--- a/engines/xeen/saves.h
+++ b/engines/xeen/saves.h
@@ -55,8 +55,11 @@ enum Condition { CURSED = 0, HEART_BROKEN = 1, WEAK = 2, POISONED = 3,
 };
 
 #define ITEMS_COUNT 36
+#define TOTAL_CHARACTERS 30
 
-class Roster {
+class XeenEngine;
+
+class Party {
 public:
 	int _partyCount;
 	int _realPartyCount;
@@ -102,7 +105,7 @@ public:
 	int _bankGems;
 	int _totalTime;
 	bool _rested;
-	bool _gameFlags[256];
+	bool _gameFlags[512];
 	bool _autoNotes[128];
 	bool _quests[64];
 	int _questItems[85];
@@ -112,7 +115,7 @@ public:
 	XeenItem _blacksmithMisc2[ITEMS_COUNT];
 	bool _characterFlags[30][24];
 public:
-	Roster();
+	Party();
 
 	void synchronize(Common::Serializer &s);
 };
@@ -145,8 +148,8 @@ public:
 	int _dbDay;
 	int _tempAge;
 	int _skills[18];
-	bool _awards[64];
-	bool _spells[40];
+	bool _awards[512];
+	bool _spells[312];
 	int _lloydMap;
 	Common::Point _lloydPosition;
 	bool _hasSpells;
@@ -177,12 +180,25 @@ public:
 	void synchronize(Common::Serializer &s);
 };
 
+class Roster: public Common::Array<PlayerStruct> {
+public:
+	Roster() {}
+
+	void synchronize(Common::Serializer &s);
+};
+
 class SavesManager {
+private:
+	XeenEngine *_vm;
 public:
+	Party _party;
 	Roster _roster;
-	Common::Array<PlayerStruct> _conditions;
 public:
 	static void syncBitFlags(Common::Serializer &s, bool *startP, bool *endP);
+public:
+	SavesManager(XeenEngine *vm) : _vm(vm) {}
+
+	void reset();
 };
 
 } // End of namespace Xeen
diff --git a/engines/xeen/xeen.cpp b/engines/xeen/xeen.cpp
index 35b4188..96a4f5f 100644
--- a/engines/xeen/xeen.cpp
+++ b/engines/xeen/xeen.cpp
@@ -37,6 +37,7 @@ XeenEngine::XeenEngine(OSystem *syst, const XeenGameDescription *gameDesc)
 		: _gameDescription(gameDesc), Engine(syst), _randomSource("Xeen") {
 	_debugger = nullptr;
 	_events = nullptr;
+	_saves = nullptr;
 	_screen = nullptr;
 	_sound = nullptr;
 	_eventData = nullptr;
@@ -45,6 +46,7 @@ XeenEngine::XeenEngine(OSystem *syst, const XeenGameDescription *gameDesc)
 XeenEngine::~XeenEngine() {
 	delete _debugger;
 	delete _events;
+	delete _saves;
 	delete _screen;
 	delete _sound;
 	delete _eventData;
@@ -61,6 +63,7 @@ void XeenEngine::initialize() {
 	FileManager::init(this);
 	_debugger = new Debugger(this);
 	_events = new EventsManager(this);
+	_saves = new SavesManager(this);
 	_screen = new Screen(this);
 	_screen->setupWindows();
 	_sound = new SoundManager(this);
@@ -237,7 +240,8 @@ void XeenEngine::showMainMenu() {
 }
 
 void XeenEngine::playGame() {
-
+	_saves->reset();
+//	drawUI();
 }
 
 void XeenEngine::drawUI() {
diff --git a/engines/xeen/xeen.h b/engines/xeen/xeen.h
index 2049888..7d23fde 100644
--- a/engines/xeen/xeen.h
+++ b/engines/xeen/xeen.h
@@ -34,6 +34,7 @@
 #include "graphics/surface.h"
 #include "xeen/debugger.h"
 #include "xeen/events.h"
+#include "xeen/saves.h"
 #include "xeen/screen.h"
 #include "xeen/sound.h"
 
@@ -119,6 +120,7 @@ private:
 public:
 	Debugger *_debugger;
 	EventsManager *_events;
+	SavesManager *_saves;
 	Screen *_screen;
 	SoundManager *_sound;
 	Mode _mode;


Commit: bef5dbdc0a8640e3d51af5f1ef9ceb92ab930900
    https://github.com/scummvm/scummvm/commit/bef5dbdc0a8640e3d51af5f1ef9ceb92ab930900
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-01-02T11:29:15-10:00

Commit Message:
XEEN: Replaced conditions array with named field structure

Changed paths:
    engines/xeen/saves.cpp
    engines/xeen/saves.h



diff --git a/engines/xeen/saves.cpp b/engines/xeen/saves.cpp
index 771affc..b3f1b4c 100644
--- a/engines/xeen/saves.cpp
+++ b/engines/xeen/saves.cpp
@@ -171,6 +171,46 @@ void Party::synchronize(Common::Serializer &s) {
 
 /*------------------------------------------------------------------------*/
 
+Conditions::Conditions() {
+	_cursed = 0;
+	_heartBroken = 0;
+	_weak = 0;
+	_poisoned = 0;
+	_diseased = 0;
+	_insane = 0;
+	_inLove = 0;
+	_drunk = 0;
+	_asleep = 0;
+	_depressed = 0;
+	_confused = 0;
+	_paralyzed = 0;
+	_unconscious = 0;
+	_dead = 0;
+	_stoned = 0;
+	_eradicated = 0;
+}
+
+void Conditions::synchronize(Common::Serializer &s) {
+	s.syncAsByte(_cursed);
+	s.syncAsByte(_heartBroken);
+	s.syncAsByte(_weak);
+	s.syncAsByte(_poisoned);
+	s.syncAsByte(_diseased);
+	s.syncAsByte(_insane);
+	s.syncAsByte(_inLove);
+	s.syncAsByte(_drunk);
+	s.syncAsByte(_asleep);
+	s.syncAsByte(_depressed);
+	s.syncAsByte(_confused);
+	s.syncAsByte(_paralyzed);
+	s.syncAsByte(_unconscious);
+	s.syncAsByte(_dead);
+	s.syncAsByte(_stoned);
+	s.syncAsByte(_eradicated);
+}
+
+/*------------------------------------------------------------------------*/
+
 PlayerStruct::PlayerStruct() {
 	_sex = MALE;
 	_race = HUMAN;
@@ -187,7 +227,6 @@ PlayerStruct::PlayerStruct() {
 	_currentSpell = 0;
 	_quickOption = 0;
 	_lloydSide = 0;
-	Common::fill(&_conditions[0], &_conditions[16], 0);
 	_townUnknown = 0;
 	_unknown2 = 0;
 	_currentHp = 0;
@@ -253,8 +292,7 @@ void PlayerStruct::synchronize(Common::Serializer &s) {
 	_energyResistence.synchronize(s);
 	_magicResistence.synchronize(s);
 	
-	for (int i = 0; i < 16; ++i)
-		s.syncAsByte(_conditions[i]);
+	_conditions.synchronize(s);
 
 	s.syncAsUint16LE(_townUnknown);
 	s.syncAsByte(_unknown2);
diff --git a/engines/xeen/saves.h b/engines/xeen/saves.h
index 3d8978e..3075825 100644
--- a/engines/xeen/saves.h
+++ b/engines/xeen/saves.h
@@ -49,7 +49,7 @@ enum Skill { THIEVERY = 0, ARMS_MASTER = 1, ASTROLOGER = 2, BODYBUILDER = 3,
 	SPOT_DOORS = 16, DANGER_SENSE = 17
 };
 
-enum Condition { CURSED = 0, HEART_BROKEN = 1, WEAK = 2, POISONED = 3,
+enum ConditionType { CURSED = 0, HEART_BROKEN = 1, WEAK = 2, POISONED = 3,
 	DISEASED = 4, INSANE = 5, IN_LOVE = 6, DRUNK = 7, SLEEP = 8, 
 	DEPRESSED = 9, CONFUSED = 10, PARALYZED = 11
 };
@@ -129,6 +129,29 @@ public:
 	void synchronize(Common::Serializer &s);
 };
 
+class Conditions {
+	byte _cursed;
+	byte _heartBroken;
+	byte _weak;
+	byte _poisoned;
+	byte _diseased;
+	byte _insane;
+	byte _inLove;
+	byte _drunk;
+	byte _asleep;
+	byte _depressed;
+	byte _confused;
+	byte _paralyzed;
+	byte _unconscious;
+	byte _dead;
+	byte _stoned;
+	byte _eradicated;
+public:
+	Conditions();
+	
+	void synchronize(Common::Serializer &s);
+};
+
 class PlayerStruct {
 public:
 	Common::String _name;
@@ -166,7 +189,7 @@ public:
 	AttributePair _poisonResistence;
 	AttributePair _energyResistence;
 	AttributePair _magicResistence;
-	int _conditions[16];
+	Conditions _conditions;
 	int _townUnknown;
 	int _unknown2;
 	int _currentHp;


Commit: 27e020cbf98d88373111bff0f1d6ed0e846b2311
    https://github.com/scummvm/scummvm/commit/27e020cbf98d88373111bff0f1d6ed0e846b2311
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-01-02T12:14:57-10:00

Commit Message:
XEEN: Split char/party logic into it's own file

Changed paths:
  A engines/xeen/party.cpp
  A engines/xeen/party.h
    engines/xeen/module.mk
    engines/xeen/saves.h
    engines/xeen/xeen.cpp
    engines/xeen/xeen.h



diff --git a/engines/xeen/module.mk b/engines/xeen/module.mk
index 2f5a092..752608a 100644
--- a/engines/xeen/module.mk
+++ b/engines/xeen/module.mk
@@ -12,6 +12,7 @@ MODULE_OBJS := \
 	files.o \
 	font.o \
 	items.o \
+	party.o \
 	resdata.o \
 	resources.o \
 	saves.o \
diff --git a/engines/xeen/party.cpp b/engines/xeen/party.cpp
new file mode 100644
index 0000000..69a64bb
--- /dev/null
+++ b/engines/xeen/party.cpp
@@ -0,0 +1,317 @@
+/* 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 "common/algorithm.h"
+#include "xeen/party.h"
+#include "xeen/files.h"
+#include "xeen/xeen.h"
+
+namespace Xeen {
+
+AttributePair::AttributePair() {
+	_temporary = _permanent = 0;
+}
+
+void AttributePair::synchronize(Common::Serializer &s) {
+	s.syncAsByte(_permanent);
+	s.syncAsByte(_temporary);
+}
+
+/*------------------------------------------------------------------------*/
+
+Party::Party() {
+	_partyCount = 0;
+	_realPartyCount = 0;
+	Common::fill(&_partyMembers[0], &_partyMembers[8], 0);
+	_mazeDirection = DIR_NORTH;
+	_mazeId = _priorMazeId = 0;
+	_levitateActive = false;
+	_automapOn = false;
+	_wizardEyeActive = false;
+	_clairvoyanceActive = false;
+	_walkOnWaterActive = false;
+	_blessedActive = false;
+	_powerShieldActive = false;
+	_holyBonusActive = false;
+	_heroismActive = false;
+	_difficulty = ADVENTURER;
+	_cloudsEnd = false;
+	_darkSideEnd = false;
+	_worldEnd = false;
+	hour_maybe = 0;
+	_day = 0;
+	_year = 0;
+	_minutes = 0;
+	_food = 0;
+	_lightCount = 0;
+	_torchCount = 0;
+	_fireResistence = 0;
+	_electricityResistence = 0;
+	_coldResistence = 0;
+	_poisonResistence = 0;
+	_deathCount = 0;
+	_winCount = 0;
+	_lossCount = 0;
+	_gold = 0;
+	_gems = 0;
+	_bankGold = 0;
+	_bankGems = 0;
+	_totalTime = 0;
+	_rested = false;
+
+	Common::fill(&_gameFlags[0], &_gameFlags[512], false);
+	Common::fill(&_autoNotes[0], &_autoNotes[128], false);
+	Common::fill(&_quests[0], &_quests[64], false);
+	Common::fill(&_questItems[0], &_questItems[85], 0);
+
+	for (int i = 0; i < TOTAL_CHARACTERS; ++i)
+		Common::fill(&_characterFlags[i][0], &_characterFlags[i][24], false);
+}
+
+void Party::synchronize(Common::Serializer &s) {
+	byte dummy[30];
+	Common::fill(&dummy[0], &dummy[30], 0);
+
+	s.syncAsByte(_partyCount);
+	s.syncAsByte(_realPartyCount);
+	for (int i = 0; i < 8; ++i)
+		s.syncAsByte(_partyMembers[i]);
+	s.syncAsByte(_mazeDirection);
+	s.syncAsByte(_mazePosition.x);
+	s.syncAsByte(_mazePosition.y);
+	s.syncAsByte(_mazeId);
+	
+	// Game configuration flags not used in this implementation
+	s.syncBytes(dummy, 3);
+
+	s.syncAsByte(_priorMazeId);
+	s.syncAsByte(_levitateActive);
+	s.syncAsByte(_automapOn);
+	s.syncAsByte(_wizardEyeActive);
+	s.syncAsByte(_clairvoyanceActive);
+	s.syncAsByte(_walkOnWaterActive);
+	s.syncAsByte(_blessedActive);
+	s.syncAsByte(_powerShieldActive);
+	s.syncAsByte(_holyBonusActive);
+	s.syncAsByte(_heroismActive);
+	s.syncAsByte(_difficulty);
+
+	for (int i = 0; i < ITEMS_COUNT; ++i)
+		_blacksmithWeapons[i].synchronize(s);
+	for (int i = 0; i < ITEMS_COUNT; ++i)
+		_blacksmithArmor[i].synchronize(s);
+	for (int i = 0; i < ITEMS_COUNT; ++i)
+		_blacksmithAccessories[i].synchronize(s);
+	for (int i = 0; i < ITEMS_COUNT; ++i)
+		_blacksmithMisc[i].synchronize(s);
+
+	s.syncAsUint16LE(_cloudsEnd);
+	s.syncAsUint16LE(_darkSideEnd);
+	s.syncAsUint16LE(_worldEnd);
+	s.syncAsUint16LE(hour_maybe);
+	s.syncAsUint16LE(_day);
+	s.syncAsUint16LE(_year);
+	s.syncAsUint16LE(_minutes);
+	s.syncAsUint16LE(_food);
+	s.syncAsUint16LE(_lightCount);
+	s.syncAsUint16LE(_torchCount);
+	s.syncAsUint16LE(_fireResistence);
+	s.syncAsUint16LE(_electricityResistence);
+	s.syncAsUint16LE(_coldResistence);
+	s.syncAsUint16LE(_poisonResistence);
+	s.syncAsUint16LE(_deathCount);
+	s.syncAsUint16LE(_winCount);
+	s.syncAsUint16LE(_lossCount);
+	s.syncAsUint32LE(_gold);
+	s.syncAsUint32LE(_gems);
+	s.syncAsUint32LE(_bankGold);
+	s.syncAsUint32LE(_bankGems);
+	s.syncAsUint32LE(_totalTime);
+	s.syncAsByte(_rested);
+	SavesManager::syncBitFlags(s, &_gameFlags[0], &_gameFlags[512]);
+	SavesManager::syncBitFlags(s, &_autoNotes[0], &_autoNotes[128]);
+	SavesManager::syncBitFlags(s, &_quests[0], &_quests[64]);
+	
+	for (int i = 0; i < 85; ++i)
+		s.syncAsByte(_questItems[i]);
+
+	for (int i = 0; i < ITEMS_COUNT; ++i)
+		_blacksmithWeapons2[i].synchronize(s);
+	for (int i = 0; i < ITEMS_COUNT; ++i)
+		_blacksmithArmor2[i].synchronize(s);
+	for (int i = 0; i < ITEMS_COUNT; ++i)
+		_blacksmithAccessories2[i].synchronize(s);
+	for (int i = 0; i < ITEMS_COUNT; ++i)
+		_blacksmithMisc2[i].synchronize(s);
+	
+	for (int i = 0; i < TOTAL_CHARACTERS; ++i)
+		SavesManager::syncBitFlags(s, &_characterFlags[i][0], &_characterFlags[i][24]);
+	s.syncBytes(&dummy[0], 30);
+}
+
+/*------------------------------------------------------------------------*/
+
+Conditions::Conditions() {
+	_cursed = 0;
+	_heartBroken = 0;
+	_weak = 0;
+	_poisoned = 0;
+	_diseased = 0;
+	_insane = 0;
+	_inLove = 0;
+	_drunk = 0;
+	_asleep = 0;
+	_depressed = 0;
+	_confused = 0;
+	_paralyzed = 0;
+	_unconscious = 0;
+	_dead = 0;
+	_stoned = 0;
+	_eradicated = 0;
+}
+
+void Conditions::synchronize(Common::Serializer &s) {
+	s.syncAsByte(_cursed);
+	s.syncAsByte(_heartBroken);
+	s.syncAsByte(_weak);
+	s.syncAsByte(_poisoned);
+	s.syncAsByte(_diseased);
+	s.syncAsByte(_insane);
+	s.syncAsByte(_inLove);
+	s.syncAsByte(_drunk);
+	s.syncAsByte(_asleep);
+	s.syncAsByte(_depressed);
+	s.syncAsByte(_confused);
+	s.syncAsByte(_paralyzed);
+	s.syncAsByte(_unconscious);
+	s.syncAsByte(_dead);
+	s.syncAsByte(_stoned);
+	s.syncAsByte(_eradicated);
+}
+
+/*------------------------------------------------------------------------*/
+
+PlayerStruct::PlayerStruct() {
+	_sex = MALE;
+	_race = HUMAN;
+	_xeenSide = 0;
+	_class = KNIGHT;
+	_ACTemp = 0;
+	_dbDay = 0;
+	_tempAge = 0;
+	Common::fill(&_skills[0], &_skills[18], 0);
+	Common::fill(&_awards[0], &_awards[512], false);
+	Common::fill(&_spells[9], &_spells[312], false);
+	_lloydMap = 0;
+	_hasSpells = false;
+	_currentSpell = 0;
+	_quickOption = 0;
+	_lloydSide = 0;
+	_townUnknown = 0;
+	_unknown2 = 0;
+	_currentHp = 0;
+	_currentSp = 0;
+	_ybDay = 0;
+	_experience = 0;
+	_currentAdventuringSpell = 0;
+	_currentCombatSpell = 0;
+}
+
+void PlayerStruct::synchronize(Common::Serializer &s) {
+	char name[16];
+	Common::fill(&name[0], &name[16], '\0');
+	strncpy(name, _name.c_str(), 16);
+	s.syncBytes((byte *)name, 16);
+
+	if (s.isLoading())
+		_name = Common::String(name);
+
+	s.syncAsByte(_sex);
+	s.syncAsByte(_race);
+	s.syncAsByte(_xeenSide);
+	s.syncAsByte(_class);
+
+	_might.synchronize(s);
+	_intellect.synchronize(s);
+	_personality.synchronize(s);
+	_endurance.synchronize(s);
+	_speed.synchronize(s);
+	_accuracy.synchronize(s);
+	_luck.synchronize(s);
+	s.syncAsByte(_ACTemp);
+	_level.synchronize(s);
+	s.syncAsByte(_dbDay);
+	s.syncAsByte(_tempAge);
+	
+	for (int i = 0; i < 18; ++i)
+		s.syncAsByte(_skills[i]);
+	SavesManager::syncBitFlags(s, &_awards[0], &_awards[512]);
+	SavesManager::syncBitFlags(s, &_spells[0], &_spells[312]);
+	
+	s.syncAsByte(_lloydMap);
+	s.syncAsByte(_lloydPosition.x);
+	s.syncAsByte(_lloydPosition.y);
+	s.syncAsByte(_hasSpells);
+	s.syncAsByte(_currentSpell);
+	s.syncAsByte(_quickOption);
+
+	for (int i = 0; i < 9; ++i)
+		_weapons[i].synchronize(s);
+	for (int i = 0; i < 9; ++i)
+		_armor[i].synchronize(s);
+	for (int i = 0; i < 9; ++i)
+		_accessories[i].synchronize(s);
+	for (int i = 0; i < 9; ++i)
+		_misc[i].synchronize(s);
+
+	s.syncAsByte(_lloydSide);
+	_fireResistence.synchronize(s);
+	_coldResistence.synchronize(s);
+	_electricityResistence.synchronize(s);
+	_poisonResistence.synchronize(s);
+	_energyResistence.synchronize(s);
+	_magicResistence.synchronize(s);
+	
+	_conditions.synchronize(s);
+
+	s.syncAsUint16LE(_townUnknown);
+	s.syncAsByte(_unknown2);
+	s.syncAsUint16LE(_currentHp);
+	s.syncAsUint16LE(_currentSp);
+	s.syncAsUint16LE(_ybDay);
+	s.syncAsUint32LE(_experience);
+	s.syncAsByte(_currentAdventuringSpell);
+	s.syncAsByte(_currentCombatSpell);
+}
+
+/*------------------------------------------------------------------------*/
+
+void Roster::synchronize(Common::Serializer &s) {
+	if (s.isLoading())
+		resize(30);
+
+	for (uint i = 0; i < 30; ++i)
+		(*this)[i].synchronize(s);
+}
+
+} // End of namespace Xeen
diff --git a/engines/xeen/party.h b/engines/xeen/party.h
new file mode 100644
index 0000000..6a6ec5f
--- /dev/null
+++ b/engines/xeen/party.h
@@ -0,0 +1,217 @@
+/* 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_PARTY_H
+#define XEEN_PARTY_H
+
+#include "common/scummsys.h"
+#include "common/array.h"
+#include "common/rect.h"
+#include "common/serializer.h"
+#include "xeen/items.h"
+
+namespace Xeen {
+
+enum Direction { DIR_NORTH = 0, DIR_EAST = 1, DIR_SOUTH = 2, DIR_WEST = 3 };
+
+enum Difficulty { ADVENTURER = 0, WARRIOR = 1 };
+
+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 Skill { THIEVERY = 0, ARMS_MASTER = 1, ASTROLOGER = 2, BODYBUILDER = 3,
+	CARTOGRAPHER = 4, CRUSADER = 5, DIRECTION_SENSE = 6, LINGUIST = 7, 
+	MERCHANT = 8, MOUNTAINEER = 9, NAVIGATOR = 10, PATHFINDER = 11,
+	PRAYER_MASTER = 12, PRESTIDIGITATION = 13, SWIMMING = 14, TRACKING = 15,
+	SPOT_DOORS = 16, DANGER_SENSE = 17
+};
+
+enum ConditionType { CURSED = 0, HEART_BROKEN = 1, WEAK = 2, POISONED = 3,
+	DISEASED = 4, INSANE = 5, IN_LOVE = 6, DRUNK = 7, SLEEP = 8, 
+	DEPRESSED = 9, CONFUSED = 10, PARALYZED = 11
+};
+
+#define ITEMS_COUNT 36
+#define TOTAL_CHARACTERS 30
+#define MAX_ACTIVE_PARTY 6
+
+class XeenEngine;
+
+class Party {
+public:
+	int _partyCount;
+	int _realPartyCount;
+	int _partyMembers[8];
+	Direction _mazeDirection;
+	Common::Point _mazePosition;
+	int _mazeId;
+	int _priorMazeId;
+	bool _levitateActive;
+	bool _automapOn;
+	bool _wizardEyeActive;
+	bool _clairvoyanceActive;
+	bool _walkOnWaterActive;
+	bool _blessedActive;
+	bool _powerShieldActive;
+	bool _holyBonusActive;
+	bool _heroismActive;
+	Difficulty _difficulty;
+	XeenItem _blacksmithWeapons[ITEMS_COUNT];
+	XeenItem _blacksmithArmor[ITEMS_COUNT];
+	XeenItem _blacksmithAccessories[ITEMS_COUNT];
+	XeenItem _blacksmithMisc[ITEMS_COUNT];
+	bool _cloudsEnd;
+	bool _darkSideEnd;
+	bool _worldEnd;
+	int hour_maybe;
+	int _day;
+	int _year;
+	int _minutes;
+	int _food;
+	int _lightCount;
+	int _torchCount;
+	int _fireResistence;
+	int _electricityResistence;
+	int _coldResistence;
+	int _poisonResistence;
+	int _deathCount;
+	int _winCount;
+	int _lossCount;
+	int _gold;
+	int _gems;
+	int _bankGold;
+	int _bankGems;
+	int _totalTime;
+	bool _rested;
+	bool _gameFlags[512];
+	bool _autoNotes[128];
+	bool _quests[64];
+	int _questItems[85];
+	XeenItem _blacksmithWeapons2[ITEMS_COUNT];
+	XeenItem _blacksmithArmor2[ITEMS_COUNT];
+	XeenItem _blacksmithAccessories2[ITEMS_COUNT];
+	XeenItem _blacksmithMisc2[ITEMS_COUNT];
+	bool _characterFlags[30][24];
+public:
+	Party();
+
+	void synchronize(Common::Serializer &s);
+};
+
+class AttributePair {
+public:	
+	int _permanent;
+	int _temporary;
+public:
+	AttributePair();
+	void synchronize(Common::Serializer &s);
+};
+
+class Conditions {
+	byte _cursed;
+	byte _heartBroken;
+	byte _weak;
+	byte _poisoned;
+	byte _diseased;
+	byte _insane;
+	byte _inLove;
+	byte _drunk;
+	byte _asleep;
+	byte _depressed;
+	byte _confused;
+	byte _paralyzed;
+	byte _unconscious;
+	byte _dead;
+	byte _stoned;
+	byte _eradicated;
+public:
+	Conditions();
+	
+	void synchronize(Common::Serializer &s);
+};
+
+class PlayerStruct {
+public:
+	Common::String _name;
+	Sex _sex;
+	Race _race;
+	int _xeenSide;
+	CharacterClass _class;
+	AttributePair _might;
+	AttributePair _intellect;
+	AttributePair _personality;
+	AttributePair _endurance;
+	AttributePair _speed;
+	AttributePair _accuracy;
+	AttributePair _luck;
+	int _ACTemp;
+	AttributePair _level;
+	int _dbDay;
+	int _tempAge;
+	int _skills[18];
+	bool _awards[512];
+	bool _spells[312];
+	int _lloydMap;
+	Common::Point _lloydPosition;
+	bool _hasSpells;
+	int _currentSpell;
+	int _quickOption;
+	XeenItem _weapons[9];
+	XeenItem _armor[9];
+	XeenItem _accessories[9];
+	XeenItem _misc[9];
+	int _lloydSide;
+	AttributePair _fireResistence;
+	AttributePair _coldResistence;
+	AttributePair _electricityResistence;
+	AttributePair _poisonResistence;
+	AttributePair _energyResistence;
+	AttributePair _magicResistence;
+	Conditions _conditions;
+	int _townUnknown;
+	int _unknown2;
+	int _currentHp;
+	int _currentSp;
+	int _ybDay;
+	uint32 _experience;
+	int _currentAdventuringSpell;
+	int _currentCombatSpell;
+public:
+	PlayerStruct();
+	void synchronize(Common::Serializer &s);
+};
+
+class Roster: public Common::Array<PlayerStruct> {
+public:
+	Roster() {}
+
+	void synchronize(Common::Serializer &s);
+};
+
+} // End of namespace Xeen
+
+#endif	/* XEEN_PARTY_H */
diff --git a/engines/xeen/saves.h b/engines/xeen/saves.h
index 3075825..8b29f15 100644
--- a/engines/xeen/saves.h
+++ b/engines/xeen/saves.h
@@ -24,192 +24,11 @@
 #define XEEN_SAVES_H
 
 #include "common/scummsys.h"
-#include "common/rect.h"
 #include "common/savefile.h"
-#include "xeen/items.h"
+#include "xeen/party.h"
 
 namespace Xeen {
 
-enum Direction { DIR_NORTH = 0, DIR_EAST = 1, DIR_SOUTH = 2, DIR_WEST = 3 };
-
-enum Difficulty { ADVENTURER = 0, WARRIOR = 1 };
-
-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 Skill { THIEVERY = 0, ARMS_MASTER = 1, ASTROLOGER = 2, BODYBUILDER = 3,
-	CARTOGRAPHER = 4, CRUSADER = 5, DIRECTION_SENSE = 6, LINGUIST = 7, 
-	MERCHANT = 8, MOUNTAINEER = 9, NAVIGATOR = 10, PATHFINDER = 11,
-	PRAYER_MASTER = 12, PRESTIDIGITATION = 13, SWIMMING = 14, TRACKING = 15,
-	SPOT_DOORS = 16, DANGER_SENSE = 17
-};
-
-enum ConditionType { CURSED = 0, HEART_BROKEN = 1, WEAK = 2, POISONED = 3,
-	DISEASED = 4, INSANE = 5, IN_LOVE = 6, DRUNK = 7, SLEEP = 8, 
-	DEPRESSED = 9, CONFUSED = 10, PARALYZED = 11
-};
-
-#define ITEMS_COUNT 36
-#define TOTAL_CHARACTERS 30
-
-class XeenEngine;
-
-class Party {
-public:
-	int _partyCount;
-	int _realPartyCount;
-	int _partyMembers[8];
-	Direction _mazeDirection;
-	Common::Point _mazePosition;
-	int _mazeId;
-	int _priorMazeId;
-	bool _levitateActive;
-	bool _automapOn;
-	bool _wizardEyeActive;
-	bool _clairvoyanceActive;
-	bool _walkOnWaterActive;
-	bool _blessedActive;
-	bool _powerShieldActive;
-	bool _holyBonusActive;
-	bool _heroismActive;
-	Difficulty _difficulty;
-	XeenItem _blacksmithWeapons[ITEMS_COUNT];
-	XeenItem _blacksmithArmor[ITEMS_COUNT];
-	XeenItem _blacksmithAccessories[ITEMS_COUNT];
-	XeenItem _blacksmithMisc[ITEMS_COUNT];
-	bool _cloudsEnd;
-	bool _darkSideEnd;
-	bool _worldEnd;
-	int hour_maybe;
-	int _day;
-	int _year;
-	int _minutes;
-	int _food;
-	int _lightCount;
-	int _torchCount;
-	int _fireResistence;
-	int _electricityResistence;
-	int _coldResistence;
-	int _poisonResistence;
-	int _deathCount;
-	int _winCount;
-	int _lossCount;
-	int _gold;
-	int _gems;
-	int _bankGold;
-	int _bankGems;
-	int _totalTime;
-	bool _rested;
-	bool _gameFlags[512];
-	bool _autoNotes[128];
-	bool _quests[64];
-	int _questItems[85];
-	XeenItem _blacksmithWeapons2[ITEMS_COUNT];
-	XeenItem _blacksmithArmor2[ITEMS_COUNT];
-	XeenItem _blacksmithAccessories2[ITEMS_COUNT];
-	XeenItem _blacksmithMisc2[ITEMS_COUNT];
-	bool _characterFlags[30][24];
-public:
-	Party();
-
-	void synchronize(Common::Serializer &s);
-};
-
-class AttributePair {
-public:	
-	int _permanent;
-	int _temporary;
-public:
-	AttributePair();
-	void synchronize(Common::Serializer &s);
-};
-
-class Conditions {
-	byte _cursed;
-	byte _heartBroken;
-	byte _weak;
-	byte _poisoned;
-	byte _diseased;
-	byte _insane;
-	byte _inLove;
-	byte _drunk;
-	byte _asleep;
-	byte _depressed;
-	byte _confused;
-	byte _paralyzed;
-	byte _unconscious;
-	byte _dead;
-	byte _stoned;
-	byte _eradicated;
-public:
-	Conditions();
-	
-	void synchronize(Common::Serializer &s);
-};
-
-class PlayerStruct {
-public:
-	Common::String _name;
-	Sex _sex;
-	Race _race;
-	int _xeenSide;
-	CharacterClass _class;
-	AttributePair _might;
-	AttributePair _intellect;
-	AttributePair _personality;
-	AttributePair _endurance;
-	AttributePair _speed;
-	AttributePair _accuracy;
-	AttributePair _luck;
-	int _ACTemp;
-	AttributePair _level;
-	int _dbDay;
-	int _tempAge;
-	int _skills[18];
-	bool _awards[512];
-	bool _spells[312];
-	int _lloydMap;
-	Common::Point _lloydPosition;
-	bool _hasSpells;
-	int _currentSpell;
-	int _quickOption;
-	XeenItem _weapons[9];
-	XeenItem _armor[9];
-	XeenItem _accessories[9];
-	XeenItem _misc[9];
-	int _lloydSide;
-	AttributePair _fireResistence;
-	AttributePair _coldResistence;
-	AttributePair _electricityResistence;
-	AttributePair _poisonResistence;
-	AttributePair _energyResistence;
-	AttributePair _magicResistence;
-	Conditions _conditions;
-	int _townUnknown;
-	int _unknown2;
-	int _currentHp;
-	int _currentSp;
-	int _ybDay;
-	uint32 _experience;
-	int _currentAdventuringSpell;
-	int _currentCombatSpell;
-public:
-	PlayerStruct();
-	void synchronize(Common::Serializer &s);
-};
-
-class Roster: public Common::Array<PlayerStruct> {
-public:
-	Roster() {}
-
-	void synchronize(Common::Serializer &s);
-};
-
 class SavesManager {
 private:
 	XeenEngine *_vm;
diff --git a/engines/xeen/xeen.cpp b/engines/xeen/xeen.cpp
index 96a4f5f..45d9c22 100644
--- a/engines/xeen/xeen.cpp
+++ b/engines/xeen/xeen.cpp
@@ -41,6 +41,7 @@ XeenEngine::XeenEngine(OSystem *syst, const XeenGameDescription *gameDesc)
 	_screen = nullptr;
 	_sound = nullptr;
 	_eventData = nullptr;
+	Common::fill(&_activeRoster[0], &_activeRoster[MAX_ACTIVE_PARTY], nullptr);
 }
 
 XeenEngine::~XeenEngine() {
@@ -241,12 +242,21 @@ void XeenEngine::showMainMenu() {
 
 void XeenEngine::playGame() {
 	_saves->reset();
-//	drawUI();
+	drawUI();
 }
 
+/*
+ * Lots of stuff in this method.
+ * TODO: Consider renaming method when better understood
+ */
 void XeenEngine::drawUI() {
 	SpriteResource sprites1("global.icn"), borderSprites("border.icn");
 
+	// Get mappings to the active characters in the party
+	Common::fill(&_activeRoster[0], &_activeRoster[MAX_ACTIVE_PARTY], nullptr);
+	for (int i = 0; i < _saves->_party._partyCount; ++i) {
+		_activeRoster[i] = &_saves->_roster[_saves->_party._partyMembers[i]];
+	}
 }
 
 } // End of namespace Xeen
diff --git a/engines/xeen/xeen.h b/engines/xeen/xeen.h
index 7d23fde..159ce74 100644
--- a/engines/xeen/xeen.h
+++ b/engines/xeen/xeen.h
@@ -34,6 +34,7 @@
 #include "graphics/surface.h"
 #include "xeen/debugger.h"
 #include "xeen/events.h"
+#include "xeen/party.h"
 #include "xeen/saves.h"
 #include "xeen/screen.h"
 #include "xeen/sound.h"
@@ -126,6 +127,7 @@ public:
 	Mode _mode;
 	GameEvent _gameEvent;
 	Common::SeekableReadStream *_eventData;
+	PlayerStruct *_activeRoster[MAX_ACTIVE_PARTY];
 public:
 	XeenEngine(OSystem *syst, const XeenGameDescription *gameDesc);
 	virtual ~XeenEngine();


Commit: 9a8cb48a9edcc67b17c192ff13b3d9d1e40f73a9
    https://github.com/scummvm/scummvm/commit/9a8cb48a9edcc67b17c192ff13b3d9d1e40f73a9
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-01-02T12:27:59-10:00

Commit Message:
XEEN: Cleanup of party code split, moved roster and party to engine

Changed paths:
    engines/xeen/party.cpp
    engines/xeen/saves.cpp
    engines/xeen/saves.h
    engines/xeen/xeen.cpp
    engines/xeen/xeen.h



diff --git a/engines/xeen/party.cpp b/engines/xeen/party.cpp
index 69a64bb..c5f80eb 100644
--- a/engines/xeen/party.cpp
+++ b/engines/xeen/party.cpp
@@ -25,6 +25,7 @@
 #include "xeen/party.h"
 #include "xeen/files.h"
 #include "xeen/xeen.h"
+#include "xeen/saves.h"
 
 namespace Xeen {
 
diff --git a/engines/xeen/saves.cpp b/engines/xeen/saves.cpp
index b3f1b4c..7482a12 100644
--- a/engines/xeen/saves.cpp
+++ b/engines/xeen/saves.cpp
@@ -28,294 +28,10 @@
 
 namespace Xeen {
 
-AttributePair::AttributePair() {
-	_temporary = _permanent = 0;
+SavesManager::SavesManager(XeenEngine *vm, Party &party, Roster &roster) : 
+		_vm(vm), _party(party), _roster(roster) {
 }
 
-void AttributePair::synchronize(Common::Serializer &s) {
-	s.syncAsByte(_permanent);
-	s.syncAsByte(_temporary);
-}
-
-/*------------------------------------------------------------------------*/
-
-Party::Party() {
-	_partyCount = 0;
-	_realPartyCount = 0;
-	Common::fill(&_partyMembers[0], &_partyMembers[8], 0);
-	_mazeDirection = DIR_NORTH;
-	_mazeId = _priorMazeId = 0;
-	_levitateActive = false;
-	_automapOn = false;
-	_wizardEyeActive = false;
-	_clairvoyanceActive = false;
-	_walkOnWaterActive = false;
-	_blessedActive = false;
-	_powerShieldActive = false;
-	_holyBonusActive = false;
-	_heroismActive = false;
-	_difficulty = ADVENTURER;
-	_cloudsEnd = false;
-	_darkSideEnd = false;
-	_worldEnd = false;
-	hour_maybe = 0;
-	_day = 0;
-	_year = 0;
-	_minutes = 0;
-	_food = 0;
-	_lightCount = 0;
-	_torchCount = 0;
-	_fireResistence = 0;
-	_electricityResistence = 0;
-	_coldResistence = 0;
-	_poisonResistence = 0;
-	_deathCount = 0;
-	_winCount = 0;
-	_lossCount = 0;
-	_gold = 0;
-	_gems = 0;
-	_bankGold = 0;
-	_bankGems = 0;
-	_totalTime = 0;
-	_rested = false;
-
-	Common::fill(&_gameFlags[0], &_gameFlags[512], false);
-	Common::fill(&_autoNotes[0], &_autoNotes[128], false);
-	Common::fill(&_quests[0], &_quests[64], false);
-	Common::fill(&_questItems[0], &_questItems[85], 0);
-
-	for (int i = 0; i < TOTAL_CHARACTERS; ++i)
-		Common::fill(&_characterFlags[i][0], &_characterFlags[i][24], false);
-}
-
-void Party::synchronize(Common::Serializer &s) {
-	byte dummy[30];
-	Common::fill(&dummy[0], &dummy[30], 0);
-
-	s.syncAsByte(_partyCount);
-	s.syncAsByte(_realPartyCount);
-	for (int i = 0; i < 8; ++i)
-		s.syncAsByte(_partyMembers[i]);
-	s.syncAsByte(_mazeDirection);
-	s.syncAsByte(_mazePosition.x);
-	s.syncAsByte(_mazePosition.y);
-	s.syncAsByte(_mazeId);
-	
-	// Game configuration flags not used in this implementation
-	s.syncBytes(dummy, 3);
-
-	s.syncAsByte(_priorMazeId);
-	s.syncAsByte(_levitateActive);
-	s.syncAsByte(_automapOn);
-	s.syncAsByte(_wizardEyeActive);
-	s.syncAsByte(_clairvoyanceActive);
-	s.syncAsByte(_walkOnWaterActive);
-	s.syncAsByte(_blessedActive);
-	s.syncAsByte(_powerShieldActive);
-	s.syncAsByte(_holyBonusActive);
-	s.syncAsByte(_heroismActive);
-	s.syncAsByte(_difficulty);
-
-	for (int i = 0; i < ITEMS_COUNT; ++i)
-		_blacksmithWeapons[i].synchronize(s);
-	for (int i = 0; i < ITEMS_COUNT; ++i)
-		_blacksmithArmor[i].synchronize(s);
-	for (int i = 0; i < ITEMS_COUNT; ++i)
-		_blacksmithAccessories[i].synchronize(s);
-	for (int i = 0; i < ITEMS_COUNT; ++i)
-		_blacksmithMisc[i].synchronize(s);
-
-	s.syncAsUint16LE(_cloudsEnd);
-	s.syncAsUint16LE(_darkSideEnd);
-	s.syncAsUint16LE(_worldEnd);
-	s.syncAsUint16LE(hour_maybe);
-	s.syncAsUint16LE(_day);
-	s.syncAsUint16LE(_year);
-	s.syncAsUint16LE(_minutes);
-	s.syncAsUint16LE(_food);
-	s.syncAsUint16LE(_lightCount);
-	s.syncAsUint16LE(_torchCount);
-	s.syncAsUint16LE(_fireResistence);
-	s.syncAsUint16LE(_electricityResistence);
-	s.syncAsUint16LE(_coldResistence);
-	s.syncAsUint16LE(_poisonResistence);
-	s.syncAsUint16LE(_deathCount);
-	s.syncAsUint16LE(_winCount);
-	s.syncAsUint16LE(_lossCount);
-	s.syncAsUint32LE(_gold);
-	s.syncAsUint32LE(_gems);
-	s.syncAsUint32LE(_bankGold);
-	s.syncAsUint32LE(_bankGems);
-	s.syncAsUint32LE(_totalTime);
-	s.syncAsByte(_rested);
-	SavesManager::syncBitFlags(s, &_gameFlags[0], &_gameFlags[512]);
-	SavesManager::syncBitFlags(s, &_autoNotes[0], &_autoNotes[128]);
-	SavesManager::syncBitFlags(s, &_quests[0], &_quests[64]);
-	
-	for (int i = 0; i < 85; ++i)
-		s.syncAsByte(_questItems[i]);
-
-	for (int i = 0; i < ITEMS_COUNT; ++i)
-		_blacksmithWeapons2[i].synchronize(s);
-	for (int i = 0; i < ITEMS_COUNT; ++i)
-		_blacksmithArmor2[i].synchronize(s);
-	for (int i = 0; i < ITEMS_COUNT; ++i)
-		_blacksmithAccessories2[i].synchronize(s);
-	for (int i = 0; i < ITEMS_COUNT; ++i)
-		_blacksmithMisc2[i].synchronize(s);
-	
-	for (int i = 0; i < TOTAL_CHARACTERS; ++i)
-		SavesManager::syncBitFlags(s, &_characterFlags[i][0], &_characterFlags[i][24]);
-	s.syncBytes(&dummy[0], 30);
-}
-
-/*------------------------------------------------------------------------*/
-
-Conditions::Conditions() {
-	_cursed = 0;
-	_heartBroken = 0;
-	_weak = 0;
-	_poisoned = 0;
-	_diseased = 0;
-	_insane = 0;
-	_inLove = 0;
-	_drunk = 0;
-	_asleep = 0;
-	_depressed = 0;
-	_confused = 0;
-	_paralyzed = 0;
-	_unconscious = 0;
-	_dead = 0;
-	_stoned = 0;
-	_eradicated = 0;
-}
-
-void Conditions::synchronize(Common::Serializer &s) {
-	s.syncAsByte(_cursed);
-	s.syncAsByte(_heartBroken);
-	s.syncAsByte(_weak);
-	s.syncAsByte(_poisoned);
-	s.syncAsByte(_diseased);
-	s.syncAsByte(_insane);
-	s.syncAsByte(_inLove);
-	s.syncAsByte(_drunk);
-	s.syncAsByte(_asleep);
-	s.syncAsByte(_depressed);
-	s.syncAsByte(_confused);
-	s.syncAsByte(_paralyzed);
-	s.syncAsByte(_unconscious);
-	s.syncAsByte(_dead);
-	s.syncAsByte(_stoned);
-	s.syncAsByte(_eradicated);
-}
-
-/*------------------------------------------------------------------------*/
-
-PlayerStruct::PlayerStruct() {
-	_sex = MALE;
-	_race = HUMAN;
-	_xeenSide = 0;
-	_class = KNIGHT;
-	_ACTemp = 0;
-	_dbDay = 0;
-	_tempAge = 0;
-	Common::fill(&_skills[0], &_skills[18], 0);
-	Common::fill(&_awards[0], &_awards[512], false);
-	Common::fill(&_spells[9], &_spells[312], false);
-	_lloydMap = 0;
-	_hasSpells = false;
-	_currentSpell = 0;
-	_quickOption = 0;
-	_lloydSide = 0;
-	_townUnknown = 0;
-	_unknown2 = 0;
-	_currentHp = 0;
-	_currentSp = 0;
-	_ybDay = 0;
-	_experience = 0;
-	_currentAdventuringSpell = 0;
-	_currentCombatSpell = 0;
-}
-
-void PlayerStruct::synchronize(Common::Serializer &s) {
-	char name[16];
-	Common::fill(&name[0], &name[16], '\0');
-	strncpy(name, _name.c_str(), 16);
-	s.syncBytes((byte *)name, 16);
-
-	if (s.isLoading())
-		_name = Common::String(name);
-
-	s.syncAsByte(_sex);
-	s.syncAsByte(_race);
-	s.syncAsByte(_xeenSide);
-	s.syncAsByte(_class);
-
-	_might.synchronize(s);
-	_intellect.synchronize(s);
-	_personality.synchronize(s);
-	_endurance.synchronize(s);
-	_speed.synchronize(s);
-	_accuracy.synchronize(s);
-	_luck.synchronize(s);
-	s.syncAsByte(_ACTemp);
-	_level.synchronize(s);
-	s.syncAsByte(_dbDay);
-	s.syncAsByte(_tempAge);
-	
-	for (int i = 0; i < 18; ++i)
-		s.syncAsByte(_skills[i]);
-	SavesManager::syncBitFlags(s, &_awards[0], &_awards[512]);
-	SavesManager::syncBitFlags(s, &_spells[0], &_spells[312]);
-	
-	s.syncAsByte(_lloydMap);
-	s.syncAsByte(_lloydPosition.x);
-	s.syncAsByte(_lloydPosition.y);
-	s.syncAsByte(_hasSpells);
-	s.syncAsByte(_currentSpell);
-	s.syncAsByte(_quickOption);
-
-	for (int i = 0; i < 9; ++i)
-		_weapons[i].synchronize(s);
-	for (int i = 0; i < 9; ++i)
-		_armor[i].synchronize(s);
-	for (int i = 0; i < 9; ++i)
-		_accessories[i].synchronize(s);
-	for (int i = 0; i < 9; ++i)
-		_misc[i].synchronize(s);
-
-	s.syncAsByte(_lloydSide);
-	_fireResistence.synchronize(s);
-	_coldResistence.synchronize(s);
-	_electricityResistence.synchronize(s);
-	_poisonResistence.synchronize(s);
-	_energyResistence.synchronize(s);
-	_magicResistence.synchronize(s);
-	
-	_conditions.synchronize(s);
-
-	s.syncAsUint16LE(_townUnknown);
-	s.syncAsByte(_unknown2);
-	s.syncAsUint16LE(_currentHp);
-	s.syncAsUint16LE(_currentSp);
-	s.syncAsUint16LE(_ybDay);
-	s.syncAsUint32LE(_experience);
-	s.syncAsByte(_currentAdventuringSpell);
-	s.syncAsByte(_currentCombatSpell);
-}
-
-/*------------------------------------------------------------------------*/
-
-void Roster::synchronize(Common::Serializer &s) {
-	if (s.isLoading())
-		resize(30);
-
-	for (uint i = 0; i < 30; ++i)
-		(*this)[i].synchronize(s);
-}
-
-/*------------------------------------------------------------------------*/
-
 /**
  * Synchronizes a boolean array as a bitfield set
  */
diff --git a/engines/xeen/saves.h b/engines/xeen/saves.h
index 8b29f15..f3ace80 100644
--- a/engines/xeen/saves.h
+++ b/engines/xeen/saves.h
@@ -25,21 +25,29 @@
 
 #include "common/scummsys.h"
 #include "common/savefile.h"
+#include "graphics/surface.h"
 #include "xeen/party.h"
 
 namespace Xeen {
 
+struct XeenSavegameHeader {
+	uint8 _version;
+	Common::String _saveName;
+	Graphics::Surface *_thumbnail;
+	int _year, _month, _day;
+	int _hour, _minute;
+	int _totalFrames;
+};
+
 class SavesManager {
 private:
 	XeenEngine *_vm;
-public:
-	Party _party;
-	Roster _roster;
+	Party &_party;
+	Roster &_roster;
 public:
 	static void syncBitFlags(Common::Serializer &s, bool *startP, bool *endP);
 public:
-	SavesManager(XeenEngine *vm) : _vm(vm) {}
-
+	SavesManager(XeenEngine *vm, Party &party, Roster &roster);
 	void reset();
 };
 
diff --git a/engines/xeen/xeen.cpp b/engines/xeen/xeen.cpp
index 45d9c22..dfa05b0 100644
--- a/engines/xeen/xeen.cpp
+++ b/engines/xeen/xeen.cpp
@@ -42,6 +42,7 @@ XeenEngine::XeenEngine(OSystem *syst, const XeenGameDescription *gameDesc)
 	_sound = nullptr;
 	_eventData = nullptr;
 	Common::fill(&_activeRoster[0], &_activeRoster[MAX_ACTIVE_PARTY], nullptr);
+	_isEarlyGame = false;
 }
 
 XeenEngine::~XeenEngine() {
@@ -64,7 +65,7 @@ void XeenEngine::initialize() {
 	FileManager::init(this);
 	_debugger = new Debugger(this);
 	_events = new EventsManager(this);
-	_saves = new SavesManager(this);
+	_saves = new SavesManager(this, _party, _roster);
 	_screen = new Screen(this);
 	_screen->setupWindows();
 	_sound = new SoundManager(this);
@@ -254,9 +255,11 @@ void XeenEngine::drawUI() {
 
 	// Get mappings to the active characters in the party
 	Common::fill(&_activeRoster[0], &_activeRoster[MAX_ACTIVE_PARTY], nullptr);
-	for (int i = 0; i < _saves->_party._partyCount; ++i) {
-		_activeRoster[i] = &_saves->_roster[_saves->_party._partyMembers[i]];
+	for (int i = 0; i < _party._partyCount; ++i) {
+		_activeRoster[i] = &_roster[_party._partyMembers[i]];
 	}
+
+	_isEarlyGame = _party._minutes >= 300;
 }
 
 } // End of namespace Xeen
diff --git a/engines/xeen/xeen.h b/engines/xeen/xeen.h
index 159ce74..787cc3d 100644
--- a/engines/xeen/xeen.h
+++ b/engines/xeen/xeen.h
@@ -31,7 +31,6 @@
 #include "common/serializer.h"
 #include "common/util.h"
 #include "engines/engine.h"
-#include "graphics/surface.h"
 #include "xeen/debugger.h"
 #include "xeen/events.h"
 #include "xeen/party.h"
@@ -76,20 +75,12 @@ struct XeenGameDescription;
 #define XEEN_SAVEGAME_VERSION 1
 #define GAME_FRAME_TIME 50
 
-struct XeenSavegameHeader {
-	uint8 _version;
-	Common::String _saveName;
-	Graphics::Surface *_thumbnail;
-	int _year, _month, _day;
-	int _hour, _minute;
-	int _totalFrames;
-};
-
 class XeenEngine : public Engine {
 private:
 	const XeenGameDescription *_gameDescription;
 	Common::RandomSource _randomSource;
 	int _loadSaveSlot;
+	bool _isEarlyGame;
 
 	void showIntro();
 
@@ -127,6 +118,8 @@ public:
 	Mode _mode;
 	GameEvent _gameEvent;
 	Common::SeekableReadStream *_eventData;
+	Roster _roster;
+	Party _party;
 	PlayerStruct *_activeRoster[MAX_ACTIVE_PARTY];
 public:
 	XeenEngine(OSystem *syst, const XeenGameDescription *gameDesc);


Commit: 21d981f8e86bf214daa2e203acc2fb20c82ec8a0
    https://github.com/scummvm/scummvm/commit/21d981f8e86bf214daa2e203acc2fb20c82ec8a0
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-01-02T12:34:45-10:00

Commit Message:
XEEN: Fix compiler warnings

Changed paths:
    engines/xeen/darkside/darkside_game.cpp
    engines/xeen/debugger.cpp
    engines/xeen/resources.cpp



diff --git a/engines/xeen/darkside/darkside_game.cpp b/engines/xeen/darkside/darkside_game.cpp
index c039d1f..30f5458 100644
--- a/engines/xeen/darkside/darkside_game.cpp
+++ b/engines/xeen/darkside/darkside_game.cpp
@@ -181,7 +181,7 @@ void DarkSideEngine::showStartSequence() {
 	int idx1 = 0;
 	bool skipElapsed = false;
 	uint32 timeExpired = 0;
-	bool fadeFlag = true;
+//	bool fadeFlag = true;
 
 	for (int idx = 200; idx > 0; ) {
 		_events->updateGameCounter();
@@ -218,6 +218,10 @@ void DarkSideEngine::showStartSequence() {
 
 	_events->updateGameCounter();
 	pause(30);
+
+	// TODO: More
+	_sound->playMusic(voc[0]);
+	_sound->playMusic(voc[1]);
 }
 
 } // End of namespace Xeen
diff --git a/engines/xeen/debugger.cpp b/engines/xeen/debugger.cpp
index aa4516e..a83af9f 100644
--- a/engines/xeen/debugger.cpp
+++ b/engines/xeen/debugger.cpp
@@ -25,7 +25,7 @@
 #include "xeen/debugger.h"
 
 namespace Xeen {
-
+/*
 static int strToInt(const char *s) {
 	if (!*s)
 		// No string at all
@@ -41,6 +41,7 @@ static int strToInt(const char *s) {
 		error("strToInt failed on string \"%s\"", s);
 	return (int)tmp;
 }
+*/
 
 /*------------------------------------------------------------------------*/
 
diff --git a/engines/xeen/resources.cpp b/engines/xeen/resources.cpp
index d1177da..de0804d 100644
--- a/engines/xeen/resources.cpp
+++ b/engines/xeen/resources.cpp
@@ -26,42 +26,42 @@
 namespace Xeen {
 
 const char *const CREDITS =
-	"\013012\010000\003c\01435Designed and Directed By:\n"
-	"\01417Jon Van Caneghem\003l\n"
+	"\013""012\010""000\003""c\014""35Designed and Directed By:\n"
+	"\014""17Jon Van Caneghem\003""l\n"
 	"\n"
-	"\t025\01435Programming:\n"
-	"\t035\01417Mark Caldwell\n"
+	"\t025\014""35Programming:\n"
+	"\t035\014""17Mark Caldwell\n"
 	"\t035Dave Hathaway\n"
 	"\n"
-	"\t025\01435Sound System & FX:\n"
-	"\t035\01417Mike Heilemann\n"
+	"\t025\014""35Sound System & FX:\n"
+	"\t035\014""17Mike Heilemann\n"
 	"\n"
-	"\t025\01435Music & Speech:\n"
-	"\t035\01417Tim Tully\n"
+	"\t025\014""35Music & Speech:\n"
+	"\t035\014""17Tim Tully\n"
 	"\n"
-	"\t025\01435Writing:\n"
-	"\t035\01417Paul Rattner\n"
+	"\t025\014""35Writing:\n"
+	"\t035\014""17Paul Rattner\n"
 	"\t035Debbie Van Caneghem\n"
-	"\t035Jon Van Caneghem\013012\n"
+	"\t035Jon Van Caneghem\013""012\n"
 	"\n"
 	"\n"
-	"\t180\01435Graphics:\n"
-	"\t190\01417Jonathan P. Gwyn\n"
+	"\t180\014""35Graphics:\n"
+	"\t190\014""17Jonathan P. Gwyn\n"
 	"\t190Bonita Long-Hemsath\n"
 	"\t190Julia Ulano\n"
 	"\t190Ricardo Barrera\n"
 	"\n"
-	"\t180\01435Testing:\n"
-	"\t190\01417Benjamin Bent\n"
+	"\t180\014""35Testing:\n"
+	"\t190\014""17Benjamin Bent\n"
 	"\t190Christian Dailey\n"
 	"\t190Mario Escamilla\n"
 	"\t190Marco Hunter\n"
 	"\t190Robert J. Lupo\n"
 	"\t190Clayton Retzer\n"
-	"\t190David Vela\003c";
+	"\t190David Vela\003""c";
 
 const char *const OPTIONS_TITLE = 
-	"\x0D\x01\003c\014dMight and Magic Options\n"
+	"\x0D\x01\003""c\014""dMight and Magic Options\n"
 	"World of Xeen\x02\n"
 	"\v117Copyright (c) 1993 NWC, Inc.\n"
 	"All Rights Reserved\x01";


Commit: e1404f127d376225d0c15c43b12f59749689c731
    https://github.com/scummvm/scummvm/commit/e1404f127d376225d0c15c43b12f59749689c731
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-01-02T13:30:00-10:00

Commit Message:
XEEN: Simplified SpriteResource class, char faces loading in main engine

Changed paths:
    engines/xeen/events.h
    engines/xeen/sprites.cpp
    engines/xeen/sprites.h
    engines/xeen/xeen.cpp
    engines/xeen/xeen.h



diff --git a/engines/xeen/events.h b/engines/xeen/events.h
index 5a9faf1..7a6a65f 100644
--- a/engines/xeen/events.h
+++ b/engines/xeen/events.h
@@ -41,7 +41,7 @@ private:
 	uint32 _gameCounter;
 	uint32 _priorGameCounterTime;
 	Common::KeyCode _keyCode;
-	FramesResource _sprites;
+	SpriteResource _sprites;
 
 	void nextFrame();
 public:
diff --git a/engines/xeen/sprites.cpp b/engines/xeen/sprites.cpp
index 1b18e98..9485bd2 100644
--- a/engines/xeen/sprites.cpp
+++ b/engines/xeen/sprites.cpp
@@ -29,26 +29,46 @@
 
 namespace Xeen {
 
-GraphicResource::GraphicResource(const Common::String &filename) {
+SpriteResource::SpriteResource() {
+	_filesize = 0;
+	_data = nullptr;
+}
+
+SpriteResource::SpriteResource(const Common::String &filename) {
+	_data = nullptr;
+	load(filename);
+}
+
+void SpriteResource::load(const Common::String &filename) {
 	// Open the resource
 	File f(filename);
 
 	// Read in a copy of the file
 	_filesize = f.size();
+	delete[] _data;
 	_data = new byte[_filesize];
-	f.seek(0);
 	f.read(_data, _filesize);
+
+	// Read in the index
+	f.seek(0);
+	int count = f.readUint16LE();
+	_index.resize(count);
+
+	for (int i = 0; i < count; ++i) {
+		_index[i]._offset1 = f.readUint16LE();
+		_index[i]._offset2 = f.readUint16LE();
+	}
 }
 
-GraphicResource::~GraphicResource() {
+SpriteResource::~SpriteResource() {
 	delete[] _data;
 }
 
-int GraphicResource::size() const {
-	return READ_LE_UINT16(_data);
+int SpriteResource::size() const {
+	return _index.size();
 }
 
-void GraphicResource::drawOffset(XSurface &dest, uint16 offset, const Common::Point &destPos) const {
+void SpriteResource::drawOffset(XSurface &dest, uint16 offset, const Common::Point &destPos) const {
 	// Get cell header
 	Common::MemoryReadStream f(_data, _filesize);
 	f.seek(offset);
@@ -151,43 +171,6 @@ void GraphicResource::drawOffset(XSurface &dest, uint16 offset, const Common::Po
 		destPos.x + xOffset + width, destPos.y + yOffset + height));
 }
 
-/*------------------------------------------------------------------------*/
-
-FramesResource::FramesResource(const Common::String &filename) :
-		GraphicResource(filename) {
-	// Read in the index
-	Common::MemoryReadStream f(_data, _filesize);
-	int count = f.readUint16LE();
-	_index.resize(count);
-
-	for (int i = 0; i < count; ++i) {
-		_index[i] = f.readUint32LE();
-	}
-}
-
-void FramesResource::draw(XSurface &dest, int frame, const Common::Point &destPos) const {
-	drawOffset(dest, _index[frame], destPos);
-}
-
-void FramesResource::draw(XSurface &dest, int frame) const {
-	draw(dest, frame, Common::Point());
-}
-
-/*------------------------------------------------------------------------*/
-
-SpriteResource::SpriteResource(const Common::String &filename) : 
-		GraphicResource(filename) {
-	// Read in the index
-	Common::MemoryReadStream f(_data, _filesize);
-	int count = f.readUint16LE();
-	_index.resize(count);
-
-	for (int i = 0; i < count; ++i) {
-		_index[i]._offset1 = f.readUint16LE();
-		_index[i]._offset2 = f.readUint16LE();
-	}
-}
-
 void SpriteResource::draw(XSurface &dest, int frame, const Common::Point &destPos) const {
 	drawOffset(dest, _index[frame]._offset1, destPos);
 	if (_index[frame]._offset2)
diff --git a/engines/xeen/sprites.h b/engines/xeen/sprites.h
index 6c01a9f..8613d90 100644
--- a/engines/xeen/sprites.h
+++ b/engines/xeen/sprites.h
@@ -33,53 +33,29 @@ namespace Xeen {
 
 class XeenEngine;
 
-class GraphicResource {
-protected:
-	int32 _filesize;
-	byte *_data;
-
-	void drawOffset(XSurface &dest, uint16 offset, const Common::Point &destPos) const;
-public:
-	GraphicResource(const Common::String &filename);
-
-	virtual ~GraphicResource();
-
-	int size() const;
-};
-
-/**
- * Defines a resource that Contains a list of singular sprite frames 
- */
-class FramesResource : public GraphicResource {
-private:
-	Common::Array<uint32> _index;
-public:
-	FramesResource(const Common::String &filename);
-	virtual ~FramesResource() {}
-
-	void draw(XSurface &dest, int frame, const Common::Point &destPos) const;
-
-	void draw(XSurface &dest, int frame) const;
-};
-
-/**
- * Defines a resource that contains sets of two layered sprites per frame
- */
-class SpriteResource : public GraphicResource {
+class SpriteResource {
 private:
 	struct IndexEntry {
 		uint16 _offset1, _offset2;
 	};
 	Common::Array<IndexEntry> _index;
+	int32 _filesize;
+	byte *_data;
 
+	void drawOffset(XSurface &dest, uint16 offset, const Common::Point &destPos) const;
 public:
+	SpriteResource();
 	SpriteResource(const Common::String &filename);
 
-	virtual ~SpriteResource() {}
+	virtual ~SpriteResource();
+
+	void load(const Common::String &filename);
 
 	void draw(XSurface &dest, int frame, const Common::Point &destPos) const;
 
 	void draw(XSurface &dest, int frame) const;
+
+	int size() const;
 };
 
 } // End of namespace Xeen
diff --git a/engines/xeen/xeen.cpp b/engines/xeen/xeen.cpp
index dfa05b0..f2bbbe0 100644
--- a/engines/xeen/xeen.cpp
+++ b/engines/xeen/xeen.cpp
@@ -42,7 +42,10 @@ XeenEngine::XeenEngine(OSystem *syst, const XeenGameDescription *gameDesc)
 	_sound = nullptr;
 	_eventData = nullptr;
 	Common::fill(&_activeRoster[0], &_activeRoster[MAX_ACTIVE_PARTY], nullptr);
+	Common::fill(&_partyFaces[0], &_partyFaces[MAX_ACTIVE_PARTY], nullptr);
+
 	_isEarlyGame = false;
+
 }
 
 XeenEngine::~XeenEngine() {
@@ -243,14 +246,14 @@ void XeenEngine::showMainMenu() {
 
 void XeenEngine::playGame() {
 	_saves->reset();
-	drawUI();
+	drawUI(true);
 }
 
 /*
  * Lots of stuff in this method.
  * TODO: Consider renaming method when better understood
  */
-void XeenEngine::drawUI() {
+void XeenEngine::drawUI(bool soundPlayed) {
 	SpriteResource sprites1("global.icn"), borderSprites("border.icn");
 
 	// Get mappings to the active characters in the party
@@ -260,6 +263,30 @@ void XeenEngine::drawUI() {
 	}
 
 	_isEarlyGame = _party._minutes >= 300;
+	
+	if (_party._mazeId == 0) {
+		if (!soundPlayed) {
+			warning("TODO: loadSound?");
+		}
+
+		if (!_partyFaces[0]) {
+			// Xeen only uses 24 of possible 30 character slots
+			loadCharIcons(24);
+
+			for (int i = 0; i < _party._partyCount; ++i)
+				_partyFaces[i] = &_charFaces[_party._partyMembers[i]];
+		}
+	}
+}
+
+void XeenEngine::loadCharIcons(int numChars) {
+	for (int i = 0; i < numChars; ++i) {
+		// Load new character resource
+		Common::String name = Common::String::format("char%02d.fac", i);
+		_charFaces[i].load(name);
+	}
+
+	_dseFace.load("dse.fac");
 }
 
 } // End of namespace Xeen
diff --git a/engines/xeen/xeen.h b/engines/xeen/xeen.h
index 787cc3d..7155e39 100644
--- a/engines/xeen/xeen.h
+++ b/engines/xeen/xeen.h
@@ -81,12 +81,17 @@ private:
 	Common::RandomSource _randomSource;
 	int _loadSaveSlot;
 	bool _isEarlyGame;
+	SpriteResource _charFaces[TOTAL_CHARACTERS];
+	SpriteResource *_partyFaces[MAX_ACTIVE_PARTY];
+	SpriteResource _dseFace;
 
 	void showIntro();
 
 	void showMainMenu();
 
-	void drawUI();
+	void drawUI(bool soundPlayed);
+
+	void loadCharIcons(int numChars);
 protected:
 	/**
 	* Play the game


Commit: 9b40bd5c6aa8110e7b3a13eec2550a4c6f201668
    https://github.com/scummvm/scummvm/commit/9b40bd5c6aa8110e7b3a13eec2550a4c6f201668
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-01-02T15:25:14-10:00

Commit Message:
XEEN: More UI loading code, refactored Dialog base to ButtonContainer

Changed paths:
    engines/xeen/dialogs.cpp
    engines/xeen/dialogs.h
    engines/xeen/dialogs_options.cpp
    engines/xeen/party.h
    engines/xeen/xeen.cpp
    engines/xeen/xeen.h



diff --git a/engines/xeen/dialogs.cpp b/engines/xeen/dialogs.cpp
index 4d1a876..810c136 100644
--- a/engines/xeen/dialogs.cpp
+++ b/engines/xeen/dialogs.cpp
@@ -22,34 +22,36 @@
 
 #include "common/scummsys.h"
 #include "xeen/dialogs.h"
+#include "xeen/events.h"
 #include "xeen/resources.h"
+#include "xeen/xeen.h"
 
 namespace Xeen {
 
 /**
  * Saves the current list of buttons
  */
-void Dialog::saveButtons() {
+void ButtonContainer::saveButtons() {
 	_savedButtons.push(_buttons);
 }
 
 /*
  * Clears the current list of defined buttons
  */
-void Dialog::clearButtons() {
+void ButtonContainer::clearButtons() {
 	_buttons.clear();
 }
 
-void Dialog::restoreButtons() {
+void ButtonContainer::restoreButtons() {
 	_buttons = _savedButtons.pop();
 }
 
-void Dialog::addButton(const Common::Rect &bounds, char c, SpriteResource *sprites, bool draw = true) {
-	_buttons.push_back(DialogButton(bounds, c, sprites, draw));
+void ButtonContainer::addButton(const Common::Rect &bounds, int val, SpriteResource *sprites, bool draw = true) {
+	_buttons.push_back(UIButton(bounds, val, sprites, draw));
 }
 
-void Dialog::checkEvents() {
-	EventsManager &events = *_vm->_events;
+void ButtonContainer::checkEvents(XeenEngine *vm) {
+	EventsManager &events = *vm->_events;
 	events.pollEventsAndWait();
 
 	if (events._leftButton) {
@@ -59,7 +61,7 @@ void Dialog::checkEvents() {
 
 		for (uint i = 0; i < _buttons.size(); ++i) {
 			if (_buttons[i]._bounds.contains(pt)) {
-				_key = _buttons[i]._c;
+				_buttonValue = _buttons[i]._value;
 				return;
 			}
 		}
@@ -67,7 +69,7 @@ void Dialog::checkEvents() {
 		Common::KeyState keyState;
 		events.getKey(keyState);
 		if (keyState.ascii >= 32 && keyState.ascii <= 127) {
-			_key = keyState.ascii;
+			_buttonValue = keyState.ascii;
 			return;
 		}
 	}
@@ -77,13 +79,13 @@ void Dialog::checkEvents() {
 /**
 * Draws the scroll in the background
 */
-void Dialog::doScroll(bool drawFlag, bool doFade) {
-	Screen &screen = *_vm->_screen;
-	EventsManager &events = *_vm->_events;
+void ButtonContainer::doScroll(XeenEngine *vm, bool drawFlag, bool doFade) {
+	Screen &screen = *vm->_screen;
+	EventsManager &events = *vm->_events;
 
-	if (_vm->getGameID() != GType_Clouds) {
+	if (vm->getGameID() != GType_Clouds) {
 		if (doFade) {
-			_vm->_screen->fadeIn(2);
+			screen.fadeIn(2);
 		}
 		return;
 	}
@@ -127,8 +129,8 @@ void Dialog::doScroll(bool drawFlag, bool doFade) {
 				marb[i / 5]->draw(screen, i % 5);
 			}
 
-			while (!_vm->shouldQuit() && _vm->_events->timeElapsed() == 0)
-				_vm->_events->pollEventsAndWait();
+			while (!vm->shouldQuit() && events.timeElapsed() == 0)
+				events.pollEventsAndWait();
 
 			screen._windows[0].update();
 			if (i == 0 && doFade)
@@ -151,8 +153,8 @@ void Dialog::doScroll(bool drawFlag, bool doFade) {
 				marb[i / 5]->draw(screen, i % 5);
 			}
 
-			while (!_vm->shouldQuit() && _vm->_events->timeElapsed() == 0)
-				_vm->_events->pollEventsAndWait();
+			while (!vm->shouldQuit() && events.timeElapsed() == 0)
+				events.pollEventsAndWait();
 
 			screen._windows[0].update();
 			if (i == 0 && doFade)
@@ -178,10 +180,24 @@ void Dialog::doScroll(bool drawFlag, bool doFade) {
 		delete hand[i];
 }
 
+/**
+ * Draws the buttons onto the passed surface
+ */
+void ButtonContainer::drawButtons(XSurface *surface) {
+	for (uint btnIndex = 0; btnIndex < _buttons.size(); ++btnIndex) {
+		UIButton &btn = _buttons[btnIndex];
+		if (btn._draw) {
+			btn._sprites->draw(*surface, btnIndex * 2,
+				Common::Point(btn._bounds.left, btn._bounds.top));
+		}
+	}
+}
+
+
 /*------------------------------------------------------------------------*/
 
 void SettingsBaseDialog::showContents(SpriteResource &title1, bool waitFlag) {
-	checkEvents();
+	checkEvents(_vm);
 }
 
 /*------------------------------------------------------------------------*/
@@ -197,12 +213,12 @@ void CreditsScreen::execute() {
 	EventsManager &events = *_vm->_events;
 	
 	// Handle drawing the credits screen
-	doScroll(true, false);
+	doScroll(_vm, true, false);
 	screen._windows[28].close();
 
 	screen.loadBackground("marb.raw");
 	screen._windows[0].writeString(CREDITS);
-	doScroll(false, false);
+	doScroll(_vm, false, false);
 	
 	events.setCursor(0);
 	screen._windows[0].update();
@@ -212,7 +228,7 @@ void CreditsScreen::execute() {
 	while (!events.isKeyMousePressed())
 		events.pollEventsAndWait();
 
-	doScroll(true, false);
+	doScroll(_vm, true, false);
 }
 
 } // End of namespace Xeen
diff --git a/engines/xeen/dialogs.h b/engines/xeen/dialogs.h
index 1f8f2fb..61ae734 100644
--- a/engines/xeen/dialogs.h
+++ b/engines/xeen/dialogs.h
@@ -26,36 +26,39 @@
 #include "common/array.h"
 #include "common/stack.h"
 #include "common/rect.h"
-#include "xeen/xeen.h"
+#include "xeen/sprites.h"
 
 namespace Xeen {
 
-class DialogButton {
+class XeenEngine;
+
+class UIButton {
 public:
 	Common::Rect _bounds;
 	SpriteResource *_sprites;
-	char _c;
+	int _value;
 	bool _draw;
 
-	DialogButton(const Common::Rect &bounds, char c, SpriteResource *sprites, bool draw) :
-		_bounds(bounds), _c(c), _sprites(sprites), _draw(draw) {}
+	UIButton(const Common::Rect &bounds, int value, SpriteResource *sprites, bool draw) :
+		_bounds(bounds), _value(value), _sprites(sprites), _draw(draw) {}
 
-	DialogButton() : _c('\0'), _sprites(nullptr), _draw(false) {}
+	UIButton() : _value(0), _sprites(nullptr), _draw(false) {}
 };
 
-class Dialog {
+class ButtonContainer {
 private:
-	Common::Stack< Common::Array<DialogButton> > _savedButtons;
+	Common::Stack< Common::Array<UIButton> > _savedButtons;
 protected:
-	XeenEngine *_vm;
-	Common::Array<DialogButton> _buttons;
-	char _key;
+	Common::Array<UIButton> _buttons;
+	int _buttonValue;
 
-	void doScroll(bool drawFlag, bool doFade);
+	void doScroll(XeenEngine *vm, bool drawFlag, bool doFade);
 
-	void checkEvents();
+	void checkEvents(XeenEngine *vm);
+
+	void drawButtons(XSurface *surface);
 public:
-	Dialog(XeenEngine *vm): _vm(vm), _key('\0') {}
+	ButtonContainer() : _buttonValue(0) {}
 
 	void saveButtons();
 
@@ -63,19 +66,23 @@ public:
 
 	void restoreButtons();
 
-	void addButton(const Common::Rect &bounds, char c, SpriteResource *sprites, bool draw);
+	void addButton(const Common::Rect &bounds, int val, SpriteResource *sprites, bool draw);
 };
 
-class SettingsBaseDialog : public Dialog {
+class SettingsBaseDialog : public ButtonContainer {
 protected:
+	XeenEngine *_vm;
+
 	virtual void showContents(SpriteResource &title1, bool mode);
 public:
-	SettingsBaseDialog(XeenEngine *vm) : Dialog(vm) {}
+	SettingsBaseDialog(XeenEngine *vm) : ButtonContainer(), _vm(vm) {}
 };
 
-class CreditsScreen: public Dialog {
+class CreditsScreen: public ButtonContainer {
 private:
-	CreditsScreen(XeenEngine *vm) : Dialog(vm) {}
+	XeenEngine *_vm;
+
+	CreditsScreen(XeenEngine *vm) : ButtonContainer(), _vm(vm) {}
 
 	void execute();
 public:
diff --git a/engines/xeen/dialogs_options.cpp b/engines/xeen/dialogs_options.cpp
index e85a4af..eace67e 100644
--- a/engines/xeen/dialogs_options.cpp
+++ b/engines/xeen/dialogs_options.cpp
@@ -81,14 +81,14 @@ void OptionsMenu::execute() {
 
 		while (!_vm->shouldQuit()) {
 			// Show the dialog with a continually animating background
-			while (!_vm->shouldQuit() && _key == '\0')
+			while (!_vm->shouldQuit() && !_buttonValue)
 				showContents(title1Sprites, true);
 			if (_vm->shouldQuit())
 				return;
 
 			// Handle keypress
-			char key = toupper(_key);
-			_key = '\0';
+			int key = toupper(_buttonValue);
+			_buttonValue = 0;
 
 			if (key == 'C' || key == 'V') {
 				// Show credits
@@ -218,20 +218,13 @@ void WorldOptionsMenu::showContents(SpriteResource &title1, bool waitFlag) {
 	screen._windows[28].frame();
 	screen._windows[28].writeString(OPTIONS_TITLE);
 
-	for (uint btnIndex = 0; btnIndex < _buttons.size(); ++btnIndex) {
-		DialogButton &btn = _buttons[btnIndex];
-		if (btn._draw) {
-			btn._sprites->draw(screen._windows[0], btnIndex * 2,
-				Common::Point(btn._bounds.left, btn._bounds.top));
-		}
-	}
+	drawButtons(&screen._windows[0]);
 
 	if (waitFlag) {
 		screen._windows[0].update();
 
-		while (!_vm->shouldQuit() && _key == Common::KEYCODE_INVALID &&
-				events.timeElapsed() < 3) {
-			checkEvents();
+		while (!_vm->shouldQuit() && !_buttonValue && events.timeElapsed() < 3) {
+			checkEvents(_vm);
 		}
 	}
 }
diff --git a/engines/xeen/party.h b/engines/xeen/party.h
index 6a6ec5f..9031b88 100644
--- a/engines/xeen/party.h
+++ b/engines/xeen/party.h
@@ -57,6 +57,7 @@ enum ConditionType { CURSED = 0, HEART_BROKEN = 1, WEAK = 2, POISONED = 3,
 
 #define ITEMS_COUNT 36
 #define TOTAL_CHARACTERS 30
+#define XEEN_TOTAL_CHARACTERS 24
 #define MAX_ACTIVE_PARTY 6
 
 class XeenEngine;
diff --git a/engines/xeen/xeen.cpp b/engines/xeen/xeen.cpp
index f2bbbe0..d7f6138 100644
--- a/engines/xeen/xeen.cpp
+++ b/engines/xeen/xeen.cpp
@@ -34,7 +34,7 @@
 namespace Xeen {
 
 XeenEngine::XeenEngine(OSystem *syst, const XeenGameDescription *gameDesc)
-		: _gameDescription(gameDesc), Engine(syst), _randomSource("Xeen") {
+		: Engine(syst), ButtonContainer(), _gameDescription(gameDesc), _randomSource("Xeen") {
 	_debugger = nullptr;
 	_events = nullptr;
 	_saves = nullptr;
@@ -43,9 +43,9 @@ XeenEngine::XeenEngine(OSystem *syst, const XeenGameDescription *gameDesc)
 	_eventData = nullptr;
 	Common::fill(&_activeRoster[0], &_activeRoster[MAX_ACTIVE_PARTY], nullptr);
 	Common::fill(&_partyFaces[0], &_partyFaces[MAX_ACTIVE_PARTY], nullptr);
-
 	_isEarlyGame = false;
-
+	_loadDarkSide = 1;
+	_buttonsLoaded = false;
 }
 
 XeenEngine::~XeenEngine() {
@@ -246,15 +246,16 @@ void XeenEngine::showMainMenu() {
 
 void XeenEngine::playGame() {
 	_saves->reset();
-	drawUI(true);
+	setupUI(true);
 }
 
 /*
  * Lots of stuff in this method.
  * TODO: Consider renaming method when better understood
  */
-void XeenEngine::drawUI(bool soundPlayed) {
-	SpriteResource sprites1("global.icn"), borderSprites("border.icn");
+void XeenEngine::setupUI(bool soundPlayed) {
+	SpriteResource sprites1("global.icn"), borderSprites("border.icn"),
+		uiSprites("inn.icn");
 
 	// Get mappings to the active characters in the party
 	Common::fill(&_activeRoster[0], &_activeRoster[MAX_ACTIVE_PARTY], nullptr);
@@ -271,11 +272,39 @@ void XeenEngine::drawUI(bool soundPlayed) {
 
 		if (!_partyFaces[0]) {
 			// Xeen only uses 24 of possible 30 character slots
-			loadCharIcons(24);
+			loadCharIcons(XEEN_TOTAL_CHARACTERS);
 
 			for (int i = 0; i < _party._partyCount; ++i)
 				_partyFaces[i] = &_charFaces[_party._partyMembers[i]];
 		}
+
+		_mode = MODE_1;
+		Common::Array<int> xeenSideChars;
+
+		// Build up a list of characters on the same Xeen side being loaded
+		for (int i = 0; i < XEEN_TOTAL_CHARACTERS; ++i) {
+			PlayerStruct &player = _roster[i];
+			if (player._name.empty() || player._xeenSide != _loadDarkSide)
+				continue;
+
+			xeenSideChars.push_back(i);
+		}
+
+		// Add in buttons for the UI
+		_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);
+
+		setupGameBackground();
 	}
 }
 
@@ -289,4 +318,8 @@ void XeenEngine::loadCharIcons(int numChars) {
 	_dseFace.load("dse.fac");
 }
 
+void XeenEngine::setupGameBackground() {
+	
+}
+
 } // End of namespace Xeen
diff --git a/engines/xeen/xeen.h b/engines/xeen/xeen.h
index 7155e39..7261efc 100644
--- a/engines/xeen/xeen.h
+++ b/engines/xeen/xeen.h
@@ -32,6 +32,7 @@
 #include "common/util.h"
 #include "engines/engine.h"
 #include "xeen/debugger.h"
+#include "xeen/dialogs.h"
 #include "xeen/events.h"
 #include "xeen/party.h"
 #include "xeen/saves.h"
@@ -67,6 +68,7 @@ enum XeenDebugChannels {
 
 enum Mode {
 	MODE_0 = 0,
+	MODE_1 = 1,
 	MODE_9 = 9
 };
 
@@ -75,23 +77,27 @@ struct XeenGameDescription;
 #define XEEN_SAVEGAME_VERSION 1
 #define GAME_FRAME_TIME 50
 
-class XeenEngine : public Engine {
+class XeenEngine : public Engine, public ButtonContainer {
 private:
 	const XeenGameDescription *_gameDescription;
 	Common::RandomSource _randomSource;
 	int _loadSaveSlot;
 	bool _isEarlyGame;
+	int _loadDarkSide;
 	SpriteResource _charFaces[TOTAL_CHARACTERS];
 	SpriteResource *_partyFaces[MAX_ACTIVE_PARTY];
 	SpriteResource _dseFace;
+	bool _buttonsLoaded;
 
 	void showIntro();
 
 	void showMainMenu();
 
-	void drawUI(bool soundPlayed);
+	void setupUI(bool soundPlayed);
 
 	void loadCharIcons(int numChars);
+
+	void setupGameBackground();
 protected:
 	/**
 	* Play the game


Commit: 7d4fcfd5afb272c62ad7f1628cc1adfe17c8ee6f
    https://github.com/scummvm/scummvm/commit/7d4fcfd5afb272c62ad7f1628cc1adfe17c8ee6f
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-01-02T16:02:24-10:00

Commit Message:
XEEN: Added checkSkill and animating indicators to assembleBorder

Changed paths:
    engines/xeen/dialogs.cpp
    engines/xeen/dialogs_options.cpp
    engines/xeen/party.h
    engines/xeen/screen.h
    engines/xeen/sprites.cpp
    engines/xeen/sprites.h
    engines/xeen/xeen.cpp
    engines/xeen/xeen.h



diff --git a/engines/xeen/dialogs.cpp b/engines/xeen/dialogs.cpp
index 810c136..70a22d1 100644
--- a/engines/xeen/dialogs.cpp
+++ b/engines/xeen/dialogs.cpp
@@ -214,7 +214,7 @@ void CreditsScreen::execute() {
 	
 	// Handle drawing the credits screen
 	doScroll(_vm, true, false);
-	screen._windows[28].close();
+	screen._windows[GAME_WINDOW].close();
 
 	screen.loadBackground("marb.raw");
 	screen._windows[0].writeString(CREDITS);
diff --git a/engines/xeen/dialogs_options.cpp b/engines/xeen/dialogs_options.cpp
index eace67e..fb7366c 100644
--- a/engines/xeen/dialogs_options.cpp
+++ b/engines/xeen/dialogs_options.cpp
@@ -56,7 +56,7 @@ void OptionsMenu::execute() {
 	File newBright("newbrigh.m");
 	_vm->_sound->playMusic(newBright);
 
-	screen._windows[28].setBounds(Common::Rect(72, 25, 248, 175));
+	screen._windows[GAME_WINDOW].setBounds(Common::Rect(72, 25, 248, 175));
 
 	Common::String title1, title2;
 	startup(title1, title2);
@@ -202,7 +202,7 @@ void WorldOptionsMenu::setBackground(bool doFade) {
 }
 
 void WorldOptionsMenu::openWindow() {
-	_vm->_screen->_windows[28].open();
+	_vm->_screen->_windows[GAME_WINDOW].open();
 }
 
 void WorldOptionsMenu::showContents(SpriteResource &title1, bool waitFlag) {
@@ -215,8 +215,8 @@ void WorldOptionsMenu::showContents(SpriteResource &title1, bool waitFlag) {
 	title1.draw(screen._windows[0], _bgFrame);
 
 	// Draw the basic frame for the optitons menu and title text
-	screen._windows[28].frame();
-	screen._windows[28].writeString(OPTIONS_TITLE);
+	screen._windows[GAME_WINDOW].frame();
+	screen._windows[GAME_WINDOW].writeString(OPTIONS_TITLE);
 
 	drawButtons(&screen._windows[0]);
 
diff --git a/engines/xeen/party.h b/engines/xeen/party.h
index 9031b88..a42fe6e 100644
--- a/engines/xeen/party.h
+++ b/engines/xeen/party.h
@@ -50,7 +50,7 @@ enum Skill { THIEVERY = 0, ARMS_MASTER = 1, ASTROLOGER = 2, BODYBUILDER = 3,
 	SPOT_DOORS = 16, DANGER_SENSE = 17
 };
 
-enum ConditionType { CURSED = 0, HEART_BROKEN = 1, WEAK = 2, POISONED = 3,
+enum ConditionType { CURSED = 0, HEARTBROKEN = 1, WEAK = 2, POISONED = 3,
 	DISEASED = 4, INSANE = 5, IN_LOVE = 6, DRUNK = 7, SLEEP = 8, 
 	DEPRESSED = 9, CONFUSED = 10, PARALYZED = 11
 };
diff --git a/engines/xeen/screen.h b/engines/xeen/screen.h
index fd8a509..0f16934 100644
--- a/engines/xeen/screen.h
+++ b/engines/xeen/screen.h
@@ -36,6 +36,7 @@ namespace Xeen {
 #define SCREEN_HEIGHT 200
 #define PALETTE_COUNT 256
 #define PALETTE_SIZE (256 * 3)
+#define GAME_WINDOW 28
 
 class XeenEngine;
 class Screen;
diff --git a/engines/xeen/sprites.cpp b/engines/xeen/sprites.cpp
index 9485bd2..5b8fe52 100644
--- a/engines/xeen/sprites.cpp
+++ b/engines/xeen/sprites.cpp
@@ -64,10 +64,6 @@ SpriteResource::~SpriteResource() {
 	delete[] _data;
 }
 
-int SpriteResource::size() const {
-	return _index.size();
-}
-
 void SpriteResource::drawOffset(XSurface &dest, uint16 offset, const Common::Point &destPos) const {
 	// Get cell header
 	Common::MemoryReadStream f(_data, _filesize);
diff --git a/engines/xeen/sprites.h b/engines/xeen/sprites.h
index 8613d90..e9cdf72 100644
--- a/engines/xeen/sprites.h
+++ b/engines/xeen/sprites.h
@@ -55,7 +55,9 @@ public:
 
 	void draw(XSurface &dest, int frame) const;
 
-	int size() const;
+	int size() const { return _index.size(); }
+
+	bool empty() const { return _index.size() == 0; }
 };
 
 } // End of namespace Xeen
diff --git a/engines/xeen/xeen.cpp b/engines/xeen/xeen.cpp
index d7f6138..a46526e 100644
--- a/engines/xeen/xeen.cpp
+++ b/engines/xeen/xeen.cpp
@@ -46,6 +46,11 @@ XeenEngine::XeenEngine(OSystem *syst, const XeenGameDescription *gameDesc)
 	_isEarlyGame = false;
 	_loadDarkSide = 1;
 	_buttonsLoaded = false;
+	_batUIFrame = 0;
+	_spotDoorsUIFrame = 0;
+	_spotDoorsAllowed = false;
+	_dangerSenseUIFrame = 0;
+	_dangerSenseAllowed = false;
 }
 
 XeenEngine::~XeenEngine() {
@@ -254,8 +259,10 @@ void XeenEngine::playGame() {
  * TODO: Consider renaming method when better understood
  */
 void XeenEngine::setupUI(bool soundPlayed) {
-	SpriteResource sprites1("global.icn"), borderSprites("border.icn"),
-		uiSprites("inn.icn");
+	SpriteResource uiSprites("inn.icn");
+	_globalSprites.load("global.icn");
+	_borderSprites.load("border.icn");
+	_spellFxSprites.load("spellfx.icn");
 
 	// Get mappings to the active characters in the party
 	Common::fill(&_activeRoster[0], &_activeRoster[MAX_ACTIVE_PARTY], nullptr);
@@ -319,7 +326,61 @@ void XeenEngine::loadCharIcons(int numChars) {
 }
 
 void XeenEngine::setupGameBackground() {
+	_screen->loadBackground("back.raw");
+	assembleBorder();
+}
+
+void XeenEngine::assembleBorder() {
+	Window &gameWindow = _screen->_windows[28];
+
+	// Draw the outer frame
+	_globalSprites.draw(gameWindow, 0);
 	
+	// Draw the animating bat character used to show when levitate is active
+	_borderSprites.draw(*_screen, _party._levitateActive ? _batUIFrame + 16 : 16);
+	_batUIFrame = (_batUIFrame + 1) % 12;
+
+	// Draw UI element to indicate whether can spot hidden doors
+	_borderSprites.draw(*_screen,
+		(_spotDoorsAllowed && checkSkill(SPOT_DOORS)) ? _spotDoorsUIFrame + 28 : 28,
+		Common::Point(194, 91));
+	_spotDoorsUIFrame = (_spotDoorsUIFrame + 1) % 12;
+
+	// Draw UI element to indicate whether can sense danger
+	_borderSprites.draw(*_screen,
+		(_dangerSenseAllowed && checkSkill(DANGER_SENSE)) ? _spotDoorsUIFrame + 40 : 40,
+		Common::Point(107, 9));
+	_dangerSenseUIFrame = (_dangerSenseUIFrame + 1) % 12;
+
+
+	// TODO
+}
+
+bool XeenEngine::checkSkill(Skill skillId) {
+	int total = 0;
+	for (int i = 0; i < _party._partyCount; ++i) {
+		if (_activeRoster[i]->_skills[skillId]) {
+			++total;
+
+			switch (skillId) {
+			case MOUNTAINEER:
+			case PATHFINDER:
+				// At least two characters need skill for check to return true
+				if (total == 2)
+					return true;
+				break;
+			case CRUSADER:
+			case SWIMMING:
+				// Entire party must have skill for check to return true
+				if (total == _party._partyCount)
+					return true;
+				break;
+			default:
+				// All other skills only need to have a single player having it
+				return true;
+			}
+		}
+	}
 }
 
 } // End of namespace Xeen
diff --git a/engines/xeen/xeen.h b/engines/xeen/xeen.h
index 7261efc..b6ca766 100644
--- a/engines/xeen/xeen.h
+++ b/engines/xeen/xeen.h
@@ -87,7 +87,15 @@ private:
 	SpriteResource _charFaces[TOTAL_CHARACTERS];
 	SpriteResource *_partyFaces[MAX_ACTIVE_PARTY];
 	SpriteResource _dseFace;
+	SpriteResource _globalSprites;
+	SpriteResource _borderSprites;
+	SpriteResource _spellFxSprites;
 	bool _buttonsLoaded;
+	int _batUIFrame;
+	int _spotDoorsUIFrame;
+	bool _spotDoorsAllowed;
+	int _dangerSenseUIFrame;
+	bool _dangerSenseAllowed;
 
 	void showIntro();
 
@@ -98,6 +106,10 @@ private:
 	void loadCharIcons(int numChars);
 
 	void setupGameBackground();
+
+	void assembleBorder();
+
+	bool checkSkill(Skill skillId);
 protected:
 	/**
 	* Play the game


Commit: 1a999e3ceb39603bca213f81342a055e1eee7ebe
    https://github.com/scummvm/scummvm/commit/1a999e3ceb39603bca213f81342a055e1eee7ebe
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-01-02T16:08:38-10:00

Commit Message:
XEEN: Refactored checkSkill into Party class

Changed paths:
    engines/xeen/party.cpp
    engines/xeen/party.h
    engines/xeen/xeen.cpp
    engines/xeen/xeen.h



diff --git a/engines/xeen/party.cpp b/engines/xeen/party.cpp
index c5f80eb..97b4a76 100644
--- a/engines/xeen/party.cpp
+++ b/engines/xeen/party.cpp
@@ -40,138 +40,6 @@ void AttributePair::synchronize(Common::Serializer &s) {
 
 /*------------------------------------------------------------------------*/
 
-Party::Party() {
-	_partyCount = 0;
-	_realPartyCount = 0;
-	Common::fill(&_partyMembers[0], &_partyMembers[8], 0);
-	_mazeDirection = DIR_NORTH;
-	_mazeId = _priorMazeId = 0;
-	_levitateActive = false;
-	_automapOn = false;
-	_wizardEyeActive = false;
-	_clairvoyanceActive = false;
-	_walkOnWaterActive = false;
-	_blessedActive = false;
-	_powerShieldActive = false;
-	_holyBonusActive = false;
-	_heroismActive = false;
-	_difficulty = ADVENTURER;
-	_cloudsEnd = false;
-	_darkSideEnd = false;
-	_worldEnd = false;
-	hour_maybe = 0;
-	_day = 0;
-	_year = 0;
-	_minutes = 0;
-	_food = 0;
-	_lightCount = 0;
-	_torchCount = 0;
-	_fireResistence = 0;
-	_electricityResistence = 0;
-	_coldResistence = 0;
-	_poisonResistence = 0;
-	_deathCount = 0;
-	_winCount = 0;
-	_lossCount = 0;
-	_gold = 0;
-	_gems = 0;
-	_bankGold = 0;
-	_bankGems = 0;
-	_totalTime = 0;
-	_rested = false;
-
-	Common::fill(&_gameFlags[0], &_gameFlags[512], false);
-	Common::fill(&_autoNotes[0], &_autoNotes[128], false);
-	Common::fill(&_quests[0], &_quests[64], false);
-	Common::fill(&_questItems[0], &_questItems[85], 0);
-
-	for (int i = 0; i < TOTAL_CHARACTERS; ++i)
-		Common::fill(&_characterFlags[i][0], &_characterFlags[i][24], false);
-}
-
-void Party::synchronize(Common::Serializer &s) {
-	byte dummy[30];
-	Common::fill(&dummy[0], &dummy[30], 0);
-
-	s.syncAsByte(_partyCount);
-	s.syncAsByte(_realPartyCount);
-	for (int i = 0; i < 8; ++i)
-		s.syncAsByte(_partyMembers[i]);
-	s.syncAsByte(_mazeDirection);
-	s.syncAsByte(_mazePosition.x);
-	s.syncAsByte(_mazePosition.y);
-	s.syncAsByte(_mazeId);
-	
-	// Game configuration flags not used in this implementation
-	s.syncBytes(dummy, 3);
-
-	s.syncAsByte(_priorMazeId);
-	s.syncAsByte(_levitateActive);
-	s.syncAsByte(_automapOn);
-	s.syncAsByte(_wizardEyeActive);
-	s.syncAsByte(_clairvoyanceActive);
-	s.syncAsByte(_walkOnWaterActive);
-	s.syncAsByte(_blessedActive);
-	s.syncAsByte(_powerShieldActive);
-	s.syncAsByte(_holyBonusActive);
-	s.syncAsByte(_heroismActive);
-	s.syncAsByte(_difficulty);
-
-	for (int i = 0; i < ITEMS_COUNT; ++i)
-		_blacksmithWeapons[i].synchronize(s);
-	for (int i = 0; i < ITEMS_COUNT; ++i)
-		_blacksmithArmor[i].synchronize(s);
-	for (int i = 0; i < ITEMS_COUNT; ++i)
-		_blacksmithAccessories[i].synchronize(s);
-	for (int i = 0; i < ITEMS_COUNT; ++i)
-		_blacksmithMisc[i].synchronize(s);
-
-	s.syncAsUint16LE(_cloudsEnd);
-	s.syncAsUint16LE(_darkSideEnd);
-	s.syncAsUint16LE(_worldEnd);
-	s.syncAsUint16LE(hour_maybe);
-	s.syncAsUint16LE(_day);
-	s.syncAsUint16LE(_year);
-	s.syncAsUint16LE(_minutes);
-	s.syncAsUint16LE(_food);
-	s.syncAsUint16LE(_lightCount);
-	s.syncAsUint16LE(_torchCount);
-	s.syncAsUint16LE(_fireResistence);
-	s.syncAsUint16LE(_electricityResistence);
-	s.syncAsUint16LE(_coldResistence);
-	s.syncAsUint16LE(_poisonResistence);
-	s.syncAsUint16LE(_deathCount);
-	s.syncAsUint16LE(_winCount);
-	s.syncAsUint16LE(_lossCount);
-	s.syncAsUint32LE(_gold);
-	s.syncAsUint32LE(_gems);
-	s.syncAsUint32LE(_bankGold);
-	s.syncAsUint32LE(_bankGems);
-	s.syncAsUint32LE(_totalTime);
-	s.syncAsByte(_rested);
-	SavesManager::syncBitFlags(s, &_gameFlags[0], &_gameFlags[512]);
-	SavesManager::syncBitFlags(s, &_autoNotes[0], &_autoNotes[128]);
-	SavesManager::syncBitFlags(s, &_quests[0], &_quests[64]);
-	
-	for (int i = 0; i < 85; ++i)
-		s.syncAsByte(_questItems[i]);
-
-	for (int i = 0; i < ITEMS_COUNT; ++i)
-		_blacksmithWeapons2[i].synchronize(s);
-	for (int i = 0; i < ITEMS_COUNT; ++i)
-		_blacksmithArmor2[i].synchronize(s);
-	for (int i = 0; i < ITEMS_COUNT; ++i)
-		_blacksmithAccessories2[i].synchronize(s);
-	for (int i = 0; i < ITEMS_COUNT; ++i)
-		_blacksmithMisc2[i].synchronize(s);
-	
-	for (int i = 0; i < TOTAL_CHARACTERS; ++i)
-		SavesManager::syncBitFlags(s, &_characterFlags[i][0], &_characterFlags[i][24]);
-	s.syncBytes(&dummy[0], 30);
-}
-
-/*------------------------------------------------------------------------*/
-
 Conditions::Conditions() {
 	_cursed = 0;
 	_heartBroken = 0;
@@ -315,4 +183,163 @@ void Roster::synchronize(Common::Serializer &s) {
 		(*this)[i].synchronize(s);
 }
 
+/*------------------------------------------------------------------------*/
+
+Party::Party() {
+	_partyCount = 0;
+	_realPartyCount = 0;
+	Common::fill(&_partyMembers[0], &_partyMembers[8], 0);
+	_mazeDirection = DIR_NORTH;
+	_mazeId = _priorMazeId = 0;
+	_levitateActive = false;
+	_automapOn = false;
+	_wizardEyeActive = false;
+	_clairvoyanceActive = false;
+	_walkOnWaterActive = false;
+	_blessedActive = false;
+	_powerShieldActive = false;
+	_holyBonusActive = false;
+	_heroismActive = false;
+	_difficulty = ADVENTURER;
+	_cloudsEnd = false;
+	_darkSideEnd = false;
+	_worldEnd = false;
+	hour_maybe = 0;
+	_day = 0;
+	_year = 0;
+	_minutes = 0;
+	_food = 0;
+	_lightCount = 0;
+	_torchCount = 0;
+	_fireResistence = 0;
+	_electricityResistence = 0;
+	_coldResistence = 0;
+	_poisonResistence = 0;
+	_deathCount = 0;
+	_winCount = 0;
+	_lossCount = 0;
+	_gold = 0;
+	_gems = 0;
+	_bankGold = 0;
+	_bankGems = 0;
+	_totalTime = 0;
+	_rested = false;
+
+	Common::fill(&_gameFlags[0], &_gameFlags[512], false);
+	Common::fill(&_autoNotes[0], &_autoNotes[128], false);
+	Common::fill(&_quests[0], &_quests[64], false);
+	Common::fill(&_questItems[0], &_questItems[85], 0);
+
+	for (int i = 0; i < TOTAL_CHARACTERS; ++i)
+		Common::fill(&_characterFlags[i][0], &_characterFlags[i][24], false);
+}
+
+void Party::synchronize(Common::Serializer &s) {
+	byte dummy[30];
+	Common::fill(&dummy[0], &dummy[30], 0);
+
+	s.syncAsByte(_partyCount);
+	s.syncAsByte(_realPartyCount);
+	for (int i = 0; i < 8; ++i)
+		s.syncAsByte(_partyMembers[i]);
+	s.syncAsByte(_mazeDirection);
+	s.syncAsByte(_mazePosition.x);
+	s.syncAsByte(_mazePosition.y);
+	s.syncAsByte(_mazeId);
+
+	// Game configuration flags not used in this implementation
+	s.syncBytes(dummy, 3);
+
+	s.syncAsByte(_priorMazeId);
+	s.syncAsByte(_levitateActive);
+	s.syncAsByte(_automapOn);
+	s.syncAsByte(_wizardEyeActive);
+	s.syncAsByte(_clairvoyanceActive);
+	s.syncAsByte(_walkOnWaterActive);
+	s.syncAsByte(_blessedActive);
+	s.syncAsByte(_powerShieldActive);
+	s.syncAsByte(_holyBonusActive);
+	s.syncAsByte(_heroismActive);
+	s.syncAsByte(_difficulty);
+
+	for (int i = 0; i < ITEMS_COUNT; ++i)
+		_blacksmithWeapons[i].synchronize(s);
+	for (int i = 0; i < ITEMS_COUNT; ++i)
+		_blacksmithArmor[i].synchronize(s);
+	for (int i = 0; i < ITEMS_COUNT; ++i)
+		_blacksmithAccessories[i].synchronize(s);
+	for (int i = 0; i < ITEMS_COUNT; ++i)
+		_blacksmithMisc[i].synchronize(s);
+
+	s.syncAsUint16LE(_cloudsEnd);
+	s.syncAsUint16LE(_darkSideEnd);
+	s.syncAsUint16LE(_worldEnd);
+	s.syncAsUint16LE(hour_maybe);
+	s.syncAsUint16LE(_day);
+	s.syncAsUint16LE(_year);
+	s.syncAsUint16LE(_minutes);
+	s.syncAsUint16LE(_food);
+	s.syncAsUint16LE(_lightCount);
+	s.syncAsUint16LE(_torchCount);
+	s.syncAsUint16LE(_fireResistence);
+	s.syncAsUint16LE(_electricityResistence);
+	s.syncAsUint16LE(_coldResistence);
+	s.syncAsUint16LE(_poisonResistence);
+	s.syncAsUint16LE(_deathCount);
+	s.syncAsUint16LE(_winCount);
+	s.syncAsUint16LE(_lossCount);
+	s.syncAsUint32LE(_gold);
+	s.syncAsUint32LE(_gems);
+	s.syncAsUint32LE(_bankGold);
+	s.syncAsUint32LE(_bankGems);
+	s.syncAsUint32LE(_totalTime);
+	s.syncAsByte(_rested);
+	SavesManager::syncBitFlags(s, &_gameFlags[0], &_gameFlags[512]);
+	SavesManager::syncBitFlags(s, &_autoNotes[0], &_autoNotes[128]);
+	SavesManager::syncBitFlags(s, &_quests[0], &_quests[64]);
+
+	for (int i = 0; i < 85; ++i)
+		s.syncAsByte(_questItems[i]);
+
+	for (int i = 0; i < ITEMS_COUNT; ++i)
+		_blacksmithWeapons2[i].synchronize(s);
+	for (int i = 0; i < ITEMS_COUNT; ++i)
+		_blacksmithArmor2[i].synchronize(s);
+	for (int i = 0; i < ITEMS_COUNT; ++i)
+		_blacksmithAccessories2[i].synchronize(s);
+	for (int i = 0; i < ITEMS_COUNT; ++i)
+		_blacksmithMisc2[i].synchronize(s);
+
+	for (int i = 0; i < TOTAL_CHARACTERS; ++i)
+		SavesManager::syncBitFlags(s, &_characterFlags[i][0], &_characterFlags[i][24]);
+	s.syncBytes(&dummy[0], 30);
+}
+
+bool Party::checkSkill(Skill skillId) {
+	uint total = 0;
+	for (uint i = 0; i < _activeParty.size(); ++i) {
+		if (_activeParty[i]->_skills[skillId]) {
+			++total;
+
+			switch (skillId) {
+			case MOUNTAINEER:
+			case PATHFINDER:
+				// At least two characters need skill for check to return true
+				if (total == 2)
+					return true;
+				break;
+			case CRUSADER:
+			case SWIMMING:
+				// Entire party must have skill for check to return true
+				if (total == _activeParty.size())
+					return true;
+				break;
+			default:
+				// All other skills only need to have a single player having it
+				return true;
+			}
+		}
+	}
+}
+
 } // End of namespace Xeen
diff --git a/engines/xeen/party.h b/engines/xeen/party.h
index a42fe6e..d521537 100644
--- a/engines/xeen/party.h
+++ b/engines/xeen/party.h
@@ -50,7 +50,7 @@ enum Skill { THIEVERY = 0, ARMS_MASTER = 1, ASTROLOGER = 2, BODYBUILDER = 3,
 	SPOT_DOORS = 16, DANGER_SENSE = 17
 };
 
-enum ConditionType { CURSED = 0, HEARTBROKEN = 1, WEAK = 2, POISONED = 3,
+enum ConditionType { CURSED = 0, HEART_BROKEN = 1, WEAK = 2, POISONED = 3,
 	DISEASED = 4, INSANE = 5, IN_LOVE = 6, DRUNK = 7, SLEEP = 8, 
 	DEPRESSED = 9, CONFUSED = 10, PARALYZED = 11
 };
@@ -62,67 +62,6 @@ enum ConditionType { CURSED = 0, HEARTBROKEN = 1, WEAK = 2, POISONED = 3,
 
 class XeenEngine;
 
-class Party {
-public:
-	int _partyCount;
-	int _realPartyCount;
-	int _partyMembers[8];
-	Direction _mazeDirection;
-	Common::Point _mazePosition;
-	int _mazeId;
-	int _priorMazeId;
-	bool _levitateActive;
-	bool _automapOn;
-	bool _wizardEyeActive;
-	bool _clairvoyanceActive;
-	bool _walkOnWaterActive;
-	bool _blessedActive;
-	bool _powerShieldActive;
-	bool _holyBonusActive;
-	bool _heroismActive;
-	Difficulty _difficulty;
-	XeenItem _blacksmithWeapons[ITEMS_COUNT];
-	XeenItem _blacksmithArmor[ITEMS_COUNT];
-	XeenItem _blacksmithAccessories[ITEMS_COUNT];
-	XeenItem _blacksmithMisc[ITEMS_COUNT];
-	bool _cloudsEnd;
-	bool _darkSideEnd;
-	bool _worldEnd;
-	int hour_maybe;
-	int _day;
-	int _year;
-	int _minutes;
-	int _food;
-	int _lightCount;
-	int _torchCount;
-	int _fireResistence;
-	int _electricityResistence;
-	int _coldResistence;
-	int _poisonResistence;
-	int _deathCount;
-	int _winCount;
-	int _lossCount;
-	int _gold;
-	int _gems;
-	int _bankGold;
-	int _bankGems;
-	int _totalTime;
-	bool _rested;
-	bool _gameFlags[512];
-	bool _autoNotes[128];
-	bool _quests[64];
-	int _questItems[85];
-	XeenItem _blacksmithWeapons2[ITEMS_COUNT];
-	XeenItem _blacksmithArmor2[ITEMS_COUNT];
-	XeenItem _blacksmithAccessories2[ITEMS_COUNT];
-	XeenItem _blacksmithMisc2[ITEMS_COUNT];
-	bool _characterFlags[30][24];
-public:
-	Party();
-
-	void synchronize(Common::Serializer &s);
-};
-
 class AttributePair {
 public:	
 	int _permanent;
@@ -213,6 +152,71 @@ public:
 	void synchronize(Common::Serializer &s);
 };
 
+class Party {
+public:
+	int _partyCount;
+	int _realPartyCount;
+	int _partyMembers[8];
+	Direction _mazeDirection;
+	Common::Point _mazePosition;
+	int _mazeId;
+	int _priorMazeId;
+	bool _levitateActive;
+	bool _automapOn;
+	bool _wizardEyeActive;
+	bool _clairvoyanceActive;
+	bool _walkOnWaterActive;
+	bool _blessedActive;
+	bool _powerShieldActive;
+	bool _holyBonusActive;
+	bool _heroismActive;
+	Difficulty _difficulty;
+	XeenItem _blacksmithWeapons[ITEMS_COUNT];
+	XeenItem _blacksmithArmor[ITEMS_COUNT];
+	XeenItem _blacksmithAccessories[ITEMS_COUNT];
+	XeenItem _blacksmithMisc[ITEMS_COUNT];
+	bool _cloudsEnd;
+	bool _darkSideEnd;
+	bool _worldEnd;
+	int hour_maybe;
+	int _day;
+	int _year;
+	int _minutes;
+	int _food;
+	int _lightCount;
+	int _torchCount;
+	int _fireResistence;
+	int _electricityResistence;
+	int _coldResistence;
+	int _poisonResistence;
+	int _deathCount;
+	int _winCount;
+	int _lossCount;
+	int _gold;
+	int _gems;
+	int _bankGold;
+	int _bankGems;
+	int _totalTime;
+	bool _rested;
+	bool _gameFlags[512];
+	bool _autoNotes[128];
+	bool _quests[64];
+	int _questItems[85];
+	XeenItem _blacksmithWeapons2[ITEMS_COUNT];
+	XeenItem _blacksmithArmor2[ITEMS_COUNT];
+	XeenItem _blacksmithAccessories2[ITEMS_COUNT];
+	XeenItem _blacksmithMisc2[ITEMS_COUNT];
+	bool _characterFlags[30][24];
+public:
+	Common::Array<PlayerStruct *> _activeParty;
+public:
+	Party();
+
+	void synchronize(Common::Serializer &s);
+
+	bool checkSkill(Skill skillId);
+};
+
 } // End of namespace Xeen
 
 #endif	/* XEEN_PARTY_H */
diff --git a/engines/xeen/xeen.cpp b/engines/xeen/xeen.cpp
index a46526e..315e517 100644
--- a/engines/xeen/xeen.cpp
+++ b/engines/xeen/xeen.cpp
@@ -41,7 +41,6 @@ XeenEngine::XeenEngine(OSystem *syst, const XeenGameDescription *gameDesc)
 	_screen = nullptr;
 	_sound = nullptr;
 	_eventData = nullptr;
-	Common::fill(&_activeRoster[0], &_activeRoster[MAX_ACTIVE_PARTY], nullptr);
 	Common::fill(&_partyFaces[0], &_partyFaces[MAX_ACTIVE_PARTY], nullptr);
 	_isEarlyGame = false;
 	_loadDarkSide = 1;
@@ -265,9 +264,9 @@ void XeenEngine::setupUI(bool soundPlayed) {
 	_spellFxSprites.load("spellfx.icn");
 
 	// Get mappings to the active characters in the party
-	Common::fill(&_activeRoster[0], &_activeRoster[MAX_ACTIVE_PARTY], nullptr);
+	_party._activeParty.resize(_party._partyCount);
 	for (int i = 0; i < _party._partyCount; ++i) {
-		_activeRoster[i] = &_roster[_party._partyMembers[i]];
+		_party._activeParty[i] = &_roster[_party._partyMembers[i]];
 	}
 
 	_isEarlyGame = _party._minutes >= 300;
@@ -342,13 +341,13 @@ void XeenEngine::assembleBorder() {
 
 	// Draw UI element to indicate whether can spot hidden doors
 	_borderSprites.draw(*_screen,
-		(_spotDoorsAllowed && checkSkill(SPOT_DOORS)) ? _spotDoorsUIFrame + 28 : 28,
+		(_spotDoorsAllowed && _party.checkSkill(SPOT_DOORS)) ? _spotDoorsUIFrame + 28 : 28,
 		Common::Point(194, 91));
 	_spotDoorsUIFrame = (_spotDoorsUIFrame + 1) % 12;
 
 	// Draw UI element to indicate whether can sense danger
 	_borderSprites.draw(*_screen,
-		(_dangerSenseAllowed && checkSkill(DANGER_SENSE)) ? _spotDoorsUIFrame + 40 : 40,
+		(_dangerSenseAllowed && _party.checkSkill(DANGER_SENSE)) ? _spotDoorsUIFrame + 40 : 40,
 		Common::Point(107, 9));
 	_dangerSenseUIFrame = (_dangerSenseUIFrame + 1) % 12;
 
@@ -356,31 +355,4 @@ void XeenEngine::assembleBorder() {
 	// TODO
 }
 
-bool XeenEngine::checkSkill(Skill skillId) {
-	int total = 0;
-	for (int i = 0; i < _party._partyCount; ++i) {
-		if (_activeRoster[i]->_skills[skillId]) {
-			++total;
-
-			switch (skillId) {
-			case MOUNTAINEER:
-			case PATHFINDER:
-				// At least two characters need skill for check to return true
-				if (total == 2)
-					return true;
-				break;
-			case CRUSADER:
-			case SWIMMING:
-				// Entire party must have skill for check to return true
-				if (total == _party._partyCount)
-					return true;
-				break;
-			default:
-				// All other skills only need to have a single player having it
-				return true;
-			}
-		}
-	}
-}
-
 } // End of namespace Xeen
diff --git a/engines/xeen/xeen.h b/engines/xeen/xeen.h
index b6ca766..f63f73d 100644
--- a/engines/xeen/xeen.h
+++ b/engines/xeen/xeen.h
@@ -108,8 +108,6 @@ private:
 	void setupGameBackground();
 
 	void assembleBorder();
-
-	bool checkSkill(Skill skillId);
 protected:
 	/**
 	* Play the game
@@ -143,7 +141,6 @@ public:
 	Common::SeekableReadStream *_eventData;
 	Roster _roster;
 	Party _party;
-	PlayerStruct *_activeRoster[MAX_ACTIVE_PARTY];
 public:
 	XeenEngine(OSystem *syst, const XeenGameDescription *gameDesc);
 	virtual ~XeenEngine();


Commit: 166676462ae3ed6ddbe186504cf7ecb5f2e55703
    https://github.com/scummvm/scummvm/commit/166676462ae3ed6ddbe186504cf7ecb5f2e55703
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-01-02T16:54:59-10:00

Commit Message:
XEEN: Completed assembleGameBorder method

Changed paths:
    engines/xeen/resources.cpp
    engines/xeen/resources.h
    engines/xeen/screen.h
    engines/xeen/xeen.cpp
    engines/xeen/xeen.h



diff --git a/engines/xeen/resources.cpp b/engines/xeen/resources.cpp
index de0804d..d7d3fcc 100644
--- a/engines/xeen/resources.cpp
+++ b/engines/xeen/resources.cpp
@@ -232,4 +232,6 @@ const byte TEXT_COLORS[40][4] = {
 	{ 0x00, 0xDB, 0xDB, 0xDB },
 };
 
+const char *DIRECTION_TEXT[4] = { "NORTH", "EAST", "SOUTH", "WEST" };
+
 } // End of namespace Xeen
diff --git a/engines/xeen/resources.h b/engines/xeen/resources.h
index d24b1fe..cf4207b 100644
--- a/engines/xeen/resources.h
+++ b/engines/xeen/resources.h
@@ -36,6 +36,8 @@ extern const byte SYMBOLS[20][64];
 
 extern const byte TEXT_COLORS[40][4];
 
+extern const char *DIRECTION_TEXT[4];
+
 } // End of namespace Xeen
 
 #endif	/* XEEN_RESOURCES_H */
diff --git a/engines/xeen/screen.h b/engines/xeen/screen.h
index 0f16934..d62191e 100644
--- a/engines/xeen/screen.h
+++ b/engines/xeen/screen.h
@@ -50,10 +50,11 @@ private:
 	int _border;
 	int _xLo, _xHi;
 	int _ycL, _ycH;
-	bool _enabled;
 
 	void open2();
 public:
+	bool _enabled;
+public:
 	virtual void addDirtyRect(const Common::Rect &r);
 public:
 	Window();
diff --git a/engines/xeen/xeen.cpp b/engines/xeen/xeen.cpp
index 315e517..ec98a5f 100644
--- a/engines/xeen/xeen.cpp
+++ b/engines/xeen/xeen.cpp
@@ -30,6 +30,7 @@
 #include "xeen/xeen.h"
 #include "xeen/dialogs_options.h"
 #include "xeen/files.h"
+#include "xeen/resources.h"
 
 namespace Xeen {
 
@@ -50,6 +51,15 @@ XeenEngine::XeenEngine(OSystem *syst, const XeenGameDescription *gameDesc)
 	_spotDoorsAllowed = false;
 	_dangerSenseUIFrame = 0;
 	_dangerSenseAllowed = false;
+	_face1UIFrame = 0;
+	_face1State = 0;
+	_face2UIFrame = 0;
+	_face2State = 0;
+	_blessedUIFrame = 0;
+	_powerShieldUIFrame = 0;
+	_holyBonusUIFrame = 0;
+	_heroismUIFrame = 0;
+	_noDirectionSense = false;
 }
 
 XeenEngine::~XeenEngine() {
@@ -262,6 +272,8 @@ void XeenEngine::setupUI(bool soundPlayed) {
 	_globalSprites.load("global.icn");
 	_borderSprites.load("border.icn");
 	_spellFxSprites.load("spellfx.icn");
+	_fecpSprites.load("fecp.brd");
+	_blessSprites.load("bless.icn");
 
 	// Get mappings to the active characters in the party
 	_party._activeParty.resize(_party._partyCount);
@@ -326,10 +338,10 @@ void XeenEngine::loadCharIcons(int numChars) {
 
 void XeenEngine::setupGameBackground() {
 	_screen->loadBackground("back.raw");
-	assembleBorder();
+	assembleGameBorder();
 }
 
-void XeenEngine::assembleBorder() {
+void XeenEngine::assembleGameBorder() {
 	Window &gameWindow = _screen->_windows[28];
 
 	// Draw the outer frame
@@ -351,8 +363,89 @@ void XeenEngine::assembleBorder() {
 		Common::Point(107, 9));
 	_dangerSenseUIFrame = (_dangerSenseUIFrame + 1) % 12;
 
+	// Handle the face UI elements for indicating clairvoyance status
+	_face1UIFrame = (_face1UIFrame + 1) % 4;
+	if (_face1State == 0)
+		_face1UIFrame += 4;
+	else if (_face1State == 2)
+		_face1UIFrame = 0;
+
+	_face2UIFrame = (_face2UIFrame + 1) % 4 + 12;
+	if (_face2State == 0)
+		_face2UIFrame += 252;
+	else if (_face2State == 2)
+		_face2UIFrame = 0;
+
+	if (!_party._clairvoyanceActive) {
+		_face1UIFrame = 0;
+		_face2UIFrame = 8;
+	}
 
-	// TODO
+	_borderSprites.draw(*_screen, _face1UIFrame, Common::Point(0, 32));
+	_borderSprites.draw(*_screen,
+		_screen->_windows[10]._enabled || _screen->_windows[2]._enabled ?
+		52 : _face2UIFrame,
+		Common::Point(215, 32));
+
+	// Draw resistence indicators
+	if (!_screen->_windows[10]._enabled && !_screen->_windows[2]._enabled
+			&& _screen->_windows[38]._enabled) {
+		_fecpSprites.draw(*_screen, _party._fireResistence ? 1 : 0,
+			Common::Point(2, 2));
+		_fecpSprites.draw(*_screen, _party._electricityResistence ? 3 : 2,
+			Common::Point(219, 2));
+		_fecpSprites.draw(*_screen, _party._coldResistence ? 5 : 4,
+			Common::Point(2, 134));
+		_fecpSprites.draw(*_screen, _party._poisonResistence ? 7 : 6,
+			Common::Point(219, 134));
+	} else {
+		_fecpSprites.draw(*_screen, _party._fireResistence ? 9 : 8,
+			Common::Point(8, 8));
+		_fecpSprites.draw(*_screen, _party._electricityResistence ? 10 : 11,
+			Common::Point(219, 8));
+		_fecpSprites.draw(*_screen, _party._coldResistence ? 12 : 13,
+			Common::Point(8, 134));
+		_fecpSprites.draw(*_screen, _party._poisonResistence ? 14 : 15,
+			Common::Point(219, 134));
+	}
+
+	// Draw UI element for blessed
+	_blessSprites.draw(*_screen, 16, Common::Point(33, 137));
+	if (_party._blessedActive) {
+		_blessedUIFrame = (_blessedUIFrame + 1) % 4;
+		_blessSprites.draw(*_screen, _blessedUIFrame, Common::Point(33, 137));
+	}
+
+	// Draw UI element for power shield
+	if (_party._powerShieldActive) {
+		_powerShieldUIFrame = (_powerShieldUIFrame + 1) % 4;
+		_blessSprites.draw(*_screen, _powerShieldUIFrame + 4,
+			Common::Point(55, 137));
+	}
+
+	// Draw UI element for holy bonus
+	if (_party._holyBonusActive) {
+		_holyBonusUIFrame = (_holyBonusUIFrame + 1) % 4;
+		_blessSprites.draw(*_screen, _holyBonusUIFrame + 8, Common::Point(160, 137));
+	}
+
+	// Draw UI element for heroism
+	if (_party._heroismActive) {
+		_heroismUIFrame = (_heroismUIFrame + 1) % 4;
+		_blessSprites.draw(*_screen, _heroismUIFrame + 12, Common::Point(182, 137));
+	}
+
+	// Draw direction character if direction sense is active
+	if (_party.checkSkill(DIRECTION_SENSE) && !_noDirectionSense) {
+		const char *dirText = DIRECTION_TEXT[_party._mazeDirection];
+		Common::String msg = Common::String::format(
+			"\002""08\003""c\013""139\011""116%c\014""d\001", *dirText);
+		_screen->_windows[0].writeString(msg);
+	}
+
+	// Draw view frame
+	if (_screen->_windows[12]._enabled)
+		_screen->_windows[12].frame();
 }
 
 } // End of namespace Xeen
diff --git a/engines/xeen/xeen.h b/engines/xeen/xeen.h
index f63f73d..c175048 100644
--- a/engines/xeen/xeen.h
+++ b/engines/xeen/xeen.h
@@ -90,12 +90,23 @@ private:
 	SpriteResource _globalSprites;
 	SpriteResource _borderSprites;
 	SpriteResource _spellFxSprites;
+	SpriteResource _fecpSprites;
+	SpriteResource _blessSprites;
 	bool _buttonsLoaded;
 	int _batUIFrame;
 	int _spotDoorsUIFrame;
 	bool _spotDoorsAllowed;
 	int _dangerSenseUIFrame;
 	bool _dangerSenseAllowed;
+	int _face1UIFrame;
+	bool _face1State;
+	int _face2UIFrame;
+	bool _face2State;
+	int _blessedUIFrame;
+	int _powerShieldUIFrame;
+	int _holyBonusUIFrame;
+	int _heroismUIFrame;
+	bool _noDirectionSense;
 
 	void showIntro();
 
@@ -107,7 +118,7 @@ private:
 
 	void setupGameBackground();
 
-	void assembleBorder();
+	void assembleGameBorder();
 protected:
 	/**
 	* Play the game


Commit: 97cd5a7e6961be52d545e3c131a85cd90c582441
    https://github.com/scummvm/scummvm/commit/97cd5a7e6961be52d545e3c131a85cd90c582441
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-01-03T03:19:14-10:00

Commit Message:
XEEN: Split game interface code into it's own class

Changed paths:
  A engines/xeen/interface.cpp
  A engines/xeen/interface.h
    engines/xeen/module.mk
    engines/xeen/xeen.cpp
    engines/xeen/xeen.h



diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp
new file mode 100644
index 0000000..cdb9204
--- /dev/null
+++ b/engines/xeen/interface.cpp
@@ -0,0 +1,231 @@
+/* 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 "xeen/interface.h"
+#include "xeen/resources.h"
+#include "xeen/xeen.h"
+
+namespace Xeen {
+
+Interface::Interface(XeenEngine *vm) : ButtonContainer(), _vm(vm) {
+	Common::fill(&_partyFaces[0], &_partyFaces[MAX_ACTIVE_PARTY], nullptr);
+	_batUIFrame = 0;
+	_spotDoorsUIFrame = 0;
+	_dangerSenseUIFrame = 0;
+	_face1UIFrame = 0;
+	_face2UIFrame = 0;
+	_blessedUIFrame = 0;
+	_powerShieldUIFrame = 0;
+	_holyBonusUIFrame = 0;
+	_heroismUIFrame = 0;
+	_isEarlyGame = false;
+	_buttonsLoaded = false;
+
+	loadSprites();
+}
+
+void Interface::loadSprites() {
+	_globalSprites.load("global.icn");
+	_borderSprites.load("border.icn");
+	_spellFxSprites.load("spellfx.icn");
+	_fecpSprites.load("fecp.brd");
+	_blessSprites.load("bless.icn");
+}
+
+void Interface::setup(bool soundPlayed) {
+	SpriteResource uiSprites("inn.icn");
+
+	// 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]];
+	}
+
+	_isEarlyGame = _vm->_party._minutes >= 300;
+
+	if (_vm->_party._mazeId == 0) {
+		if (!soundPlayed) {
+			warning("TODO: loadSound?");
+		}
+
+		if (!_partyFaces[0]) {
+			// Xeen only uses 24 of possible 30 character slots
+			loadCharIcons(XEEN_TOTAL_CHARACTERS);
+
+			for (int i = 0; i < _vm->_party._partyCount; ++i)
+				_partyFaces[i] = &_charFaces[_vm->_party._partyMembers[i]];
+		}
+
+		_vm->_mode = MODE_1;
+		Common::Array<int> xeenSideChars;
+
+		// Build up a list of characters on the same Xeen side being loaded
+		for (int i = 0; i < XEEN_TOTAL_CHARACTERS; ++i) {
+			PlayerStruct &player = _vm->_roster[i];
+			if (player._name.empty() || player._xeenSide != _vm->_loadDarkSide)
+				continue;
+
+			xeenSideChars.push_back(i);
+		}
+
+		// Add in buttons for the UI
+		_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);
+
+		setupBackground();
+	}
+}
+
+void Interface::loadCharIcons(int numChars) {
+	for (int i = 0; i < numChars; ++i) {
+		// Load new character resource
+		Common::String name = Common::String::format("char%02d.fac", i);
+		_charFaces[i].load(name);
+	}
+
+	_dseFace.load("dse.fac");
+}
+
+void Interface::setupBackground() {
+	_vm->_screen->loadBackground("back.raw");
+	assembleBorder();
+}
+
+void Interface::assembleBorder() {
+	Screen &screen = *_vm->_screen;
+	Window &gameWindow = screen._windows[28];
+
+	// Draw the outer frame
+	_globalSprites.draw(gameWindow, 0);
+
+	// Draw the animating bat character used to show when levitate is active
+	_borderSprites.draw(screen, _vm->_party._levitateActive ? _batUIFrame + 16 : 16);
+	_batUIFrame = (_batUIFrame + 1) % 12;
+
+	// Draw UI element to indicate whether can spot hidden doors
+	_borderSprites.draw(screen,
+		(_vm->_spotDoorsAllowed && _vm->_party.checkSkill(SPOT_DOORS)) ? _spotDoorsUIFrame + 28 : 28,
+		Common::Point(194, 91));
+	_spotDoorsUIFrame = (_spotDoorsUIFrame + 1) % 12;
+
+	// Draw UI element to indicate whether can sense danger
+	_borderSprites.draw(screen,
+		(_vm->_dangerSenseAllowed && _vm->_party.checkSkill(DANGER_SENSE)) ? _spotDoorsUIFrame + 40 : 40,
+		Common::Point(107, 9));
+	_dangerSenseUIFrame = (_dangerSenseUIFrame + 1) % 12;
+
+	// Handle the face UI elements for indicating clairvoyance status
+	_face1UIFrame = (_face1UIFrame + 1) % 4;
+	if (_vm->_face1State == 0)
+		_face1UIFrame += 4;
+	else if (_vm->_face1State == 2)
+		_face1UIFrame = 0;
+
+	_face2UIFrame = (_face2UIFrame + 1) % 4 + 12;
+	if (_vm->_face2State == 0)
+		_face2UIFrame += 252;
+	else if (_vm->_face2State == 2)
+		_face2UIFrame = 0;
+
+	if (!_vm->_party._clairvoyanceActive) {
+		_face1UIFrame = 0;
+		_face2UIFrame = 8;
+	}
+
+	_borderSprites.draw(screen, _face1UIFrame, Common::Point(0, 32));
+	_borderSprites.draw(screen,
+		screen._windows[10]._enabled || screen._windows[2]._enabled ?
+		52 : _face2UIFrame,
+		Common::Point(215, 32));
+
+	// Draw resistence indicators
+	if (!screen._windows[10]._enabled && !screen._windows[2]._enabled
+		&& screen._windows[38]._enabled) {
+		_fecpSprites.draw(screen, _vm->_party._fireResistence ? 1 : 0,
+			Common::Point(2, 2));
+		_fecpSprites.draw(screen, _vm->_party._electricityResistence ? 3 : 2,
+			Common::Point(219, 2));
+		_fecpSprites.draw(screen, _vm->_party._coldResistence ? 5 : 4,
+			Common::Point(2, 134));
+		_fecpSprites.draw(screen, _vm->_party._poisonResistence ? 7 : 6,
+			Common::Point(219, 134));
+	} else {
+		_fecpSprites.draw(screen, _vm->_party._fireResistence ? 9 : 8,
+			Common::Point(8, 8));
+		_fecpSprites.draw(screen, _vm->_party._electricityResistence ? 10 : 11,
+			Common::Point(219, 8));
+		_fecpSprites.draw(screen, _vm->_party._coldResistence ? 12 : 13,
+			Common::Point(8, 134));
+		_fecpSprites.draw(screen, _vm->_party._poisonResistence ? 14 : 15,
+			Common::Point(219, 134));
+	}
+
+	// Draw UI element for blessed
+	_blessSprites.draw(screen, 16, Common::Point(33, 137));
+	if (_vm->_party._blessedActive) {
+		_blessedUIFrame = (_blessedUIFrame + 1) % 4;
+		_blessSprites.draw(screen, _blessedUIFrame, Common::Point(33, 137));
+	}
+
+	// Draw UI element for power shield
+	if (_vm->_party._powerShieldActive) {
+		_powerShieldUIFrame = (_powerShieldUIFrame + 1) % 4;
+		_blessSprites.draw(screen, _powerShieldUIFrame + 4,
+			Common::Point(55, 137));
+	}
+
+	// Draw UI element for holy bonus
+	if (_vm->_party._holyBonusActive) {
+		_holyBonusUIFrame = (_holyBonusUIFrame + 1) % 4;
+		_blessSprites.draw(screen, _holyBonusUIFrame + 8, Common::Point(160, 137));
+	}
+
+	// Draw UI element for heroism
+	if (_vm->_party._heroismActive) {
+		_heroismUIFrame = (_heroismUIFrame + 1) % 4;
+		_blessSprites.draw(screen, _heroismUIFrame + 12, Common::Point(182, 137));
+	}
+
+	// Draw direction character if direction sense is active
+	if (_vm->_party.checkSkill(DIRECTION_SENSE) && !_vm->_noDirectionSense) {
+		const char *dirText = DIRECTION_TEXT[_vm->_party._mazeDirection];
+		Common::String msg = Common::String::format(
+			"\002""08\003""c\013""139\011""116%c\014""d\001", *dirText);
+		screen._windows[0].writeString(msg);
+	}
+
+	// Draw view frame
+	if (screen._windows[12]._enabled)
+		screen._windows[12].frame();
+}
+
+} // End of namespace Xeen
diff --git a/engines/xeen/interface.h b/engines/xeen/interface.h
new file mode 100644
index 0000000..565fe84
--- /dev/null
+++ b/engines/xeen/interface.h
@@ -0,0 +1,73 @@
+/* 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_INTERFACE_H
+#define XEEN_INTERFACE_H
+
+#include "common/scummsys.h"
+#include "xeen/dialogs.h"
+#include "xeen/party.h"
+
+namespace Xeen {
+
+class XeenEngine;
+
+class Interface: public ButtonContainer {
+private:
+	XeenEngine *_vm;
+	SpriteResource _dseFace;
+	SpriteResource _globalSprites;
+	SpriteResource _borderSprites;
+	SpriteResource _spellFxSprites;
+	SpriteResource _fecpSprites;
+	SpriteResource _blessSprites;
+	SpriteResource _charFaces[TOTAL_CHARACTERS];
+	SpriteResource *_partyFaces[MAX_ACTIVE_PARTY];
+
+	int _batUIFrame;
+	int _spotDoorsUIFrame;
+	int _dangerSenseUIFrame;
+	int _face1UIFrame;
+	int _face2UIFrame;
+	int _blessedUIFrame;
+	int _powerShieldUIFrame;
+	int _holyBonusUIFrame;
+	int _heroismUIFrame;
+	bool _isEarlyGame;
+	bool _buttonsLoaded;
+
+	void loadSprites();
+
+	void loadCharIcons(int numChars);
+
+	void assembleBorder();
+
+	void setupBackground();
+public:
+	Interface(XeenEngine *vm);
+
+	void setup(bool soundPlayed);
+};
+
+} // End of namespace Xeen
+
+#endif /* XEEN_INTERFACE_H */
diff --git a/engines/xeen/module.mk b/engines/xeen/module.mk
index 752608a..7f0caf7 100644
--- a/engines/xeen/module.mk
+++ b/engines/xeen/module.mk
@@ -11,6 +11,7 @@ MODULE_OBJS := \
 	events.o \
 	files.o \
 	font.o \
+	interface.o \
 	items.o \
 	party.o \
 	resdata.o \
diff --git a/engines/xeen/xeen.cpp b/engines/xeen/xeen.cpp
index ec98a5f..1574871 100644
--- a/engines/xeen/xeen.cpp
+++ b/engines/xeen/xeen.cpp
@@ -35,36 +35,26 @@
 namespace Xeen {
 
 XeenEngine::XeenEngine(OSystem *syst, const XeenGameDescription *gameDesc)
-		: Engine(syst), ButtonContainer(), _gameDescription(gameDesc), _randomSource("Xeen") {
+		: Engine(syst), _gameDescription(gameDesc), _randomSource("Xeen") {
 	_debugger = nullptr;
 	_events = nullptr;
+	_interface = nullptr;
 	_saves = nullptr;
 	_screen = nullptr;
 	_sound = nullptr;
 	_eventData = nullptr;
-	Common::fill(&_partyFaces[0], &_partyFaces[MAX_ACTIVE_PARTY], nullptr);
-	_isEarlyGame = false;
 	_loadDarkSide = 1;
-	_buttonsLoaded = false;
-	_batUIFrame = 0;
-	_spotDoorsUIFrame = 0;
 	_spotDoorsAllowed = false;
-	_dangerSenseUIFrame = 0;
 	_dangerSenseAllowed = false;
-	_face1UIFrame = 0;
 	_face1State = 0;
-	_face2UIFrame = 0;
 	_face2State = 0;
-	_blessedUIFrame = 0;
-	_powerShieldUIFrame = 0;
-	_holyBonusUIFrame = 0;
-	_heroismUIFrame = 0;
 	_noDirectionSense = false;
 }
 
 XeenEngine::~XeenEngine() {
 	delete _debugger;
 	delete _events;
+	delete _interface;
 	delete _saves;
 	delete _screen;
 	delete _sound;
@@ -82,6 +72,7 @@ void XeenEngine::initialize() {
 	FileManager::init(this);
 	_debugger = new Debugger(this);
 	_events = new EventsManager(this);
+	_interface = new Interface(this);
 	_saves = new SavesManager(this, _party, _roster);
 	_screen = new Screen(this);
 	_screen->setupWindows();
@@ -260,192 +251,7 @@ void XeenEngine::showMainMenu() {
 
 void XeenEngine::playGame() {
 	_saves->reset();
-	setupUI(true);
-}
-
-/*
- * Lots of stuff in this method.
- * TODO: Consider renaming method when better understood
- */
-void XeenEngine::setupUI(bool soundPlayed) {
-	SpriteResource uiSprites("inn.icn");
-	_globalSprites.load("global.icn");
-	_borderSprites.load("border.icn");
-	_spellFxSprites.load("spellfx.icn");
-	_fecpSprites.load("fecp.brd");
-	_blessSprites.load("bless.icn");
-
-	// Get mappings to the active characters in the party
-	_party._activeParty.resize(_party._partyCount);
-	for (int i = 0; i < _party._partyCount; ++i) {
-		_party._activeParty[i] = &_roster[_party._partyMembers[i]];
-	}
-
-	_isEarlyGame = _party._minutes >= 300;
-	
-	if (_party._mazeId == 0) {
-		if (!soundPlayed) {
-			warning("TODO: loadSound?");
-		}
-
-		if (!_partyFaces[0]) {
-			// Xeen only uses 24 of possible 30 character slots
-			loadCharIcons(XEEN_TOTAL_CHARACTERS);
-
-			for (int i = 0; i < _party._partyCount; ++i)
-				_partyFaces[i] = &_charFaces[_party._partyMembers[i]];
-		}
-
-		_mode = MODE_1;
-		Common::Array<int> xeenSideChars;
-
-		// Build up a list of characters on the same Xeen side being loaded
-		for (int i = 0; i < XEEN_TOTAL_CHARACTERS; ++i) {
-			PlayerStruct &player = _roster[i];
-			if (player._name.empty() || player._xeenSide != _loadDarkSide)
-				continue;
-
-			xeenSideChars.push_back(i);
-		}
-
-		// Add in buttons for the UI
-		_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);
-
-		setupGameBackground();
-	}
-}
-
-void XeenEngine::loadCharIcons(int numChars) {
-	for (int i = 0; i < numChars; ++i) {
-		// Load new character resource
-		Common::String name = Common::String::format("char%02d.fac", i);
-		_charFaces[i].load(name);
-	}
-
-	_dseFace.load("dse.fac");
-}
-
-void XeenEngine::setupGameBackground() {
-	_screen->loadBackground("back.raw");
-	assembleGameBorder();
-}
-
-void XeenEngine::assembleGameBorder() {
-	Window &gameWindow = _screen->_windows[28];
-
-	// Draw the outer frame
-	_globalSprites.draw(gameWindow, 0);
-	
-	// Draw the animating bat character used to show when levitate is active
-	_borderSprites.draw(*_screen, _party._levitateActive ? _batUIFrame + 16 : 16);
-	_batUIFrame = (_batUIFrame + 1) % 12;
-
-	// Draw UI element to indicate whether can spot hidden doors
-	_borderSprites.draw(*_screen,
-		(_spotDoorsAllowed && _party.checkSkill(SPOT_DOORS)) ? _spotDoorsUIFrame + 28 : 28,
-		Common::Point(194, 91));
-	_spotDoorsUIFrame = (_spotDoorsUIFrame + 1) % 12;
-
-	// Draw UI element to indicate whether can sense danger
-	_borderSprites.draw(*_screen,
-		(_dangerSenseAllowed && _party.checkSkill(DANGER_SENSE)) ? _spotDoorsUIFrame + 40 : 40,
-		Common::Point(107, 9));
-	_dangerSenseUIFrame = (_dangerSenseUIFrame + 1) % 12;
-
-	// Handle the face UI elements for indicating clairvoyance status
-	_face1UIFrame = (_face1UIFrame + 1) % 4;
-	if (_face1State == 0)
-		_face1UIFrame += 4;
-	else if (_face1State == 2)
-		_face1UIFrame = 0;
-
-	_face2UIFrame = (_face2UIFrame + 1) % 4 + 12;
-	if (_face2State == 0)
-		_face2UIFrame += 252;
-	else if (_face2State == 2)
-		_face2UIFrame = 0;
-
-	if (!_party._clairvoyanceActive) {
-		_face1UIFrame = 0;
-		_face2UIFrame = 8;
-	}
-
-	_borderSprites.draw(*_screen, _face1UIFrame, Common::Point(0, 32));
-	_borderSprites.draw(*_screen,
-		_screen->_windows[10]._enabled || _screen->_windows[2]._enabled ?
-		52 : _face2UIFrame,
-		Common::Point(215, 32));
-
-	// Draw resistence indicators
-	if (!_screen->_windows[10]._enabled && !_screen->_windows[2]._enabled
-			&& _screen->_windows[38]._enabled) {
-		_fecpSprites.draw(*_screen, _party._fireResistence ? 1 : 0,
-			Common::Point(2, 2));
-		_fecpSprites.draw(*_screen, _party._electricityResistence ? 3 : 2,
-			Common::Point(219, 2));
-		_fecpSprites.draw(*_screen, _party._coldResistence ? 5 : 4,
-			Common::Point(2, 134));
-		_fecpSprites.draw(*_screen, _party._poisonResistence ? 7 : 6,
-			Common::Point(219, 134));
-	} else {
-		_fecpSprites.draw(*_screen, _party._fireResistence ? 9 : 8,
-			Common::Point(8, 8));
-		_fecpSprites.draw(*_screen, _party._electricityResistence ? 10 : 11,
-			Common::Point(219, 8));
-		_fecpSprites.draw(*_screen, _party._coldResistence ? 12 : 13,
-			Common::Point(8, 134));
-		_fecpSprites.draw(*_screen, _party._poisonResistence ? 14 : 15,
-			Common::Point(219, 134));
-	}
-
-	// Draw UI element for blessed
-	_blessSprites.draw(*_screen, 16, Common::Point(33, 137));
-	if (_party._blessedActive) {
-		_blessedUIFrame = (_blessedUIFrame + 1) % 4;
-		_blessSprites.draw(*_screen, _blessedUIFrame, Common::Point(33, 137));
-	}
-
-	// Draw UI element for power shield
-	if (_party._powerShieldActive) {
-		_powerShieldUIFrame = (_powerShieldUIFrame + 1) % 4;
-		_blessSprites.draw(*_screen, _powerShieldUIFrame + 4,
-			Common::Point(55, 137));
-	}
-
-	// Draw UI element for holy bonus
-	if (_party._holyBonusActive) {
-		_holyBonusUIFrame = (_holyBonusUIFrame + 1) % 4;
-		_blessSprites.draw(*_screen, _holyBonusUIFrame + 8, Common::Point(160, 137));
-	}
-
-	// Draw UI element for heroism
-	if (_party._heroismActive) {
-		_heroismUIFrame = (_heroismUIFrame + 1) % 4;
-		_blessSprites.draw(*_screen, _heroismUIFrame + 12, Common::Point(182, 137));
-	}
-
-	// Draw direction character if direction sense is active
-	if (_party.checkSkill(DIRECTION_SENSE) && !_noDirectionSense) {
-		const char *dirText = DIRECTION_TEXT[_party._mazeDirection];
-		Common::String msg = Common::String::format(
-			"\002""08\003""c\013""139\011""116%c\014""d\001", *dirText);
-		_screen->_windows[0].writeString(msg);
-	}
-
-	// Draw view frame
-	if (_screen->_windows[12]._enabled)
-		_screen->_windows[12].frame();
+	_interface->setup(true);
 }
 
 } // End of namespace Xeen
diff --git a/engines/xeen/xeen.h b/engines/xeen/xeen.h
index c175048..a549c15 100644
--- a/engines/xeen/xeen.h
+++ b/engines/xeen/xeen.h
@@ -34,6 +34,7 @@
 #include "xeen/debugger.h"
 #include "xeen/dialogs.h"
 #include "xeen/events.h"
+#include "xeen/interface.h"
 #include "xeen/party.h"
 #include "xeen/saves.h"
 #include "xeen/screen.h"
@@ -77,48 +78,15 @@ struct XeenGameDescription;
 #define XEEN_SAVEGAME_VERSION 1
 #define GAME_FRAME_TIME 50
 
-class XeenEngine : public Engine, public ButtonContainer {
+class XeenEngine : public Engine {
 private:
 	const XeenGameDescription *_gameDescription;
 	Common::RandomSource _randomSource;
 	int _loadSaveSlot;
-	bool _isEarlyGame;
-	int _loadDarkSide;
-	SpriteResource _charFaces[TOTAL_CHARACTERS];
-	SpriteResource *_partyFaces[MAX_ACTIVE_PARTY];
-	SpriteResource _dseFace;
-	SpriteResource _globalSprites;
-	SpriteResource _borderSprites;
-	SpriteResource _spellFxSprites;
-	SpriteResource _fecpSprites;
-	SpriteResource _blessSprites;
-	bool _buttonsLoaded;
-	int _batUIFrame;
-	int _spotDoorsUIFrame;
-	bool _spotDoorsAllowed;
-	int _dangerSenseUIFrame;
-	bool _dangerSenseAllowed;
-	int _face1UIFrame;
-	bool _face1State;
-	int _face2UIFrame;
-	bool _face2State;
-	int _blessedUIFrame;
-	int _powerShieldUIFrame;
-	int _holyBonusUIFrame;
-	int _heroismUIFrame;
-	bool _noDirectionSense;
 
 	void showIntro();
 
 	void showMainMenu();
-
-	void setupUI(bool soundPlayed);
-
-	void loadCharIcons(int numChars);
-
-	void setupGameBackground();
-
-	void assembleGameBorder();
 protected:
 	/**
 	* Play the game
@@ -144,6 +112,7 @@ private:
 public:
 	Debugger *_debugger;
 	EventsManager *_events;
+	Interface *_interface;
 	SavesManager *_saves;
 	Screen *_screen;
 	SoundManager *_sound;
@@ -152,6 +121,12 @@ public:
 	Common::SeekableReadStream *_eventData;
 	Roster _roster;
 	Party _party;
+	int _loadDarkSide;
+	bool _spotDoorsAllowed;
+	bool _dangerSenseAllowed;
+	int _face1State;
+	int _face2State;
+	bool _noDirectionSense;
 public:
 	XeenEngine(OSystem *syst, const XeenGameDescription *gameDesc);
 	virtual ~XeenEngine();


Commit: f9316bf14107c3ac46bd8bb53da9665c3652c381
    https://github.com/scummvm/scummvm/commit/f9316bf14107c3ac46bd8bb53da9665c3652c381
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-01-03T19:08:30-05:00

Commit Message:
XEEN: Implemented charIconsPrint

Changed paths:
    engines/xeen/interface.cpp
    engines/xeen/interface.h
    engines/xeen/party.cpp
    engines/xeen/party.h
    engines/xeen/resources.cpp
    engines/xeen/resources.h
    engines/xeen/screen.cpp
    engines/xeen/screen.h
    engines/xeen/xeen.h



diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp
index cdb9204..3a07cec 100644
--- a/engines/xeen/interface.cpp
+++ b/engines/xeen/interface.cpp
@@ -39,6 +39,13 @@ Interface::Interface(XeenEngine *vm) : ButtonContainer(), _vm(vm) {
 	_heroismUIFrame = 0;
 	_isEarlyGame = false;
 	_buttonsLoaded = false;
+	_hiliteChar = -1;
+	Common::fill(&_combatCharIds[0], &_combatCharIds[8], 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();
 }
@@ -49,9 +56,12 @@ void Interface::loadSprites() {
 	_spellFxSprites.load("spellfx.icn");
 	_fecpSprites.load("fecp.brd");
 	_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");
 
 	// Get mappings to the active characters in the party
@@ -88,6 +98,7 @@ 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);
@@ -102,6 +113,11 @@ void Interface::setup(bool soundPlayed) {
 		addButton(Common::Rect(117, 59, 149, 81), 52, &uiSprites, false);
 
 		setupBackground();
+		screen._windows[11].open();
+		setupFaces(0, xeenSideChars, 0);
+		screen._windows[11].writeString(_interfaceText);
+
+		// TODO
 	}
 }
 
@@ -228,4 +244,103 @@ void Interface::assembleBorder() {
 		screen._windows[12].frame();
 }
 
+void Interface::setupFaces(int charIndex, Common::Array<int> xeenSideChars, int v3) {
+	Common::String playerNames[4];
+	Common::String playerRaces[4];
+	Common::String playerSex[4];
+	Common::String playerClass[4];
+	int posIndex;
+	int charId;
+
+	for (posIndex = 0; posIndex < 4; ++posIndex) {
+		int charId = xeenSideChars[charIndex];
+		bool isInParty = _vm->_party.isInParty(charId);
+
+		if (charId == 0xff) {
+			while ((int)_buttons.size() > (7 + posIndex))
+				_buttons.remove_at(_buttons.size() - 1);
+			break;
+		}
+
+		Common::Rect &b = _buttons[7 + posIndex]._bounds;
+		b.moveTo((posIndex & 1) ? 117 : 16, b.top);
+		PlayerStruct &ps = _vm->_roster[xeenSideChars[charIndex + posIndex]];
+		playerNames[posIndex] = isInParty ? IN_PARTY : ps._name;
+		playerRaces[posIndex] = RACE_NAMES[ps._race];
+		playerSex[posIndex] = SEX_NAMES[ps._sex];
+		playerClass[posIndex] = CLASS_NAMES[ps._class];
+	}
+
+	charIconsPrint(v3);
+
+	// Set up the sprite set to use for each face
+	charId = xeenSideChars[charIndex];
+	_faceDrawStructs[0]._sprites = (charId == 0xff) ? (SpriteResource *)nullptr : &_charFaces[charId];
+	charId = xeenSideChars[charIndex + 1];
+	_faceDrawStructs[1]._sprites = (charId == 0xff) ? (SpriteResource *)nullptr : &_charFaces[charId];
+	charId = xeenSideChars[charIndex + 2];
+	_faceDrawStructs[2]._sprites = (charId == 0xff) ? (SpriteResource *)nullptr : &_charFaces[charId];
+	charId = xeenSideChars[charIndex + 3];
+	_faceDrawStructs[3]._sprites = (charId == 0xff) ? (SpriteResource *)nullptr : &_charFaces[charId];
+
+	_interfaceText = Common::String::format(PARTY_DETAILS,
+		playerNames[0].c_str(), playerRaces[0].c_str(), playerSex[0].c_str(), playerClass[0].c_str(),
+		playerNames[1].c_str(), playerRaces[1].c_str(), playerSex[1].c_str(), playerClass[1].c_str(),
+		playerNames[2].c_str(), playerRaces[2].c_str(), playerSex[2].c_str(), playerClass[2].c_str(),
+		playerNames[3].c_str(), playerRaces[3].c_str(), playerSex[3].c_str(), playerClass[3].c_str()
+	);
+}
+
+void Interface::charIconsPrint(bool updateFlag) {
+	Screen &screen = *_vm->_screen;
+	bool stateFlag = _vm->_mode == MODE_2;
+	_restoreSprites.draw(screen, 0, Common::Point(8, 149));
+
+	// Handle drawing the party faces
+	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];
+		Condition charCondition = ps.findCondition();
+		int charFrame = FACE_CONDITION_FRAMES[charCondition];
+		
+		SpriteResource *sprites = (charFrame > 4 && !_charFaces[0].empty()) ?
+			&_dseFace : _partyFaces[charIndex];
+		if (charFrame > 4)
+			charFrame -= 5;
+
+		sprites->draw(screen, charFrame, Common::Point(CHAR_FACES_X[idx], 150));
+	}
+
+	if (!_hpSprites.empty()) {
+		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];
+
+			// Draw the Hp bar
+			int maxHp = ps.getMaxHp();
+			int frame;
+			if (ps._currentHp < 1)
+				frame = 4;
+			else if (ps._currentHp > maxHp)
+				frame = 3;
+			else if (ps._currentHp == maxHp)
+				frame = 0;
+			else if (ps._currentHp < (maxHp / 4))
+				frame = 2;
+			else
+				frame = 1;
+
+			_hpSprites.draw(screen, frame, Common::Point(HP_BARS_X[idx], 182));
+		}
+	}
+
+	if (_hiliteChar != -1)
+		_globalSprites.draw(screen, 8, Common::Point(CHAR_FACES_X[_hiliteChar] - 1, 149));
+
+	if (updateFlag)
+		screen._windows[33].update();
+}
+
 } // End of namespace Xeen
diff --git a/engines/xeen/interface.h b/engines/xeen/interface.h
index 565fe84..3ceb082 100644
--- a/engines/xeen/interface.h
+++ b/engines/xeen/interface.h
@@ -26,6 +26,7 @@
 #include "common/scummsys.h"
 #include "xeen/dialogs.h"
 #include "xeen/party.h"
+#include "xeen/screen.h"
 
 namespace Xeen {
 
@@ -40,8 +41,12 @@ private:
 	SpriteResource _spellFxSprites;
 	SpriteResource _fecpSprites;
 	SpriteResource _blessSprites;
+	SpriteResource _restoreSprites;
+	SpriteResource _hpSprites;
 	SpriteResource _charFaces[TOTAL_CHARACTERS];
 	SpriteResource *_partyFaces[MAX_ACTIVE_PARTY];
+	DrawStruct _faceDrawStructs[4];
+	int _combatCharIds[8];
 
 	int _batUIFrame;
 	int _spotDoorsUIFrame;
@@ -54,6 +59,8 @@ private:
 	int _heroismUIFrame;
 	bool _isEarlyGame;
 	bool _buttonsLoaded;
+	Common::String _interfaceText;
+	int _hiliteChar;
 
 	void loadSprites();
 
@@ -62,6 +69,10 @@ private:
 	void assembleBorder();
 
 	void setupBackground();
+
+	void setupFaces(int charIndex, Common::Array<int> xeenSideChars, int v3);
+
+	void charIconsPrint(bool updateFlag);
 public:
 	Interface(XeenEngine *vm);
 
diff --git a/engines/xeen/party.cpp b/engines/xeen/party.cpp
index 97b4a76..25366d5 100644
--- a/engines/xeen/party.cpp
+++ b/engines/xeen/party.cpp
@@ -40,46 +40,6 @@ void AttributePair::synchronize(Common::Serializer &s) {
 
 /*------------------------------------------------------------------------*/
 
-Conditions::Conditions() {
-	_cursed = 0;
-	_heartBroken = 0;
-	_weak = 0;
-	_poisoned = 0;
-	_diseased = 0;
-	_insane = 0;
-	_inLove = 0;
-	_drunk = 0;
-	_asleep = 0;
-	_depressed = 0;
-	_confused = 0;
-	_paralyzed = 0;
-	_unconscious = 0;
-	_dead = 0;
-	_stoned = 0;
-	_eradicated = 0;
-}
-
-void Conditions::synchronize(Common::Serializer &s) {
-	s.syncAsByte(_cursed);
-	s.syncAsByte(_heartBroken);
-	s.syncAsByte(_weak);
-	s.syncAsByte(_poisoned);
-	s.syncAsByte(_diseased);
-	s.syncAsByte(_insane);
-	s.syncAsByte(_inLove);
-	s.syncAsByte(_drunk);
-	s.syncAsByte(_asleep);
-	s.syncAsByte(_depressed);
-	s.syncAsByte(_confused);
-	s.syncAsByte(_paralyzed);
-	s.syncAsByte(_unconscious);
-	s.syncAsByte(_dead);
-	s.syncAsByte(_stoned);
-	s.syncAsByte(_eradicated);
-}
-
-/*------------------------------------------------------------------------*/
-
 PlayerStruct::PlayerStruct() {
 	_sex = MALE;
 	_race = HUMAN;
@@ -96,6 +56,7 @@ PlayerStruct::PlayerStruct() {
 	_currentSpell = 0;
 	_quickOption = 0;
 	_lloydSide = 0;
+	Common::fill(&_conditions[0], &_conditions[16], 0);
 	_townUnknown = 0;
 	_unknown2 = 0;
 	_currentHp = 0;
@@ -161,7 +122,8 @@ void PlayerStruct::synchronize(Common::Serializer &s) {
 	_energyResistence.synchronize(s);
 	_magicResistence.synchronize(s);
 	
-	_conditions.synchronize(s);
+	for (int i = 0; i < 16; ++i)
+		s.syncAsByte(_conditions[i]);
 
 	s.syncAsUint16LE(_townUnknown);
 	s.syncAsByte(_unknown2);
@@ -173,6 +135,26 @@ void PlayerStruct::synchronize(Common::Serializer &s) {
 	s.syncAsByte(_currentCombatSpell);
 }
 
+Condition PlayerStruct::findCondition() const {
+	for (int cond = ERADICATED; cond >= CURSED; --cond) {
+		if (_conditions[cond])
+			return (Condition)cond;
+	}
+
+	return NO_CONDITION;
+}
+
+int PlayerStruct::getYear(int partyYear, bool ignoreTemp) {
+	int year = MIN(partyYear - _ybDay, 254);
+
+	return ignoreTemp ? year : year + _tempAge;
+}
+
+int PlayerStruct::getMaxHp() {
+	warning("TODO: getMaxHp");
+	return 20;
+}
+
 /*------------------------------------------------------------------------*/
 
 void Roster::synchronize(Common::Serializer &s) {
@@ -232,6 +214,8 @@ Party::Party() {
 
 	for (int i = 0; i < TOTAL_CHARACTERS; ++i)
 		Common::fill(&_characterFlags[i][0], &_characterFlags[i][24], false);
+
+	_combatPartyCount = 0;
 }
 
 void Party::synchronize(Common::Serializer &s) {
@@ -342,4 +326,13 @@ bool Party::checkSkill(Skill skillId) {
 	}
 }
 
+bool Party::isInParty(int charId) {
+	for (int i = 0; i < 8; ++i) {
+		if (_partyMembers[i] == charId)
+			return true;
+	}
+
+	return false;
+}
+
 } // End of namespace Xeen
diff --git a/engines/xeen/party.h b/engines/xeen/party.h
index d521537..7e50104 100644
--- a/engines/xeen/party.h
+++ b/engines/xeen/party.h
@@ -50,9 +50,11 @@ enum Skill { THIEVERY = 0, ARMS_MASTER = 1, ASTROLOGER = 2, BODYBUILDER = 3,
 	SPOT_DOORS = 16, DANGER_SENSE = 17
 };
 
-enum ConditionType { CURSED = 0, HEART_BROKEN = 1, WEAK = 2, POISONED = 3,
+enum Condition { CURSED = 0, HEART_BROKEN = 1, WEAK = 2, POISONED = 3,
 	DISEASED = 4, INSANE = 5, IN_LOVE = 6, DRUNK = 7, SLEEP = 8, 
-	DEPRESSED = 9, CONFUSED = 10, PARALYZED = 11
+	DEPRESSED = 9, CONFUSED = 10, PARALYZED = 11, UNCONSCIOUS = 12,
+	DEAD = 13, STONED = 14, ERADICATED = 15,
+	NO_CONDITION = 16
 };
 
 #define ITEMS_COUNT 36
@@ -71,29 +73,6 @@ public:
 	void synchronize(Common::Serializer &s);
 };
 
-class Conditions {
-	byte _cursed;
-	byte _heartBroken;
-	byte _weak;
-	byte _poisoned;
-	byte _diseased;
-	byte _insane;
-	byte _inLove;
-	byte _drunk;
-	byte _asleep;
-	byte _depressed;
-	byte _confused;
-	byte _paralyzed;
-	byte _unconscious;
-	byte _dead;
-	byte _stoned;
-	byte _eradicated;
-public:
-	Conditions();
-	
-	void synchronize(Common::Serializer &s);
-};
-
 class PlayerStruct {
 public:
 	Common::String _name;
@@ -131,7 +110,7 @@ public:
 	AttributePair _poisonResistence;
 	AttributePair _energyResistence;
 	AttributePair _magicResistence;
-	Conditions _conditions;
+	int _conditions[16];
 	int _townUnknown;
 	int _unknown2;
 	int _currentHp;
@@ -143,6 +122,12 @@ public:
 public:
 	PlayerStruct();
 	void synchronize(Common::Serializer &s);
+
+	Condition findCondition() const;
+
+	int getYear(int partyYear, bool ignoreTemp);
+
+	int getMaxHp();
 };
 
 class Roster: public Common::Array<PlayerStruct> {
@@ -154,6 +139,7 @@ public:
 
 class Party {
 public:
+	// Dynamic data that's saved
 	int _partyCount;
 	int _realPartyCount;
 	int _partyMembers[8];
@@ -208,13 +194,17 @@ public:
 	XeenItem _blacksmithMisc2[ITEMS_COUNT];
 	bool _characterFlags[30][24];
 public:
+	// Other party related runtime data
 	Common::Array<PlayerStruct *> _activeParty;
+	int _combatPartyCount;
 public:
 	Party();
 
 	void synchronize(Common::Serializer &s);
 
 	bool checkSkill(Skill skillId);
+
+	bool isInParty(int charId);
 };
 
 } // End of namespace Xeen
diff --git a/engines/xeen/resources.cpp b/engines/xeen/resources.cpp
index d7d3fcc..79e8ba1 100644
--- a/engines/xeen/resources.cpp
+++ b/engines/xeen/resources.cpp
@@ -232,6 +232,51 @@ const byte TEXT_COLORS[40][4] = {
 	{ 0x00, 0xDB, 0xDB, 0xDB },
 };
 
-const char *DIRECTION_TEXT[4] = { "NORTH", "EAST", "SOUTH", "WEST" };
+const char *const DIRECTION_TEXT[4] = { "NORTH", "EAST", "SOUTH", "WEST" };
+
+const char *const RACE_NAMES[5] = { "Human", "Elf", "Dwarf", "Gnome", "H-Orc" };
+
+const char *const ALIGNMENT_NAMES[3] = { "Good", "Neutral", "Evil" };
+
+const char *const SEX_NAMES[2] = { "Male", "Female" };
+
+const char *const CLASS_NAMES[11] = {
+	"Knight", "Paladin", "Archer", "Cleric", "Sorcerer", "Robber", 
+	"Ninja", "Barbarian", "Druid", "Ranger", nullptr
+};
+
+const char *const CONDITION_NAMES[18] = {
+	nullptr, "Cursed", "Heart Broken", "Weak", "Poisoned", "Diseased", 
+	"Insane", "In Love", "Drunk", "Asleep", "Depressed", "Confused", 
+	"Paralyzed", "Unconscious", "Dead", "Stone", "Eradicated", "Good"
+};
+
+const char *const IN_PARTY = "\014""15In Party\014""d";
+
+const char *const PARTY_DETAILS = "\015\003l\002\014""00"
+	"\013""001""\011""035%s" 
+	"\013""009""\011""035%s" 
+	"\013""017""\011""035%s" 
+	"\013""025""\011""035%s" 
+	"\013""001""\011""136%s" 
+	"\013""009""\011""136%s" 
+	"\013""017""\011""136%s" 
+	"\013""025""\011""136%s" 
+	"\013""044""\011""035%s" 
+	"\013""052""\011""035%s" 
+	"\013""060""\011""035%s" 
+	"\013""068""\011""035%s" 
+	"\013""044""\011""136%s" 
+	"\013""052""\011""136%s" 
+	"\013""060""\011""136%s" 
+	"\013""068""\011""136%s";
+
+const int FACE_CONDITION_FRAMES[17] = { 
+	2, 2, 2, 1, 1, 4, 4, 4, 3, 2, 4, 3, 3, 5, 6, 7, 0 
+};
+
+const int CHAR_FACES_X[6] = { 10, 45, 81, 117, 153, 189 };
+
+const int HP_BARS_X[6] = { 13, 50, 86, 122, 158, 194 };
 
 } // End of namespace Xeen
diff --git a/engines/xeen/resources.h b/engines/xeen/resources.h
index cf4207b..80febec 100644
--- a/engines/xeen/resources.h
+++ b/engines/xeen/resources.h
@@ -36,7 +36,27 @@ extern const byte SYMBOLS[20][64];
 
 extern const byte TEXT_COLORS[40][4];
 
-extern const char *DIRECTION_TEXT[4];
+extern const char *const DIRECTION_TEXT[4];
+
+extern const char *const RACE_NAMES[5];
+
+extern const char *const CLASS_NAMES[11];
+
+extern const char *const ALIGNMENT_NAMES[3];
+
+extern const char *const SEX_NAMES[2];
+
+extern const char *const CONDITION_NAMES[18];
+
+extern const char *const IN_PARTY;
+
+extern const char *const PARTY_DETAILS;
+
+extern const int FACE_CONDITION_FRAMES[17];
+
+extern const int CHAR_FACES_X[6];
+
+extern const int HP_BARS_X[6];
 
 } // End of namespace Xeen
 
diff --git a/engines/xeen/screen.cpp b/engines/xeen/screen.cpp
index f3cbabc..ba2c97b 100644
--- a/engines/xeen/screen.cpp
+++ b/engines/xeen/screen.cpp
@@ -166,6 +166,22 @@ void Window::writeString(const Common::String &s) {
 	_vm->_screen->writeString(s, _innerBounds);
 }
 
+void Window::drawList(DrawStruct *items) {
+	Screen &screen = *_vm->_screen;
+
+	for (; items->_sprites != nullptr; ++items) {
+		if (items->_frame == -1 || items->_scale == -1)
+			continue;
+
+		Common::Rect bounds = _innerBounds;
+		bounds.translate(items->_x, items->_y);
+
+		// TODO: There are two sprite calls in this method. Figure out why
+		items->_sprites->draw(screen, items->_frame,
+			Common::Point(items->_x, items->_y));
+	}
+}
+
 /*------------------------------------------------------------------------*/
 
 /**
diff --git a/engines/xeen/screen.h b/engines/xeen/screen.h
index d62191e..ae38ec3 100644
--- a/engines/xeen/screen.h
+++ b/engines/xeen/screen.h
@@ -28,6 +28,7 @@
 #include "common/array.h"
 #include "common/rect.h"
 #include "xeen/font.h"
+#include "xeen/sprites.h"
 #include "xeen/xsurface.h"
 
 namespace Xeen {
@@ -41,6 +42,19 @@ namespace Xeen {
 class XeenEngine;
 class Screen;
 
+struct DrawStruct {
+	SpriteResource *_sprites;
+	int _frame;
+	int _x;
+	int _y;
+	int _scale;
+	int _flags;
+
+	DrawStruct(SpriteResource *sprites, int frame, int x, int y, int scale = 0, int flags = 0) :
+		_sprites(sprites), _frame(frame), _x(x), _y(y), _scale(scale), _flags(flags) {}
+	DrawStruct(): _sprites(nullptr), _frame(0), _x(0), _y(0), _scale(0), _flags(0) {}
+};
+
 class Window: public XSurface {
 private:
 	XeenEngine *_vm;
@@ -74,7 +88,10 @@ public:
 
 	void fill();
 
-	void writeString(const Common::String &s);};
+	void writeString(const Common::String &s);
+
+	void drawList(DrawStruct *items);
+};
 
 class Screen: public FontSurface {
 private:
diff --git a/engines/xeen/xeen.h b/engines/xeen/xeen.h
index a549c15..a7210ca 100644
--- a/engines/xeen/xeen.h
+++ b/engines/xeen/xeen.h
@@ -70,6 +70,13 @@ enum XeenDebugChannels {
 enum Mode {
 	MODE_0 = 0,
 	MODE_1 = 1,
+	MODE_2 = 2,
+	MODE_3 = 3,
+	MODE_4 = 4,
+	MODE_5 = 5,
+	MODE_6 = 6,
+	MODE_7 = 7,
+	MODE_8 = 8,
 	MODE_9 = 9
 };
 


Commit: ce96094c9bc54266c9742364e656c97446a6ecaf
    https://github.com/scummvm/scummvm/commit/ce96094c9bc54266c9742364e656c97446a6ecaf
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-01-05T08:11:16-05:00

Commit Message:
XEEN: In progress implementing map loading

Changed paths:
  A engines/xeen/dialogs_error.cpp
  A engines/xeen/dialogs_error.h
  A engines/xeen/map.cpp
  A engines/xeen/map.h
    engines/xeen/dialogs.cpp
    engines/xeen/dialogs.h
    engines/xeen/events.cpp
    engines/xeen/events.h
    engines/xeen/files.cpp
    engines/xeen/files.h
    engines/xeen/interface.cpp
    engines/xeen/interface.h
    engines/xeen/module.mk
    engines/xeen/party.cpp
    engines/xeen/party.h
    engines/xeen/resources.cpp
    engines/xeen/resources.h
    engines/xeen/saves.cpp
    engines/xeen/saves.h
    engines/xeen/screen.cpp
    engines/xeen/screen.h
    engines/xeen/sprites.cpp
    engines/xeen/sprites.h
    engines/xeen/xeen.cpp
    engines/xeen/xeen.h



diff --git a/engines/xeen/dialogs.cpp b/engines/xeen/dialogs.cpp
index 70a22d1..8e8e752 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 61ae734..987df6b 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 0000000..c0c0723
--- /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 0000000..03a6f16
--- /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 285005a..e0c3b26 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 7a6a65f..1705bb4 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 107cde4..a0ca243 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 8a028a9..3e38ad8 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 3a07cec..08128e5 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 3ceb082..1ed7afe 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 0000000..d797179
--- /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 0000000..4482173
--- /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 7f0caf7..5cbb1bb 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 25366d5..ec25f4a 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 7e50104..b415707 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 79e8ba1..3f59f3e 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 80febec..78104b2 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 7482a12..95957c4 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 f3ace80..1e67638 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 ba2c97b..cfde780 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 ae38ec3..1e164a3 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 5b8fe52..598870d 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 e9cdf72..998d5d3 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 1574871..b3ac743 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 a7210ca..9938519 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();


Commit: 86cdb68f4da1f43412bbbadca1e2c4a9a80c60d8
    https://github.com/scummvm/scummvm/commit/86cdb68f4da1f43412bbbadca1e2c4a9a80c60d8
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-01-05T11:02:35-05:00

Commit Message:
XEEN: Properly implemented map loading first loading loop

Changed paths:
    engines/xeen/map.cpp
    engines/xeen/map.h



diff --git a/engines/xeen/map.cpp b/engines/xeen/map.cpp
index d797179..4a3eda6 100644
--- a/engines/xeen/map.cpp
+++ b/engines/xeen/map.cpp
@@ -29,6 +29,14 @@
 
 namespace Xeen {
 
+const int MAP_GRID_PRIOR_INDEX[] = { 0, 0, 0, 0, 1, 2, 3, 4, 0 };
+
+const int MAP_GRID_PRIOR_DIRECTION[] = { 0, 1, 2, 3, 1, 2, 3, 0, 0 };
+
+const int MAP_GRID_PRIOR_INDEX2[] = { 0, 0, 0, 0, 2, 3, 4, 1, 0 };
+
+const int MAP_GRID_PRIOR_DIRECTION2[] = { 0, 1, 2, 3, 0, 1, 2, 3, 0 };
+
 MonsterStruct::MonsterStruct() {
 	_experience = 0;
 	_hp = 0;
@@ -490,6 +498,19 @@ void SurroundingMazes::synchronize(Common::SeekableReadStream &s) {
 	_west = s.readUint16LE();
 }
 
+int &SurroundingMazes::operator[](int idx) {
+	switch (idx) {
+	case DIR_NORTH:
+		return _north;
+	case DIR_EAST:
+		return _east;
+	case DIR_SOUTH:
+		return _south;
+	default:
+		return _west;
+	}
+}
+
 /*------------------------------------------------------------------------*/
 
 MazeDifficulties::MazeDifficulties() {
@@ -752,29 +773,30 @@ void Map::load(int mapId) {
 	}
 
 	bool isDarkCc = _vm->getGameID() == GType_DarkSide;
-	uint16 mapGrid[9];
-	uint16 *gridPtr = &mapGrid[0];
+	MazeData *mazeData = &_mazeData[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) {
+	for (int idx = 0; idx < 9; ++idx, ++mazeData) {
+		mazeData->_mazeId = mapId;
+
 		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);
+			mazeData->synchronize(datFile);
 			datFile.close();
 
 			if (isDarkCc && mapId == 50)
-				_mazeData.setAllTilesStepped();
+				mazeData->setAllTilesStepped();
 			if (!isDarkCc && _vm->_party._gameFlags[25] &&
 					(mapId == 42 || mapId == 43 || mapId == 4)) {
-				_mazeData.clearCellBits();
+				mazeData->clearCellBits();
 			}
 
-			_isOutdoors = (_mazeData._mazeFlags2 & FLAG_IS_OUTDOORS) != 0;
+			_isOutdoors = (mazeData->_mazeFlags2 & FLAG_IS_OUTDOORS) != 0;
 
 			// Handle loading text data
 			if (!textLoaded) {
@@ -815,10 +837,26 @@ void Map::load(int mapId) {
 			}
 		}
 
-		// TODO: Move to next surrounding maze
+		// Move to next surrounding maze
+		MazeData *baseMaze = &_mazeData[MAP_GRID_PRIOR_INDEX[idx]];
+		mapId = baseMaze->_surroundingMazes[MAP_GRID_PRIOR_DIRECTION[idx]];
+		if (mapId) {
+			baseMaze = &_mazeData[MAP_GRID_PRIOR_INDEX2[idx]];
+			mapId = baseMaze->_surroundingMazes[MAP_GRID_PRIOR_DIRECTION2[idx]];
+		}
 	}
 
-	// TODO
+	// TODO: Switch setting flags that don't seem to ever be used
+
+	// Reload object data, since prior loop iterations replaced the data
+	// for the main map with all the surrounding mazes
+	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();
+
+	// TODO: Loop loading moer data
 }
 
 } // End of namespace Xeen
diff --git a/engines/xeen/map.h b/engines/xeen/map.h
index 4482173..e52e978 100644
--- a/engines/xeen/map.h
+++ b/engines/xeen/map.h
@@ -126,6 +126,8 @@ public:
 	SurroundingMazes();
 
 	void synchronize(Common::SeekableReadStream &s);
+
+	int &operator[](int idx);
 };
 
 class MazeDifficulties {
@@ -155,6 +157,7 @@ enum MazeFlags2 { FLAG_IS_OUTDOORS = 0x8000, FLAG_IS_DARK = 0x4000 };
 
 class MazeData {
 public:
+	// Resource fields
 	int _wallData[MAP_HEIGHT][MAP_WIDTH];
 	int _cellFlag[MAP_HEIGHT][MAP_WIDTH];
 	int _mazeNumber;
@@ -171,6 +174,9 @@ public:
 	int _tavernTips;
 	bool _seenTiles[MAP_HEIGHT][MAP_WIDTH];
 	bool _steppedOnTiles[MAP_HEIGHT][MAP_WIDTH];
+
+	// Misc fields
+	int _mazeId;
 public:
 	MazeData();
 
@@ -242,7 +248,7 @@ public:
 class Map {
 private:
 	XeenEngine *_vm;
-	MazeData _mazeData;
+	MazeData _mazeData[9];
 	Common::String _mazeName;
 	MonsterObjectData _mobData;
 	HeadData _headData;


Commit: 42165d21bb626e325d79d755bbf65b8b5044020f
    https://github.com/scummvm/scummvm/commit/42165d21bb626e325d79d755bbf65b8b5044020f
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-01-05T15:10:42-05:00

Commit Message:
XEEN: Implement more map loading

Changed paths:
    engines/xeen/interface.cpp
    engines/xeen/interface.h
    engines/xeen/map.cpp
    engines/xeen/map.h
    engines/xeen/screen.h
    engines/xeen/xeen.cpp
    engines/xeen/xeen.h



diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp
index 08128e5..4f40c47 100644
--- a/engines/xeen/interface.cpp
+++ b/engines/xeen/interface.cpp
@@ -44,10 +44,31 @@ Interface::Interface(XeenEngine *vm) : ButtonContainer(), _vm(vm) {
 	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);
+	initDrawStructs();
+}
+
+void Interface::initDrawStructs() {
+	_faceDrawStructs[0] = DrawStruct(0, 0, 0);
+	_faceDrawStructs[1] = DrawStruct(0, 101, 0);
+	_faceDrawStructs[2] = DrawStruct(0, 0, 43);
+	_faceDrawStructs[3] = DrawStruct(0, 101, 43);
+
+	_mainList[0] = DrawStruct(7, 232, 74);
+	_mainList[1] = DrawStruct(0, 235, 75);
+	_mainList[2] = DrawStruct(2, 260, 75);
+	_mainList[3] = DrawStruct(4, 286, 75);
+	_mainList[4] = DrawStruct(6, 235, 96);
+	_mainList[5] = DrawStruct(8, 260, 96);
+	_mainList[6] = DrawStruct(10, 286, 96);
+	_mainList[7] = DrawStruct(12, 235, 117);
+	_mainList[8] = DrawStruct(14, 260, 117);
+	_mainList[9] = DrawStruct(16, 286, 117);
+	_mainList[10] = DrawStruct(20, 235, 148);
+	_mainList[11] = DrawStruct(22, 260, 148);
+	_mainList[12] = DrawStruct(24, 286, 148);
+	_mainList[13] = DrawStruct(26, 235, 169);
+	_mainList[14] = DrawStruct(28, 260, 169);
+	_mainList[15] = DrawStruct(30, 286, 169);
 }
 
 void Interface::manageCharacters(bool soundPlayed) {
@@ -82,7 +103,7 @@ start:
 
 		if (!_partyFaces[0]) {
 			// Xeen only uses 24 of possible 30 character slots
-			loadCharIcons(XEEN_TOTAL_CHARACTERS);
+			loadCharIcons();
 
 			for (int i = 0; i < _vm->_party._partyCount; ++i)
 				_partyFaces[i] = &_charFaces[_vm->_party._partyMembers[i]];
@@ -255,8 +276,8 @@ start:
 	_uiSprites.clear();
 }
 
-void Interface::loadCharIcons(int numChars) {
-	for (int i = 0; i < numChars; ++i) {
+void Interface::loadCharIcons() {
+	for (int i = 0; i < XEEN_TOTAL_CHARACTERS; ++i) {
 		// Load new character resource
 		Common::String name = Common::String::format("char%02d.fac", i);
 		_charFaces[i].load(name);
@@ -265,6 +286,11 @@ void Interface::loadCharIcons(int numChars) {
 	_dseFace.load("dse.fac");
 }
 
+void Interface::loadPartyIcons() {
+	for (int i = 0; i < _vm->_party._partyCount; ++i)
+		_partyFaces[i] = &_charFaces[_vm->_party._partyMembers[i]];
+}
+
 void Interface::setupBackground() {
 	_vm->_screen->loadBackground("back.raw");
 	assembleBorder();
@@ -508,4 +534,54 @@ void Interface::draw3d(bool flag) {
 	warning("TODO");
 }
 
+void Interface::animate3d() {
+
+}
+
+void Interface::setMonsters() {
+
+}
+
+void Interface::setObjects() {
+
+}
+
+void Interface::setOutdoorsMonsters() {
+
+}
+
+void Interface::setOutdoorsObjects() {
+
+}
+
+void Interface::startup() {
+	Screen &screen = *_vm->_screen;
+	_iconSprites.load("main.icn");
+
+	animate3d();
+	if (_vm->_map->_isOutdoors) {
+		setMonsters();
+		setObjects();
+	} else {
+		setOutdoorsMonsters();
+		setOutdoorsObjects();
+	}
+	draw3d(false);
+
+	_globalSprites.draw(screen._windows[1], 5, Common::Point(232, 9));
+	charIconsPrint(false);
+
+	_mainList[0]._sprites = &_globalSprites;
+	for (int i = 1; i < 16; ++i)
+		_mainList[i]._sprites = &_iconSprites;
+}
+
+void Interface::mainIconsPrint() {
+	Screen &screen = *_vm->_screen;
+	screen._windows[38].close();
+	screen._windows[12].close();
+	screen._windows[0].drawList(_mainList, 16);
+	screen._windows[34].update();
+}
+
 } // End of namespace Xeen
diff --git a/engines/xeen/interface.h b/engines/xeen/interface.h
index 1ed7afe..f455957 100644
--- a/engines/xeen/interface.h
+++ b/engines/xeen/interface.h
@@ -44,9 +44,11 @@ private:
 	SpriteResource _restoreSprites;
 	SpriteResource _hpSprites;
 	SpriteResource _uiSprites;
+	SpriteResource _iconSprites;
 	SpriteResource _charFaces[TOTAL_CHARACTERS];
 	SpriteResource *_partyFaces[MAX_ACTIVE_PARTY];
 	DrawStruct _faceDrawStructs[4];
+	DrawStruct _mainList[16];
 	int _combatCharIds[8];
 
 	int _batUIFrame;
@@ -64,6 +66,8 @@ private:
 	int _hiliteChar;
 	int _intrIndex1;
 
+	void initDrawStructs();
+
 	void assembleBorder();
 
 	void setupBackground();
@@ -75,14 +79,30 @@ private:
 	void drawViewBackground(int bgType);
 
 	void addCharacterToRoster();
+
+	void animate3d();
+
+	void setMonsters();
+
+	void setObjects();
+
+	void setOutdoorsMonsters();
+
+	void setOutdoorsObjects();
 public:
 	Interface(XeenEngine *vm);
 
 	void manageCharacters(bool soundPlayed);
 
-	void loadCharIcons(int numChars);
+	void loadCharIcons();
+
+	void loadPartyIcons();
 
 	void draw3d(bool flag);
+
+	void startup();
+
+	void mainIconsPrint();
 };
 
 } // End of namespace Xeen
diff --git a/engines/xeen/map.cpp b/engines/xeen/map.cpp
index 4a3eda6..5179b92 100644
--- a/engines/xeen/map.cpp
+++ b/engines/xeen/map.cpp
@@ -475,7 +475,7 @@ void MonsterData::load(const Common::String &name) {
 void MonsterData::synchronize(Common::SeekableReadStream &s) {
 	clear();
 
-	MonsterData spr;
+	MonsterStruct spr;
 	while (!s.eos()) {
 		spr.synchronize(s);
 		push_back(spr);
@@ -710,6 +710,7 @@ Map::Map(XeenEngine *vm) : _vm(vm), _mobData(vm) {
 	_sideObj = 0;
 	_sideMon = 0;
 	_isOutdoors = false;
+	_stepped = false;
 }
 
 void Map::load(int mapId) {
@@ -722,6 +723,11 @@ void Map::load(int mapId) {
 		PleaseWait::show(_vm);
 	}
 
+	_stepped = true;
+	_vm->_party._mazeId = mapId;
+	_vm->_events->clearEvents();
+
+
 	if (mapId >= 113 && mapId <= 127) {
 		_townPortalSide = 0;
 	} else {
@@ -856,7 +862,13 @@ void Map::load(int mapId) {
 	_mobData.synchronize(mobFile, _isOutdoors, _monsterData);
 	mobFile.close();
 
-	// TODO: Loop loading moer data
+	// TODO: Loop loading moer data / other / cbr? data
+
+	if (_isOutdoors) {
+
+	} else {
+
+	}
 }
 
 } // End of namespace Xeen
diff --git a/engines/xeen/map.h b/engines/xeen/map.h
index e52e978..882e495 100644
--- a/engines/xeen/map.h
+++ b/engines/xeen/map.h
@@ -258,6 +258,8 @@ private:
 	int _townPortalSide;
 	int _sideObj;
 	int _sideMon;
+	bool _stepped;
+public:
 	bool _isOutdoors;
 public:
 	Map(XeenEngine *vm);
diff --git a/engines/xeen/screen.h b/engines/xeen/screen.h
index 1e164a3..adf956e 100644
--- a/engines/xeen/screen.h
+++ b/engines/xeen/screen.h
@@ -50,8 +50,8 @@ struct DrawStruct {
 	int _scale;
 	int _flags;
 
-	DrawStruct(SpriteResource *sprites, int frame, int x, int y, int scale = 0, int flags = 0) :
-		_sprites(sprites), _frame(frame), _x(x), _y(y), _scale(scale), _flags(flags) {}
+	DrawStruct(int frame, int x, int y, int scale = 0, int flags = 0) :
+		_sprites(nullptr), _frame(frame), _x(x), _y(y), _scale(scale), _flags(flags) {}
 	DrawStruct(): _sprites(nullptr), _frame(0), _x(0), _y(0), _scale(0), _flags(0) {}
 };
 
diff --git a/engines/xeen/xeen.cpp b/engines/xeen/xeen.cpp
index b3ac743..7321bef 100644
--- a/engines/xeen/xeen.cpp
+++ b/engines/xeen/xeen.cpp
@@ -52,6 +52,8 @@ XeenEngine::XeenEngine(OSystem *syst, const XeenGameDescription *gameDesc)
 	_face2State = 0;
 	_noDirectionSense = false;
 	_falling = false;
+	_tillMove = false;
+	_moveMonsters = false;
 }
 
 XeenEngine::~XeenEngine() {
@@ -271,8 +273,7 @@ void XeenEngine::play() {
 
 	_screen->loadBackground("back.raw");
 	_screen->loadPalette("mm4.pal");
-	_interface->loadCharIcons(_party._partyCount);
-	_iconsSprites.load("main.icn");
+	_interface->loadPartyIcons();
 
 	if (getGameID() != GType_WorldOfXeen && !_loadDarkSide) {
 		_loadDarkSide = true;
@@ -283,6 +284,28 @@ void XeenEngine::play() {
 	}
 
 	_map->load(_party._mazeId);
+
+	_interface->startup();
+	if (_mode == MODE_0) {
+		_screen->fadeOut(4);
+	}
+
+	_screen->_windows[0].update();
+	_interface->mainIconsPrint();
+	_screen->_windows[0].update();
+	_events->setCursor(0);
+
+	_moveMonsters = true;
+	_tillMove = false;
+	if (_mode == MODE_0) {
+		_mode = MODE_1;
+		_screen->fadeIn(4);
+	}
+
+	// Main game loop
+	while (!shouldQuit()) {
+		_events->pollEventsAndWait();
+	}
 }
 
 } // End of namespace Xeen
diff --git a/engines/xeen/xeen.h b/engines/xeen/xeen.h
index 9938519..776f319 100644
--- a/engines/xeen/xeen.h
+++ b/engines/xeen/xeen.h
@@ -93,7 +93,8 @@ private:
 	const XeenGameDescription *_gameDescription;
 	Common::RandomSource _randomSource;
 	int _loadSaveSlot;
-	SpriteResource _iconsSprites;
+	bool _moveMonsters;
+	bool _tillMove;
 
 	void showIntro();
 


Commit: eb0c292aafc9b1b819ab1f43d4ec3a059842e96a
    https://github.com/scummvm/scummvm/commit/eb0c292aafc9b1b819ab1f43d4ec3a059842e96a
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-01-05T21:17:44-05:00

Commit Message:
XEEN: Start of in-game display implementation

Changed paths:
    engines/xeen/files.cpp
    engines/xeen/files.h
    engines/xeen/interface.cpp
    engines/xeen/interface.h
    engines/xeen/map.cpp
    engines/xeen/saves.cpp
    engines/xeen/saves.h
    engines/xeen/xeen.cpp



diff --git a/engines/xeen/files.cpp b/engines/xeen/files.cpp
index a0ca243..b1358d4 100644
--- a/engines/xeen/files.cpp
+++ b/engines/xeen/files.cpp
@@ -29,64 +29,10 @@
 
 namespace Xeen {
 
-CCArchive::CCArchive(const Common::String &filename, bool encoded): 
-		_filename(filename), _encoded(encoded) {
-	File f(filename);
-	loadIndex(&f);
-}
-
-CCArchive::~CCArchive() {
-}
-
-// Archive implementation
-bool CCArchive::hasFile(const Common::String &name) const {
-	CCEntry ccEntry;
-	return getHeaderEntry(name, ccEntry);
-}
-
-int CCArchive::listMembers(Common::ArchiveMemberList &list) const {
-	// CC files don't maintain the original filenames, so we can't list it
-	return 0;
-}
-
-const Common::ArchiveMemberPtr CCArchive::getMember(const Common::String &name) const {
-	if (!hasFile(name))
-		return Common::ArchiveMemberPtr();
-
-	return Common::ArchiveMemberPtr(new Common::GenericArchiveMember(name, this));
-}
-
-Common::SeekableReadStream *CCArchive::createReadStreamForMember(const Common::String &name) const {
-	CCEntry ccEntry;
-
-	if (getHeaderEntry(name, ccEntry)) {
-		// Open the correct CC file
-		Common::File f;
-		if (!f.open(_filename))
-			error("Could not open CC file");
-
-		// Read in the data for the specific resource
-		f.seek(ccEntry._offset);
-		byte *data = new byte[ccEntry._size];
-		f.read(data, ccEntry._size);
-
-		if (_encoded) {
-			// Decrypt the data
-			for (int i = 0; i < ccEntry._size; ++i)
-				data[i] ^= 0x35;
-		}
-
-		// Return the data as a stream
-		return new Common::MemoryReadStream(data, ccEntry._size, DisposeAfterUse::YES);
-	}
-
-	return nullptr;
-}
-
 /**
- * Hash a given filename to produce the Id that represents it
- */
-uint16 CCArchive::convertNameToId(const Common::String &resourceName) const {
+* Hash a given filename to produce the Id that represents it
+*/
+uint16 BaseCCArchive::convertNameToId(const Common::String &resourceName) const {
 	if (resourceName.empty())
 		return 0xffff;
 
@@ -104,9 +50,9 @@ uint16 CCArchive::convertNameToId(const Common::String &resourceName) const {
 }
 
 /**
- * Load the index of a given CC file
- */
-void CCArchive::loadIndex(Common::SeekableReadStream *stream) {
+* Load the index of a given CC file
+*/
+void BaseCCArchive::loadIndex(Common::SeekableReadStream *stream) {
 	int count = stream->readUint16LE();
 
 	// Read in the data for the archive's index
@@ -136,11 +82,16 @@ void CCArchive::loadIndex(Common::SeekableReadStream *stream) {
 	delete[] rawIndex;
 }
 
+bool BaseCCArchive::hasFile(const Common::String &name) const {
+	CCEntry ccEntry;
+	return getHeaderEntry(name, ccEntry);
+}
+
 /**
 * Given a resource name, returns whether an entry exists, and returns
 * the header index data for that entry
 */
-bool CCArchive::getHeaderEntry(const Common::String &resourceName, CCEntry &ccEntry) const {
+bool BaseCCArchive::getHeaderEntry(const Common::String &resourceName, CCEntry &ccEntry) const {
 	uint16 id = convertNameToId(resourceName);
 
 	// Loop through the index
@@ -155,6 +106,56 @@ bool CCArchive::getHeaderEntry(const Common::String &resourceName, CCEntry &ccEn
 	return false;
 }
 
+const Common::ArchiveMemberPtr BaseCCArchive::getMember(const Common::String &name) const {
+	if (!hasFile(name))
+		return Common::ArchiveMemberPtr();
+
+	return Common::ArchiveMemberPtr(new Common::GenericArchiveMember(name, this));
+}
+
+int BaseCCArchive::listMembers(Common::ArchiveMemberList &list) const {
+	// CC files don't maintain the original filenames, so we can't list it
+	return 0;
+}
+
+/*------------------------------------------------------------------------*/
+
+CCArchive::CCArchive(const Common::String &filename, bool encoded): 
+		_filename(filename), _encoded(encoded) {
+	File f(filename);
+	loadIndex(&f);
+}
+
+CCArchive::~CCArchive() {
+}
+
+Common::SeekableReadStream *CCArchive::createReadStreamForMember(const Common::String &name) const {
+	CCEntry ccEntry;
+
+	if (getHeaderEntry(name, ccEntry)) {
+		// Open the correct CC file
+		Common::File f;
+		if (!f.open(_filename))
+			error("Could not open CC file");
+
+		// Read in the data for the specific resource
+		f.seek(ccEntry._offset);
+		byte *data = new byte[ccEntry._size];
+		f.read(data, ccEntry._size);
+
+		if (_encoded) {
+			// Decrypt the data
+			for (int i = 0; i < ccEntry._size; ++i)
+				data[i] ^= 0x35;
+		}
+
+		// Return the data as a stream
+		return new Common::MemoryReadStream(data, ccEntry._size, DisposeAfterUse::YES);
+	}
+
+	return nullptr;
+}
+
 /*------------------------------------------------------------------------*/
 
 /**
diff --git a/engines/xeen/files.h b/engines/xeen/files.h
index 3e38ad8..6e560ca 100644
--- a/engines/xeen/files.h
+++ b/engines/xeen/files.h
@@ -58,41 +58,52 @@ public:
 };
 
 /**
-* Xeen CC file implementation
+* Details of a single entry in a CC file index
 */
-class CCArchive : public Common::Archive {
-private:
-	/**
-	* Details of a single entry in a CC file index
-	*/
-	struct CCEntry {
-		uint16 _id;
-		uint32 _offset;
-		uint16 _size;
-
-		CCEntry() : _id(0), _offset(0), _size(0) {}
-		CCEntry(uint16 id, uint32 offset, uint32 size)
-			: _id(id), _offset(offset), _size(size) {
-		}
-	};
-
-	Common::Array<CCEntry> _index;
-	Common::String _filename;
-	bool _encoded;
+struct CCEntry {
+	uint16 _id;
+	uint32 _offset;
+	uint16 _size;
+
+	CCEntry() : _id(0), _offset(0), _size(0) {}
+	CCEntry(uint16 id, uint32 offset, uint32 size)
+		: _id(id), _offset(offset), _size(size) {
+	}
+};
 
+/**
+* Base Xeen CC file implementation
+*/
+class BaseCCArchive : public Common::Archive {
+private:
 	uint16 convertNameToId(const Common::String &resourceName) const;
+protected:
+	Common::Array<CCEntry> _index;
 
 	void loadIndex(Common::SeekableReadStream *stream);
 
 	bool getHeaderEntry(const Common::String &resourceName, CCEntry &ccEntry) const;
 public:
-	CCArchive(const Common::String &filename, bool encoded = true);
-	virtual ~CCArchive();
+	BaseCCArchive() {}
 
 	// Archive implementation
 	virtual bool hasFile(const Common::String &name) const;
 	virtual int listMembers(Common::ArchiveMemberList &list) const;
 	virtual const Common::ArchiveMemberPtr getMember(const Common::String &name) const;
+};
+
+/**
+* Xeen CC file implementation
+*/
+class CCArchive : public BaseCCArchive {
+private:
+	Common::String _filename;
+	bool _encoded;
+public:
+	CCArchive(const Common::String &filename, bool encoded = true);
+	virtual ~CCArchive();
+
+	// Archive implementation
 	virtual Common::SeekableReadStream *createReadStreamForMember(const Common::String &name) const;
 };
 
diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp
index 4f40c47..daeb440 100644
--- a/engines/xeen/interface.cpp
+++ b/engines/xeen/interface.cpp
@@ -71,10 +71,7 @@ void Interface::initDrawStructs() {
 	_mainList[15] = DrawStruct(30, 286, 169);
 }
 
-void Interface::manageCharacters(bool soundPlayed) {
-	Screen &screen = *_vm->_screen;
-	EventsManager &events = *_vm->_events;
-	bool flag = false;
+void Interface::setup() {
 	_globalSprites.load("global.icn");
 	_borderSprites.load("border.icn");
 	_spellFxSprites.load("spellfx.icn");
@@ -84,7 +81,6 @@ void Interface::manageCharacters(bool soundPlayed) {
 	_hpSprites.load("hpbars.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) {
@@ -92,7 +88,14 @@ start:
 	}
 
 	_isEarlyGame = _vm->_party._minutes >= 300;
+}
 
+void Interface::manageCharacters(bool soundPlayed) {
+	Screen &screen = *_vm->_screen;
+	EventsManager &events = *_vm->_events;
+	bool flag = false;
+
+start:
 	if (_vm->_party._mazeId != 0) {
 		_vm->_mode = MODE_0;
 		_buttonsLoaded = true;
@@ -279,7 +282,7 @@ start:
 void Interface::loadCharIcons() {
 	for (int i = 0; i < XEEN_TOTAL_CHARACTERS; ++i) {
 		// Load new character resource
-		Common::String name = Common::String::format("char%02d.fac", i);
+		Common::String name = Common::String::format("char%02d.fac", i + 1);
 		_charFaces[i].load(name);
 	}
 
@@ -556,6 +559,7 @@ void Interface::setOutdoorsObjects() {
 
 void Interface::startup() {
 	Screen &screen = *_vm->_screen;
+	loadCharIcons();
 	_iconSprites.load("main.icn");
 
 	animate3d();
diff --git a/engines/xeen/interface.h b/engines/xeen/interface.h
index f455957..b19f031 100644
--- a/engines/xeen/interface.h
+++ b/engines/xeen/interface.h
@@ -66,6 +66,8 @@ private:
 	int _hiliteChar;
 	int _intrIndex1;
 
+	void loadSprites();
+
 	void initDrawStructs();
 
 	void assembleBorder();
@@ -92,6 +94,8 @@ private:
 public:
 	Interface(XeenEngine *vm);
 
+	void setup();
+
 	void manageCharacters(bool soundPlayed);
 
 	void loadCharIcons();
diff --git a/engines/xeen/map.cpp b/engines/xeen/map.cpp
index 5179b92..5e98c51 100644
--- a/engines/xeen/map.cpp
+++ b/engines/xeen/map.cpp
@@ -669,6 +669,7 @@ void MonsterObjectData::synchronize(Common::SeekableReadStream &s,
 	}
 
 	// merge up monsters
+	_monsters.resize(monData.size());
 	for (uint i = 0; i < monData.size(); ++i) {
 		MazeMonster &dest = _monsters[i];
 		dest._position = monData[i]._pos;
@@ -808,7 +809,7 @@ void Map::load(int mapId) {
 			if (!textLoaded) {
 				textLoaded = true;
 				Common::String txtName = Common::String::format("%s%c%03u.txt",
-					isDarkCc ? "dark" : "xeen", mapId >= 100 ? 'x' : '0');
+					isDarkCc ? "dark" : "xeen", mapId >= 100 ? 'x' : '0', mapId);
 				File fText(txtName);
 				char mazeName[33];
 				fText.read(mazeName, 33);
@@ -819,13 +820,13 @@ void Map::load(int mapId) {
 
 				// Load the monster data
 				Common::String mobName = Common::String::format("maze%c%03u.mob",
-					(_vm->_party._mazeId >= 100) ? 'x' : '0', _vm->_party._mazeId);
+					(mapId >= 100) ? 'x' : '0', mapId);
 				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);
+					(mapId >= 100) ? 'x' : '0', mapId);
 				File headFile(headName);
 				_headData.synchronize(headFile);
 				headFile.close();
@@ -846,7 +847,7 @@ void Map::load(int mapId) {
 		// Move to next surrounding maze
 		MazeData *baseMaze = &_mazeData[MAP_GRID_PRIOR_INDEX[idx]];
 		mapId = baseMaze->_surroundingMazes[MAP_GRID_PRIOR_DIRECTION[idx]];
-		if (mapId) {
+		if (!mapId) {
 			baseMaze = &_mazeData[MAP_GRID_PRIOR_INDEX2[idx]];
 			mapId = baseMaze->_surroundingMazes[MAP_GRID_PRIOR_DIRECTION2[idx]];
 		}
diff --git a/engines/xeen/saves.cpp b/engines/xeen/saves.cpp
index 95957c4..ae29dd1 100644
--- a/engines/xeen/saves.cpp
+++ b/engines/xeen/saves.cpp
@@ -22,6 +22,7 @@
 
 #include "common/scummsys.h"
 #include "common/algorithm.h"
+#include "common/memstream.h"
 #include "xeen/saves.h"
 #include "xeen/files.h"
 #include "xeen/xeen.h"
@@ -29,7 +30,13 @@
 namespace Xeen {
 
 SavesManager::SavesManager(XeenEngine *vm, Party &party, Roster &roster) : 
-		_vm(vm), _party(party), _roster(roster) {
+		BaseCCArchive(), _vm(vm), _party(party), _roster(roster) {
+	SearchMan.add("saves", this, 0, false);
+	_data = nullptr;
+}
+
+SavesManager::~SavesManager() {
+	delete[] _data;
 }
 
 /**
@@ -57,24 +64,47 @@ void SavesManager::syncBitFlags(Common::Serializer &s, bool *startP, bool *endP)
 	}
 }
 
-/**
- * Sets up the dynamic data for the game for a new game
- */
-void SavesManager::reset() {
-	Common::String name(_vm->getGameID() == GType_Clouds ? "xeen.cur" : "dark.cur");
-	CCArchive cur(name, false);
-	
-	Common::SeekableReadStream *chr = cur.createReadStreamForMember("maze.chr");
+Common::SeekableReadStream *SavesManager::createReadStreamForMember(const Common::String &name) const {
+	CCEntry ccEntry;
+
+	if (getHeaderEntry(name, ccEntry)) {
+		// Open the correct CC entry
+		return new Common::MemoryReadStream(_data + ccEntry._offset, ccEntry._size);
+	}
+
+	return nullptr;
+}
+
+void SavesManager::load(Common::SeekableReadStream *stream) {
+	loadIndex(stream);
+
+	delete[] _data;
+	_data = new byte[stream->size()];
+	stream->seek(0);
+	stream->read(_data, stream->size());
+
+	// Load in the character stats and active party
+	Common::SeekableReadStream *chr = createReadStreamForMember("maze.chr");
 	Common::Serializer sChr(chr, nullptr);
 	_roster.synchronize(sChr);
 	delete chr;
 
-	Common::SeekableReadStream *pty = cur.createReadStreamForMember("maze.pty");
+	Common::SeekableReadStream *pty = createReadStreamForMember("maze.pty");
 	Common::Serializer sPty(pty, nullptr);
 	_party.synchronize(sPty);
 	delete pty;
 }
 
+/**
+ * Sets up the dynamic data for the game for a new game
+ */
+void SavesManager::reset() {
+	Common::String name(_vm->getGameID() == GType_Clouds ? "xeen.cur" : "dark.cur");
+	File f(name);
+
+	load(&f);
+}
+
 void SavesManager::readCharFile() {
 	warning("TODO: readCharFile");
 }
diff --git a/engines/xeen/saves.h b/engines/xeen/saves.h
index 1e67638..ed4b80b 100644
--- a/engines/xeen/saves.h
+++ b/engines/xeen/saves.h
@@ -27,6 +27,7 @@
 #include "common/savefile.h"
 #include "graphics/surface.h"
 #include "xeen/party.h"
+#include "xeen/files.h"
 
 namespace Xeen {
 
@@ -39,20 +40,29 @@ struct XeenSavegameHeader {
 	int _totalFrames;
 };
 
-class SavesManager {
+class SavesManager: public BaseCCArchive {
 private:
 	XeenEngine *_vm;
 	Party &_party;
 	Roster &_roster;
+	byte *_data;
+
+	void load(Common::SeekableReadStream *stream);
 public:
 	static void syncBitFlags(Common::Serializer &s, bool *startP, bool *endP);
 public:
 	SavesManager(XeenEngine *vm, Party &party, Roster &roster);
+
+	~SavesManager();
+
 	void reset();
 
 	void readCharFile();
 
 	void writeCharFile();
+
+	// Archive implementation
+	virtual Common::SeekableReadStream *createReadStreamForMember(const Common::String &name) const;
 };
 
 } // End of namespace Xeen
diff --git a/engines/xeen/xeen.cpp b/engines/xeen/xeen.cpp
index 7321bef..948b415 100644
--- a/engines/xeen/xeen.cpp
+++ b/engines/xeen/xeen.cpp
@@ -54,6 +54,7 @@ XeenEngine::XeenEngine(OSystem *syst, const XeenGameDescription *gameDesc)
 	_falling = false;
 	_tillMove = false;
 	_moveMonsters = false;
+	_mode = MODE_0;
 }
 
 XeenEngine::~XeenEngine() {
@@ -271,6 +272,7 @@ void XeenEngine::playGame() {
 void XeenEngine::play() {
 	// TODO: Init variables
 
+	_interface->setup();
 	_screen->loadBackground("back.raw");
 	_screen->loadPalette("mm4.pal");
 	_interface->loadPartyIcons();


Commit: 31f4f5b843400531d3e091ae0eb673d6dacc227d
    https://github.com/scummvm/scummvm/commit/31f4f5b843400531d3e091ae0eb673d6dacc227d
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-01-06T19:09:07-05:00

Commit Message:
XEEN: More interface setup and UI button definitions

Changed paths:
    engines/xeen/dialogs.cpp
    engines/xeen/dialogs.h
    engines/xeen/interface.cpp
    engines/xeen/interface.h
    engines/xeen/xeen.cpp
    engines/xeen/xeen.h



diff --git a/engines/xeen/dialogs.cpp b/engines/xeen/dialogs.cpp
index 8e8e752..c677fc8 100644
--- a/engines/xeen/dialogs.cpp
+++ b/engines/xeen/dialogs.cpp
@@ -46,7 +46,7 @@ void ButtonContainer::restoreButtons() {
 	_buttons = _savedButtons.pop();
 }
 
-void ButtonContainer::addButton(const Common::Rect &bounds, int val, SpriteResource *sprites, bool draw = true) {
+void ButtonContainer::addButton(const Common::Rect &bounds, int val, SpriteResource *sprites, bool draw) {
 	_buttons.push_back(UIButton(bounds, val, sprites, draw));
 }
 
diff --git a/engines/xeen/dialogs.h b/engines/xeen/dialogs.h
index 987df6b..229c40a 100644
--- a/engines/xeen/dialogs.h
+++ b/engines/xeen/dialogs.h
@@ -66,7 +66,7 @@ public:
 
 	void restoreButtons();
 
-	void addButton(const Common::Rect &bounds, int val, SpriteResource *sprites, bool draw);
+	void addButton(const Common::Rect &bounds, int val, SpriteResource *sprites, bool draw = true);
 };
 
 class SettingsBaseDialog : public ButtonContainer {
diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp
index daeb440..c27cdb9 100644
--- a/engines/xeen/interface.cpp
+++ b/engines/xeen/interface.cpp
@@ -38,11 +38,16 @@ Interface::Interface(XeenEngine *vm) : ButtonContainer(), _vm(vm) {
 	_powerShieldUIFrame = 0;
 	_holyBonusUIFrame = 0;
 	_heroismUIFrame = 0;
+	_flipUIFrame = 0;
 	_isEarlyGame = false;
 	_buttonsLoaded = false;
 	_hiliteChar = -1;
 	Common::fill(&_combatCharIds[0], &_combatCharIds[8], 0);
 	_intrIndex1 = 0;
+	_flipWtr = false;
+	_flag1 = false;
+	_flag2 = false;
+	_tillMove = 0;
 
 	initDrawStructs();
 }
@@ -534,6 +539,17 @@ void Interface::draw3d(bool flag) {
 	if (!screen._windows[11]._enabled)
 		return;
 
+	_flipUIFrame = (_flipUIFrame + 1) % 4;
+	if (_flipUIFrame == 0)
+		_flipWtr = !_flipWtr;
+	if (_tillMove && (_vm->_mode == MODE_1 || _vm->_mode == MODE_2) &&
+			!_flag1 && _vm->_moveMonsters) {
+		if (--_tillMove == 0)
+			moveMonsters();
+	}
+
+	// TODO: more
+
 	warning("TODO");
 }
 
@@ -578,6 +594,10 @@ void Interface::startup() {
 	_mainList[0]._sprites = &_globalSprites;
 	for (int i = 1; i < 16; ++i)
 		_mainList[i]._sprites = &_iconSprites;
+
+	setIconButtons();
+
+	_tillMove = false;
 }
 
 void Interface::mainIconsPrint() {
@@ -588,4 +608,33 @@ void Interface::mainIconsPrint() {
 	screen._windows[34].update();
 }
 
+void Interface::moveMonsters() {
+
+}
+
+void Interface::setIconButtons() {
+	clearButtons();
+
+	addButton(Common::Rect(235,  75, 259,  95),  83, &_iconSprites);
+	addButton(Common::Rect(260,  75, 284,  95),  67, &_iconSprites);
+	addButton(Common::Rect(286,  75, 310,  95),  82, &_iconSprites);
+	addButton(Common::Rect(235,  96, 259, 116),  66, &_iconSprites);
+	addButton(Common::Rect(260,  96, 284, 116),  68, &_iconSprites);
+	addButton(Common::Rect(286,  96, 310, 116),  86, &_iconSprites);
+	addButton(Common::Rect(235, 117, 259, 137),  77, &_iconSprites);
+	addButton(Common::Rect(260, 117, 284, 137),  73, &_iconSprites);
+	addButton(Common::Rect(286, 117, 310, 137),  81, &_iconSprites);
+	addButton(Common::Rect(109, 137, 122, 147),   9, &_iconSprites);
+	addButton(Common::Rect(235, 148, 259, 168), 240, &_iconSprites);
+	addButton(Common::Rect(260, 148, 284, 168), 242, &_iconSprites);
+	addButton(Common::Rect(286, 148, 310, 168), 241, &_iconSprites);
+	addButton(Common::Rect(235, 169, 259, 189), 176, &_iconSprites);
+	addButton(Common::Rect(260, 169, 284, 189), 243, &_iconSprites);
+	addButton(Common::Rect(286, 169, 310, 189), 177, &_iconSprites);
+	addButton(Common::Rect(236,  11, 308,  69),  61, &_iconSprites, false);
+	addButton(Common::Rect(239,  27, 312,  37),  49, &_iconSprites, false);
+	addButton(Common::Rect(239,  37, 312,  47),  50, &_iconSprites, false);
+	addButton(Common::Rect(239,  47, 312,  57),  51, &_iconSprites, false);
+}
+
 } // End of namespace Xeen
diff --git a/engines/xeen/interface.h b/engines/xeen/interface.h
index b19f031..475e71b 100644
--- a/engines/xeen/interface.h
+++ b/engines/xeen/interface.h
@@ -60,11 +60,16 @@ private:
 	int _powerShieldUIFrame;
 	int _holyBonusUIFrame;
 	int _heroismUIFrame;
+	int _flipUIFrame;
 	bool _isEarlyGame;
 	bool _buttonsLoaded;
 	Common::String _interfaceText;
 	int _hiliteChar;
 	int _intrIndex1;
+	bool _flipWtr;
+	bool _flag1;
+	bool _flag2;
+	byte _tillMove;
 
 	void loadSprites();
 
@@ -91,6 +96,10 @@ private:
 	void setOutdoorsMonsters();
 
 	void setOutdoorsObjects();
+
+	void moveMonsters();
+
+	void setIconButtons();
 public:
 	Interface(XeenEngine *vm);
 
diff --git a/engines/xeen/xeen.cpp b/engines/xeen/xeen.cpp
index 948b415..c2abdd9 100644
--- a/engines/xeen/xeen.cpp
+++ b/engines/xeen/xeen.cpp
@@ -52,7 +52,6 @@ XeenEngine::XeenEngine(OSystem *syst, const XeenGameDescription *gameDesc)
 	_face2State = 0;
 	_noDirectionSense = false;
 	_falling = false;
-	_tillMove = false;
 	_moveMonsters = false;
 	_mode = MODE_0;
 }
@@ -298,12 +297,13 @@ void XeenEngine::play() {
 	_events->setCursor(0);
 
 	_moveMonsters = true;
-	_tillMove = false;
 	if (_mode == MODE_0) {
 		_mode = MODE_1;
 		_screen->fadeIn(4);
 	}
 
+	_moveMonsters = true;
+
 	// Main game loop
 	while (!shouldQuit()) {
 		_events->pollEventsAndWait();
diff --git a/engines/xeen/xeen.h b/engines/xeen/xeen.h
index 776f319..44deaee 100644
--- a/engines/xeen/xeen.h
+++ b/engines/xeen/xeen.h
@@ -93,8 +93,6 @@ private:
 	const XeenGameDescription *_gameDescription;
 	Common::RandomSource _randomSource;
 	int _loadSaveSlot;
-	bool _moveMonsters;
-	bool _tillMove;
 
 	void showIntro();
 
@@ -146,6 +144,7 @@ public:
 	int _face2State;
 	bool _noDirectionSense;
 	bool _falling;
+	bool _moveMonsters;
 public:
 	XeenEngine(OSystem *syst, const XeenGameDescription *gameDesc);
 	virtual ~XeenEngine();


Commit: fa0d7722f1c7826887b6f2b28d2d6829c77c717a
    https://github.com/scummvm/scummvm/commit/fa0d7722f1c7826887b6f2b28d2d6829c77c717a
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-01-06T22:48:04-05:00

Commit Message:
XEEN: Work on loading sprites for monsters and objects in Map::load

Changed paths:
    engines/xeen/map.cpp
    engines/xeen/map.h
    engines/xeen/sprites.cpp
    engines/xeen/sprites.h



diff --git a/engines/xeen/map.cpp b/engines/xeen/map.cpp
index 5e98c51..f7620b1 100644
--- a/engines/xeen/map.cpp
+++ b/engines/xeen/map.cpp
@@ -619,6 +619,16 @@ bool MobStruct::synchronize(Common::SeekableReadStream &s) {
 
 /*------------------------------------------------------------------------*/
 
+MazeObject::MazeObject() {
+	_number = 0;
+	_frame = 0;
+	_id = 0;
+	_direction = DIR_NORTH;
+	_flipped = false;
+}	
+
+/*------------------------------------------------------------------------*/
+
 MonsterObjectData::MonsterObjectData(XeenEngine *vm): _vm(vm) {
 }
 
@@ -855,20 +865,60 @@ void Map::load(int mapId) {
 
 	// TODO: Switch setting flags that don't seem to ever be used
 
-	// Reload object data, since prior loop iterations replaced the data
-	// for the main map with all the surrounding mazes
-	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();
 
-	// TODO: Loop loading moer data / other / cbr? data
+	// Load secondary bj file for the objects
+	Common::String filename;
+	for (uint i = 0; i < _mobData._objects.size(); ++i) {
+		if (_vm->_party._cloudsEnd && _mobData._objects[i]._id == 85 &&
+				_vm->_party._mazeId == 27 && isDarkCc) {
+			// TODO: Flags set that don't seem to be used
+		} else if (_vm->_party._mazeId == 12 && _vm->_party._gameFlags[43] &&
+				_mobData._objects[i]._id == 118 && !isDarkCc) {
+			filename = "085.obj";
+			_mobData._objects[0]._id = 85;
+		} else {
+			filename = Common::String::format("%03u.%cbj", _mobData._objects[i]._id,
+				_mobData._objects[i]._id >= 100 ? 'o' : '0');
+		}
 
-	if (_isOutdoors) {
+		// Read in the secondary object data
+		File f(filename);
+		Common::Array<byte> &b = _mobData._objects[i]._objBj;
+		b.resize(f.size());
+		f.read(&b[0], f.size());
+	}
 
-	} else {
+	// Load sprite resources for monster standard and attack animations
+	int monsterNum = 1;
+	int monsterImgNums[95];
+	Common::fill(&monsterImgNums[0], &monsterImgNums[95], 0);
+	for (uint i = 0; i < _mobData._monsters.size(); ++i, ++monsterNum) {
+		MonsterStruct &monsterStruct = _monsterData[i];
+		int monsterImgNum = monsterStruct._imageNumber;
+		filename = Common::String::format("%03u.mon", monsterImgNum);
+
+		if (!monsterImgNums[monsterImgNum]) {
+			_mobData._monsters[i]._sprites.load(filename);
+		} else {
+			_mobData._monsters[i]._sprites = _mobData._monsters[
+				monsterImgNums[monsterImgNum] - 1]._sprites;
+		}
+
+		filename = Common::String::format("%03u.att", monsterImgNum);
+		if (!monsterImgNums[monsterImgNum]) {
+			_mobData._monsters[i]._attackSprites.load(filename);
+			monsterImgNums[monsterImgNum] = monsterNum;
+		} else {
+			_mobData._monsters[i]._attackSprites = _mobData._monsters[
+				monsterImgNums[monsterImgNum] - 1]._attackSprites;;
+		}
+	}
 
+	// Load wall picture sprite resources
+	for (uint i = 0; i < _mobData._wallImages.size(); ++i) {
+		filename = Common::String::format("%03u.pic", _mobData._wallImages[i]._id);
+		// TODO: Form WallImages struct like _monsters and _objects has
+		//_mobData._wallImages[i]._sprites.load(filename);
 	}
 }
 
diff --git a/engines/xeen/map.h b/engines/xeen/map.h
index 882e495..c4ab348 100644
--- a/engines/xeen/map.h
+++ b/engines/xeen/map.h
@@ -24,6 +24,7 @@
 #define XEEN_MAP_H
 
 #include "common/stream.h"
+#include "common/array.h"
 #include "common/rect.h"
 #include "xeen/party.h"
 #include "xeen/sprites.h"
@@ -199,12 +200,16 @@ public:
 };
 
 struct MazeObject {
+public:
 	Common::Point _position;
 	int _number;
 	int _frame;
 	int _id;
 	Direction _direction;
 	bool _flipped;
+	Common::Array<byte> _objBj;
+public:
+	MazeObject();
 };
 
 struct MazeMonster {
@@ -215,6 +220,8 @@ struct MazeMonster {
 	int _hp;
 	int _effect1, _effect2;
 	int _effect3;
+	SpriteResource _sprites;
+	SpriteResource _attackSprites;
 };
 
 class MonsterObjectData {
diff --git a/engines/xeen/sprites.cpp b/engines/xeen/sprites.cpp
index 598870d..74f2b1d 100644
--- a/engines/xeen/sprites.cpp
+++ b/engines/xeen/sprites.cpp
@@ -43,6 +43,21 @@ SpriteResource::~SpriteResource() {
 	clear();
 }
 
+SpriteResource &SpriteResource::operator=(const SpriteResource &src) {
+	delete[] _data;
+	_index.clear();
+	
+	_filesize = src._filesize;
+	_data = new byte[_filesize];
+	Common::copy(src._data, src._data + _filesize, _data);
+
+	_index.resize(src._index.size());
+	for (uint i = 0; i < src._index.size(); ++i)
+		_index[i] = src._index[i];
+
+	return *this;
+}
+
 void SpriteResource::load(const Common::String &filename) {
 	// Open the resource
 	File f(filename);
@@ -173,7 +188,10 @@ void SpriteResource::drawOffset(XSurface &dest, uint16 offset, const Common::Poi
 		destPos.x + xOffset + width, destPos.y + yOffset + height));
 }
 
-void SpriteResource::draw(XSurface &dest, int frame, const Common::Point &destPos) const {
+void SpriteResource::draw(XSurface &dest, int frame, const Common::Point &destPos, int flags) const {
+	// TODO: Support the different flags
+	assert(!flags);
+
 	drawOffset(dest, _index[frame]._offset1, destPos);
 	if (_index[frame]._offset2)
 		drawOffset(dest, _index[frame]._offset2, destPos);
diff --git a/engines/xeen/sprites.h b/engines/xeen/sprites.h
index 998d5d3..7f937ab 100644
--- a/engines/xeen/sprites.h
+++ b/engines/xeen/sprites.h
@@ -33,6 +33,8 @@ namespace Xeen {
 
 class XeenEngine;
 
+enum SpriteFlags { SPRFLAG_HORIZ_FLIPPED = 0x8000 };
+
 class SpriteResource {
 private:
 	struct IndexEntry {
@@ -49,11 +51,13 @@ public:
 
 	virtual ~SpriteResource();
 
+	SpriteResource &operator=(const SpriteResource &src);
+
 	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 Common::Point &destPos, int flags = 0) const;
 
 	void draw(XSurface &dest, int frame) const;
 


Commit: be53adbefc09f58325015b52b88f9290509a39f1
    https://github.com/scummvm/scummvm/commit/be53adbefc09f58325015b52b88f9290509a39f1
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-01-07T08:47:24-05:00

Commit Message:
XEEN: Implemented map loading of wall item sprites

Changed paths:
    engines/xeen/map.cpp
    engines/xeen/map.h



diff --git a/engines/xeen/map.cpp b/engines/xeen/map.cpp
index f7620b1..fae9efe 100644
--- a/engines/xeen/map.cpp
+++ b/engines/xeen/map.cpp
@@ -629,6 +629,24 @@ MazeObject::MazeObject() {
 
 /*------------------------------------------------------------------------*/
 
+MazeMonster::MazeMonster() {
+	_frame = 0;
+	_id = 0;
+	_refId = 0;
+	_hp = 0;
+	_effect1 = _effect2 = 0;
+	_effect3 = 0;
+}
+
+/*------------------------------------------------------------------------*/
+
+MazeWallItem::MazeWallItem() {
+	_id = 0;
+	_direction = DIR_NORTH;
+}
+
+/*------------------------------------------------------------------------*/
+
 MonsterObjectData::MonsterObjectData(XeenEngine *vm): _vm(vm) {
 }
 
@@ -636,12 +654,13 @@ void MonsterObjectData::synchronize(Common::SeekableReadStream &s,
 		bool isOutdoors, MonsterData monsterData) {
 	_objects.clear();
 	_monsters.clear();
-	_wallPicIds.clear();
-	_wallImages.clear();
+	_wallItems.clear();
 	Common::Array<int> objectSprites;
 	Common::Array<int> monsterIds;
+	Common::Array<int> wallPicIds;
 	Common::Array<MobStruct> objData;
 	Common::Array<MobStruct> monData;
+	Common::Array<MobStruct> wallItemData;
 	byte b;
 
 	for (int i = 0; i < 16; ++i) {
@@ -654,7 +673,7 @@ void MonsterObjectData::synchronize(Common::SeekableReadStream &s,
 	}
 	for (int i = 0; i < 16; ++i) {
 		if ((b = s.readByte()) != 0xff)
-			_wallPicIds.push_back(b);
+			wallPicIds.push_back(b);
 	}
 
 	MobStruct mobStruct;
@@ -664,7 +683,7 @@ void MonsterObjectData::synchronize(Common::SeekableReadStream &s,
 		monData.push_back(mobStruct);
 	if (!isOutdoors) {
 		while (mobStruct.synchronize(s))
-			_wallImages.push_back(mobStruct);
+			wallItemData.push_back(mobStruct);
 	}
 
 	// Merge up objects
@@ -693,6 +712,16 @@ void MonsterObjectData::synchronize(Common::SeekableReadStream &s,
 		if (mon._animationEffect)
 			dest._effect3 = _vm->getRandomNumber(7);
 	}
+
+	// Merge up wall items
+	_wallItems.clear();
+	for (uint i = 0; i < wallItemData.size(); ++i) {
+		MazeWallItem &dest = _wallItems[i];
+		dest._position = wallItemData[i]._pos;
+		dest._id = wallItemData[i]._id;
+		dest._refId = wallPicIds[dest._id];
+		dest._direction = wallItemData[i]._direction;
+	}
 }
 
 /*------------------------------------------------------------------------*/
@@ -915,10 +944,9 @@ void Map::load(int mapId) {
 	}
 
 	// Load wall picture sprite resources
-	for (uint i = 0; i < _mobData._wallImages.size(); ++i) {
-		filename = Common::String::format("%03u.pic", _mobData._wallImages[i]._id);
-		// TODO: Form WallImages struct like _monsters and _objects has
-		//_mobData._wallImages[i]._sprites.load(filename);
+	for (uint i = 0; i < _mobData._wallItems.size(); ++i) {
+		filename = Common::String::format("%03u.pic", _mobData._wallItems[i]._refId);
+		_mobData._wallItems[i]._sprites.load(filename);
 	}
 }
 
diff --git a/engines/xeen/map.h b/engines/xeen/map.h
index c4ab348..f39f2d8 100644
--- a/engines/xeen/map.h
+++ b/engines/xeen/map.h
@@ -208,7 +208,7 @@ public:
 	Direction _direction;
 	bool _flipped;
 	Common::Array<byte> _objBj;
-public:
+
 	MazeObject();
 };
 
@@ -222,6 +222,19 @@ struct MazeMonster {
 	int _effect3;
 	SpriteResource _sprites;
 	SpriteResource _attackSprites;
+
+	MazeMonster();
+};
+
+class MazeWallItem {
+public:
+	Common::Point _position;
+	int _id;
+	int _refId;
+	Direction _direction;
+	SpriteResource _sprites;
+public:
+	MazeWallItem();
 };
 
 class MonsterObjectData {
@@ -230,8 +243,7 @@ private:
 public:
 	Common::Array<MazeObject> _objects;
 	Common::Array<MazeMonster> _monsters;
-	Common::Array<int> _wallPicIds;
-	Common::Array<MobStruct> _wallImages;
+	Common::Array<MazeWallItem> _wallItems;
 public:
 	MonsterObjectData(XeenEngine *vm);
 


Commit: cd7c00ca8c93258d7b6c3ef92fc32452df1052cb
    https://github.com/scummvm/scummvm/commit/cd7c00ca8c93258d7b6c3ef92fc32452df1052cb
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-01-07T19:40:13-05:00

Commit Message:
XEEN: Minor standardisation on monster/object Ids

Changed paths:
    engines/xeen/map.cpp
    engines/xeen/map.h



diff --git a/engines/xeen/map.cpp b/engines/xeen/map.cpp
index fae9efe..15c696b 100644
--- a/engines/xeen/map.cpp
+++ b/engines/xeen/map.cpp
@@ -620,9 +620,9 @@ bool MobStruct::synchronize(Common::SeekableReadStream &s) {
 /*------------------------------------------------------------------------*/
 
 MazeObject::MazeObject() {
-	_number = 0;
-	_frame = 0;
 	_id = 0;
+	_frame = 0;
+	_refId = 0;
 	_direction = DIR_NORTH;
 	_flipped = false;
 }	
@@ -691,8 +691,8 @@ void MonsterObjectData::synchronize(Common::SeekableReadStream &s,
 	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._id = objData[i]._id;
+		dest._refId = objectSprites[dest._id];
 		dest._direction = objData[i]._direction;
 		dest._frame = 100;
 	}
@@ -857,7 +857,7 @@ void Map::load(int mapId) {
 				_mazeName = Common::String(mazeName);
 				fText.close();
 
-				// Load the monster data
+				// Load the monster/object data
 				Common::String mobName = Common::String::format("maze%c%03u.mob",
 					(mapId >= 100) ? 'x' : '0', mapId);
 				File mobFile(mobName);
@@ -894,27 +894,29 @@ void Map::load(int mapId) {
 
 	// TODO: Switch setting flags that don't seem to ever be used
 
+	// Reload the monster data for the main maze that we're loading
+	Common::String filename = Common::String::format("maze%c%03u.mob",
+		(_vm->_party._mazeId >= 100) ? 'x' : '0', _vm->_party._mazeId);
+	File mobFile(filename);
+	_mobData.synchronize(mobFile, _isOutdoors, _monsterData);
+	mobFile.close();
 
-	// Load secondary bj file for the objects
-	Common::String filename;
+	// Load sprites for the objects
 	for (uint i = 0; i < _mobData._objects.size(); ++i) {
-		if (_vm->_party._cloudsEnd && _mobData._objects[i]._id == 85 &&
+		if (_vm->_party._cloudsEnd && _mobData._objects[i]._refId == 85 &&
 				_vm->_party._mazeId == 27 && isDarkCc) {
 			// TODO: Flags set that don't seem to be used
 		} else if (_vm->_party._mazeId == 12 && _vm->_party._gameFlags[43] &&
-				_mobData._objects[i]._id == 118 && !isDarkCc) {
+				_mobData._objects[i]._refId == 118 && !isDarkCc) {
 			filename = "085.obj";
 			_mobData._objects[0]._id = 85;
 		} else {
-			filename = Common::String::format("%03u.%cbj", _mobData._objects[i]._id,
-				_mobData._objects[i]._id >= 100 ? 'o' : '0');
+			filename = Common::String::format("%03d.%cbj", _mobData._objects[i]._refId,
+				_mobData._objects[i]._refId >= 100 ? 'o' : '0');
 		}
 
-		// Read in the secondary object data
-		File f(filename);
-		Common::Array<byte> &b = _mobData._objects[i]._objBj;
-		b.resize(f.size());
-		f.read(&b[0], f.size());
+		// Read in the object sprites
+		_mobData._objects[i]._sprites.load(filename);
 	}
 
 	// Load sprite resources for monster standard and attack animations
diff --git a/engines/xeen/map.h b/engines/xeen/map.h
index f39f2d8..7c0344b 100644
--- a/engines/xeen/map.h
+++ b/engines/xeen/map.h
@@ -202,12 +202,12 @@ public:
 struct MazeObject {
 public:
 	Common::Point _position;
-	int _number;
-	int _frame;
 	int _id;
+	int _frame;
+	int _refId;
 	Direction _direction;
 	bool _flipped;
-	Common::Array<byte> _objBj;
+	SpriteResource _sprites;
 
 	MazeObject();
 };


Commit: 96d086ab9cc28a2145072487b60036f916b28774
    https://github.com/scummvm/scummvm/commit/96d086ab9cc28a2145072487b60036f916b28774
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-01-07T22:11:18-05:00

Commit Message:
XEEN: Add prefix support to CC files, initial save state fixes

Changed paths:
    engines/xeen/files.cpp
    engines/xeen/files.h
    engines/xeen/map.cpp
    engines/xeen/saves.cpp



diff --git a/engines/xeen/files.cpp b/engines/xeen/files.cpp
index b1358d4..79387f2 100644
--- a/engines/xeen/files.cpp
+++ b/engines/xeen/files.cpp
@@ -39,6 +39,14 @@ uint16 BaseCCArchive::convertNameToId(const Common::String &resourceName) const
 	Common::String name = resourceName;
 	name.toUppercase();
 
+	// Check if a resource number is being directly specified
+	if (name.size() == 4) {
+		char *endPtr;
+		uint16 num = (uint16)strtol(name.c_str(), &endPtr, 16);
+		if (!*endPtr)
+			return num;
+	}
+
 	const byte *msgP = (const byte *)name.c_str();
 	int total = *msgP++;
 	for (; *msgP; total += *msgP++) {
@@ -121,7 +129,15 @@ int BaseCCArchive::listMembers(Common::ArchiveMemberList &list) const {
 /*------------------------------------------------------------------------*/
 
 CCArchive::CCArchive(const Common::String &filename, bool encoded): 
-		_filename(filename), _encoded(encoded) {
+		BaseCCArchive(), _filename(filename), _encoded(encoded) {
+	File f(filename);
+	loadIndex(&f);
+}
+
+CCArchive::CCArchive(const Common::String &filename, const Common::String &prefix, 
+		bool encoded): BaseCCArchive(), _filename(filename), 
+		_prefix(prefix), _encoded(encoded) {
+	_prefix.toLowercase();
 	File f(filename);
 	loadIndex(&f);
 }
@@ -129,6 +145,25 @@ CCArchive::CCArchive(const Common::String &filename, bool encoded):
 CCArchive::~CCArchive() {
 }
 
+bool CCArchive::getHeaderEntry(const Common::String &resourceName, CCEntry &ccEntry) const {
+	Common::String resName = resourceName;
+
+	if (!_prefix.empty() && resName.contains('|')) {
+		resName.toLowercase();
+		Common::String prefix = _prefix + "|";
+
+		if (!strncmp(resName.c_str(), prefix.c_str(), prefix.size()))
+			// Matching CC prefix, so strip it off and allow processing to
+			// continue onto the base getHeaderEntry method
+			resName = Common::String(resName.c_str() + prefix.size());
+		else
+			// Not matching prefix, so don't allow a match
+			return false;
+	}
+
+	return BaseCCArchive::getHeaderEntry(resName, ccEntry);
+}
+
 Common::SeekableReadStream *CCArchive::createReadStreamForMember(const Common::String &name) const {
 	CCEntry ccEntry;
 
@@ -166,9 +201,9 @@ FileManager::FileManager(XeenEngine *vm) {
 
 	_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"));
+		SearchMan.add("dark", new CCArchive("dark.cc", "dark", true));
+	SearchMan.add("xeen", new CCArchive("xeen.cc", "xeen", true));
+	SearchMan.add("intro", new CCArchive("intro.cc", "intro", true));
 }
 
 /*------------------------------------------------------------------------*/
@@ -181,4 +216,9 @@ void File::openFile(const Common::String &filename) {
 		error("Could not open file - %s", filename.c_str());
 }
 
+void File::openFile(const Common::String &filename, Common::Archive &archive) {
+	if (!Common::File::open(filename, archive))
+		error("Could not open file - %s", filename.c_str());
+}
+
 } // End of namespace Xeen
diff --git a/engines/xeen/files.h b/engines/xeen/files.h
index 6e560ca..343aea1 100644
--- a/engines/xeen/files.h
+++ b/engines/xeen/files.h
@@ -52,9 +52,13 @@ class File : public Common::File {
 public:
 	File() : Common::File() {}
 	File(const Common::String &filename) { openFile(filename); }
+	File(const Common::String &filename, Common::Archive &archive) {
+		openFile(filename, archive);
+	}
 	virtual ~File() {}
 
 	void openFile(const Common::String &filename);
+	void openFile(const Common::String &filename, Common::Archive &archive);
 };
 
 /**
@@ -82,7 +86,7 @@ protected:
 
 	void loadIndex(Common::SeekableReadStream *stream);
 
-	bool getHeaderEntry(const Common::String &resourceName, CCEntry &ccEntry) const;
+	virtual bool getHeaderEntry(const Common::String &resourceName, CCEntry &ccEntry) const;
 public:
 	BaseCCArchive() {}
 
@@ -98,9 +102,13 @@ public:
 class CCArchive : public BaseCCArchive {
 private:
 	Common::String _filename;
+	Common::String _prefix;
 	bool _encoded;
+protected:
+	virtual bool getHeaderEntry(const Common::String &resourceName, CCEntry &ccEntry) const;
 public:
-	CCArchive(const Common::String &filename, bool encoded = true);
+	CCArchive(const Common::String &filename, bool encoded);
+	CCArchive(const Common::String &filename, const Common::String &prefix, bool encoded);
 	virtual ~CCArchive();
 
 	// Archive implementation
diff --git a/engines/xeen/map.cpp b/engines/xeen/map.cpp
index 15c696b..a3a4063 100644
--- a/engines/xeen/map.cpp
+++ b/engines/xeen/map.cpp
@@ -714,7 +714,7 @@ void MonsterObjectData::synchronize(Common::SeekableReadStream &s,
 	}
 
 	// Merge up wall items
-	_wallItems.clear();
+	_wallItems.resize(1);
 	for (uint i = 0; i < wallItemData.size(); ++i) {
 		MazeWallItem &dest = _wallItems[i];
 		dest._position = wallItemData[i]._pos;
@@ -897,7 +897,7 @@ void Map::load(int mapId) {
 	// Reload the monster data for the main maze that we're loading
 	Common::String filename = Common::String::format("maze%c%03u.mob",
 		(_vm->_party._mazeId >= 100) ? 'x' : '0', _vm->_party._mazeId);
-	File mobFile(filename);
+	File mobFile(filename, *_vm->_saves);
 	_mobData.synchronize(mobFile, _isOutdoors, _monsterData);
 	mobFile.close();
 
diff --git a/engines/xeen/saves.cpp b/engines/xeen/saves.cpp
index ae29dd1..36bb7bd 100644
--- a/engines/xeen/saves.cpp
+++ b/engines/xeen/saves.cpp
@@ -99,10 +99,39 @@ void SavesManager::load(Common::SeekableReadStream *stream) {
  * Sets up the dynamic data for the game for a new game
  */
 void SavesManager::reset() {
-	Common::String name(_vm->getGameID() == GType_Clouds ? "xeen.cur" : "dark.cur");
-	File f(name);
+	Common::String prefix = _vm->getGameID() == GType_Clouds ? "xeen|" : "dark|";
+	Common::MemoryWriteStreamDynamic saveFile(DisposeAfterUse::YES);
+	Common::File fIn;
+
+	for (int i = 0; i <= 5; ++i) {
+		Common::String filename = prefix + Common::String::format("2A%dC", i);
+		if (fIn.exists(filename)) {
+			// Read in the next resource
+			fIn.open(filename);
+			byte *data = new byte[fIn.size()];
+			fIn.read(data, fIn.size());
+
+			// Copy it to the combined savefile resource
+			saveFile.write(data, fIn.size());
+			delete[] data;
+			fIn.close();
+		}
+	}
 
+	Common::MemoryReadStream f(saveFile.getData(), saveFile.size());
 	load(&f);
+
+	// Set up the party and characters from dark.cur
+	CCArchive gameCur("xeen.cur", false);
+	File fParty("maze.pty", gameCur);
+	Common::Serializer sParty(&fParty, nullptr);
+	_party.synchronize(sParty);
+	fParty.close();
+
+	File fChar("maze.chr", gameCur);
+	Common::Serializer sChar(&fChar, nullptr);
+	_roster.synchronize(sChar);
+	fChar.close();
 }
 
 void SavesManager::readCharFile() {


Commit: f9414fe5259547b6499d9fb8ccb54bdc0bebb0ed
    https://github.com/scummvm/scummvm/commit/f9414fe5259547b6499d9fb8ccb54bdc0bebb0ed
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-01-07T22:51:03-05:00

Commit Message:
XEEN: Further fix for savegame initialization

Changed paths:
    engines/xeen/map.cpp
    engines/xeen/saves.cpp



diff --git a/engines/xeen/map.cpp b/engines/xeen/map.cpp
index a3a4063..63d5542 100644
--- a/engines/xeen/map.cpp
+++ b/engines/xeen/map.cpp
@@ -829,7 +829,7 @@ void Map::load(int mapId) {
 
 		if (mapId != 0) {
 			// Load in the maze's data file
-			Common::String datName = Common::String::format("maze%c%03u.dat",
+			Common::String datName = Common::String::format("maze%c%03d.dat",
 				(_vm->_party._mazeId >= 100) ? 'x' : '0', _vm->_party._mazeId);
 			File datFile(datName);
 			mazeData->synchronize(datFile);
@@ -847,7 +847,7 @@ void Map::load(int mapId) {
 			// Handle loading text data
 			if (!textLoaded) {
 				textLoaded = true;
-				Common::String txtName = Common::String::format("%s%c%03u.txt",
+				Common::String txtName = Common::String::format("%s%c%03d.txt",
 					isDarkCc ? "dark" : "xeen", mapId >= 100 ? 'x' : '0', mapId);
 				File fText(txtName);
 				char mazeName[33];
@@ -858,13 +858,13 @@ void Map::load(int mapId) {
 				fText.close();
 
 				// Load the monster/object data
-				Common::String mobName = Common::String::format("maze%c%03u.mob",
+				Common::String mobName = Common::String::format("maze%c%03d.mob",
 					(mapId >= 100) ? 'x' : '0', mapId);
 				File mobFile(mobName);
 				_mobData.synchronize(mobFile, _isOutdoors, _monsterData);
 				mobFile.close();
 
-				Common::String headName = Common::String::format("aaze%c%03u.hed",
+				Common::String headName = Common::String::format("aaze%c%03d.hed",
 					(mapId >= 100) ? 'x' : '0', mapId);
 				File headFile(headName);
 				_headData.synchronize(headFile);
@@ -895,7 +895,7 @@ void Map::load(int mapId) {
 	// TODO: Switch setting flags that don't seem to ever be used
 
 	// Reload the monster data for the main maze that we're loading
-	Common::String filename = Common::String::format("maze%c%03u.mob",
+	Common::String filename = Common::String::format("maze%c%03d.mob",
 		(_vm->_party._mazeId >= 100) ? 'x' : '0', _vm->_party._mazeId);
 	File mobFile(filename, *_vm->_saves);
 	_mobData.synchronize(mobFile, _isOutdoors, _monsterData);
@@ -926,7 +926,7 @@ void Map::load(int mapId) {
 	for (uint i = 0; i < _mobData._monsters.size(); ++i, ++monsterNum) {
 		MonsterStruct &monsterStruct = _monsterData[i];
 		int monsterImgNum = monsterStruct._imageNumber;
-		filename = Common::String::format("%03u.mon", monsterImgNum);
+		filename = Common::String::format("%03d.mon", monsterImgNum);
 
 		if (!monsterImgNums[monsterImgNum]) {
 			_mobData._monsters[i]._sprites.load(filename);
@@ -935,7 +935,7 @@ void Map::load(int mapId) {
 				monsterImgNums[monsterImgNum] - 1]._sprites;
 		}
 
-		filename = Common::String::format("%03u.att", monsterImgNum);
+		filename = Common::String::format("%03d.att", monsterImgNum);
 		if (!monsterImgNums[monsterImgNum]) {
 			_mobData._monsters[i]._attackSprites.load(filename);
 			monsterImgNums[monsterImgNum] = monsterNum;
@@ -947,7 +947,7 @@ void Map::load(int mapId) {
 
 	// Load wall picture sprite resources
 	for (uint i = 0; i < _mobData._wallItems.size(); ++i) {
-		filename = Common::String::format("%03u.pic", _mobData._wallItems[i]._refId);
+		filename = Common::String::format("%03d.pic", _mobData._wallItems[i]._refId);
 		_mobData._wallItems[i]._sprites.load(filename);
 	}
 }
diff --git a/engines/xeen/saves.cpp b/engines/xeen/saves.cpp
index 36bb7bd..404e349 100644
--- a/engines/xeen/saves.cpp
+++ b/engines/xeen/saves.cpp
@@ -103,8 +103,9 @@ void SavesManager::reset() {
 	Common::MemoryWriteStreamDynamic saveFile(DisposeAfterUse::YES);
 	Common::File fIn;
 
-	for (int i = 0; i <= 5; ++i) {
-		Common::String filename = prefix + Common::String::format("2A%dC", i);
+	const int RESOURCES[6] = { 0x2A0C, 0x2A1C, 0x2A2C, 0x2A3C, 0x284C, 0x2A5C };
+	for (int i = 0; i < 6; ++i) {
+		Common::String filename = prefix + Common::String::format("%.4x", RESOURCES[i]);
 		if (fIn.exists(filename)) {
 			// Read in the next resource
 			fIn.open(filename);


Commit: 03952cd9d353c4af393da7ffeb524bcdb5746f34
    https://github.com/scummvm/scummvm/commit/03952cd9d353c4af393da7ffeb524bcdb5746f34
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-01-08T20:23:54-05:00

Commit Message:
XEEN: Fix to load correct default savegame

Changed paths:
    engines/xeen/saves.cpp



diff --git a/engines/xeen/saves.cpp b/engines/xeen/saves.cpp
index 404e349..e6bfa80 100644
--- a/engines/xeen/saves.cpp
+++ b/engines/xeen/saves.cpp
@@ -99,7 +99,7 @@ void SavesManager::load(Common::SeekableReadStream *stream) {
  * Sets up the dynamic data for the game for a new game
  */
 void SavesManager::reset() {
-	Common::String prefix = _vm->getGameID() == GType_Clouds ? "xeen|" : "dark|";
+	Common::String prefix = _vm->getGameID() != GType_DarkSide ? "xeen|" : "dark|";
 	Common::MemoryWriteStreamDynamic saveFile(DisposeAfterUse::YES);
 	Common::File fIn;
 


Commit: 00ef21e2a22dc84531d325bc95734b63b5c7daed
    https://github.com/scummvm/scummvm/commit/00ef21e2a22dc84531d325bc95734b63b5c7daed
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-01-08T23:02:46-05:00

Commit Message:
XEEN: Fixed monster/object data merging and sprite loading

Changed paths:
    engines/xeen/map.cpp
    engines/xeen/map.h



diff --git a/engines/xeen/map.cpp b/engines/xeen/map.cpp
index 63d5542..52dbc83 100644
--- a/engines/xeen/map.cpp
+++ b/engines/xeen/map.cpp
@@ -622,9 +622,10 @@ bool MobStruct::synchronize(Common::SeekableReadStream &s) {
 MazeObject::MazeObject() {
 	_id = 0;
 	_frame = 0;
-	_refId = 0;
+	_spriteId = 0;
 	_direction = DIR_NORTH;
 	_flipped = false;
+	_sprites = nullptr;
 }	
 
 /*------------------------------------------------------------------------*/
@@ -632,17 +633,21 @@ MazeObject::MazeObject() {
 MazeMonster::MazeMonster() {
 	_frame = 0;
 	_id = 0;
-	_refId = 0;
+	_spriteId = 0;
 	_hp = 0;
 	_effect1 = _effect2 = 0;
 	_effect3 = 0;
+	_sprites = nullptr;
+	_attackSprites = nullptr;
 }
 
 /*------------------------------------------------------------------------*/
 
 MazeWallItem::MazeWallItem() {
 	_id = 0;
+	_spriteId = 0;
 	_direction = DIR_NORTH;
+	_sprites = nullptr;
 }
 
 /*------------------------------------------------------------------------*/
@@ -652,76 +657,83 @@ MonsterObjectData::MonsterObjectData(XeenEngine *vm): _vm(vm) {
 
 void MonsterObjectData::synchronize(Common::SeekableReadStream &s, 
 		bool isOutdoors, MonsterData monsterData) {
+	_objectSprites.clear();
+	_monsterSprites.clear();
+	_monsterAttackSprites.clear();
+	_wallItemSprites.clear();
 	_objects.clear();
 	_monsters.clear();
 	_wallItems.clear();
-	Common::Array<int> objectSprites;
-	Common::Array<int> monsterIds;
-	Common::Array<int> wallPicIds;
-	Common::Array<MobStruct> objData;
-	Common::Array<MobStruct> monData;
-	Common::Array<MobStruct> wallItemData;
+
+	Common::Array<MobStruct> mobStructs;
 	byte b;
 
 	for (int i = 0; i < 16; ++i) {
 		if ((b = s.readByte()) != 0xff)
-			objectSprites.push_back(b);
+			_objectSprites.push_back(SpriteResourceEntry(b));
 	}
 	for (int i = 0; i < 16; ++i) {
 		if ((b = s.readByte()) != 0xff)
-			monsterIds.push_back(b);
+			_monsterSprites.push_back(SpriteResourceEntry(b));
 	}
 	for (int i = 0; i < 16; ++i) {
 		if ((b = s.readByte()) != 0xff)
-			wallPicIds.push_back(b);
+			_wallItemSprites.push_back(SpriteResourceEntry(b));
 	}
 
+	// Merge together object data
 	MobStruct mobStruct;
-	while (mobStruct.synchronize(s))
-		objData.push_back(mobStruct);
-	while (mobStruct.synchronize(s))
-		monData.push_back(mobStruct);
-	if (!isOutdoors) {
-		while (mobStruct.synchronize(s))
-			wallItemData.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._id = objData[i]._id;
-		dest._refId = objectSprites[dest._id];
-		dest._direction = objData[i]._direction;
-		dest._frame = 100;
-	}
-
-	// merge up monsters
-	_monsters.resize(monData.size());
-	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);
-	}
+	mobStruct.synchronize(s);
+	do {
+		MazeObject obj;
+		obj._position = mobStruct._pos;
+		obj._id = mobStruct._id;
+		obj._direction = mobStruct._direction;
+		obj._frame = 100;
+		obj._spriteId = _objectSprites[obj._id]._spriteId;
+		obj._sprites = &_objectSprites[obj._id]._sprites;
+
+		_objects.push_back(obj);
+		mobStruct.synchronize(s);
+	} while (mobStruct._id != 255 || mobStruct._pos.x != -1);
+
+	// Merge together monster data
+	mobStruct.synchronize(s);
+	do {
+		MazeMonster mon;
+		mon._position = mobStruct._pos;
+		mon._id = mobStruct._id;
+		mon._spriteId = _monsterSprites[mon._id]._spriteId;
+		mon._sprites = &_monsterSprites[mon._id]._sprites;
+		mon._attackSprites = &_monsterSprites[mon._id]._attackSprites;
+
+		MonsterStruct &md = monsterData[mon._spriteId];
+		mon._hp = md._hp;
+		mon._frame = _vm->getRandomNumber(7);
+		mon._effect1 = mon._effect2 = md._animationEffect;
+		if (md._animationEffect)
+			mon._effect3 = _vm->getRandomNumber(7);
+
+		_monsters.push_back(mon);
+		mobStruct.synchronize(s);
+	} while (mobStruct._id != 255 || mobStruct._pos.x != -1);
+
+	// Merge together wall item data
+	mobStruct.synchronize(s);
+	do {
+		if (mobStruct._id < (int)_wallItemSprites.size()) {
+			MazeWallItem wi;
+			wi._position = mobStruct._pos;
+			wi._id = mobStruct._id;
+			wi._direction = mobStruct._direction;
+			wi._spriteId = _wallItemSprites[wi._id]._spriteId;
+			wi._sprites = &_wallItemSprites[wi._id]._sprites;
+
+			_wallItems.push_back(wi);
+		}
 
-	// Merge up wall items
-	_wallItems.resize(1);
-	for (uint i = 0; i < wallItemData.size(); ++i) {
-		MazeWallItem &dest = _wallItems[i];
-		dest._position = wallItemData[i]._pos;
-		dest._id = wallItemData[i]._id;
-		dest._refId = wallPicIds[dest._id];
-		dest._direction = wallItemData[i]._direction;
-	}
+		mobStruct.synchronize(s);
+	} while (mobStruct._id != 255 || mobStruct._pos.x != -1);
 }
 
 /*------------------------------------------------------------------------*/
@@ -893,7 +905,7 @@ void Map::load(int mapId) {
 	}
 
 	// TODO: Switch setting flags that don't seem to ever be used
-
+ 
 	// Reload the monster data for the main maze that we're loading
 	Common::String filename = Common::String::format("maze%c%03d.mob",
 		(_vm->_party._mazeId >= 100) ? 'x' : '0', _vm->_party._mazeId);
@@ -902,53 +914,37 @@ void Map::load(int mapId) {
 	mobFile.close();
 
 	// Load sprites for the objects
-	for (uint i = 0; i < _mobData._objects.size(); ++i) {
-		if (_vm->_party._cloudsEnd && _mobData._objects[i]._refId == 85 &&
+	for (uint i = 0; i < _mobData._objectSprites.size(); ++i) {
+		if (_vm->_party._cloudsEnd && _mobData._objectSprites[i]._spriteId == 85 &&
 				_vm->_party._mazeId == 27 && isDarkCc) {
 			// TODO: Flags set that don't seem to be used
 		} else if (_vm->_party._mazeId == 12 && _vm->_party._gameFlags[43] &&
-				_mobData._objects[i]._refId == 118 && !isDarkCc) {
+			_mobData._objectSprites[i]._spriteId == 118 && !isDarkCc) {
 			filename = "085.obj";
-			_mobData._objects[0]._id = 85;
+			_mobData._objectSprites[0]._spriteId = 85;
 		} else {
-			filename = Common::String::format("%03d.%cbj", _mobData._objects[i]._refId,
-				_mobData._objects[i]._refId >= 100 ? 'o' : '0');
+			filename = Common::String::format("%03d.%cbj", 
+				_mobData._objectSprites[i]._spriteId,
+				_mobData._objectSprites[i]._spriteId >= 100 ? '0' : 'o');
 		}
 
 		// Read in the object sprites
-		_mobData._objects[i]._sprites.load(filename);
+		_mobData._objectSprites[i]._sprites.load(filename);
 	}
 
-	// Load sprite resources for monster standard and attack animations
-	int monsterNum = 1;
-	int monsterImgNums[95];
-	Common::fill(&monsterImgNums[0], &monsterImgNums[95], 0);
-	for (uint i = 0; i < _mobData._monsters.size(); ++i, ++monsterNum) {
-		MonsterStruct &monsterStruct = _monsterData[i];
-		int monsterImgNum = monsterStruct._imageNumber;
-		filename = Common::String::format("%03d.mon", monsterImgNum);
-
-		if (!monsterImgNums[monsterImgNum]) {
-			_mobData._monsters[i]._sprites.load(filename);
-		} else {
-			_mobData._monsters[i]._sprites = _mobData._monsters[
-				monsterImgNums[monsterImgNum] - 1]._sprites;
-		}
+	// Load sprites for the monsters
+	for (uint i = 0; i < _mobData._monsterSprites.size(); ++i) {
+		filename = Common::String::format("%03d.mon", _mobData._objectSprites[i]._spriteId);
+		_mobData._monsterSprites[i]._sprites.load(filename);
 
-		filename = Common::String::format("%03d.att", monsterImgNum);
-		if (!monsterImgNums[monsterImgNum]) {
-			_mobData._monsters[i]._attackSprites.load(filename);
-			monsterImgNums[monsterImgNum] = monsterNum;
-		} else {
-			_mobData._monsters[i]._attackSprites = _mobData._monsters[
-				monsterImgNums[monsterImgNum] - 1]._attackSprites;;
-		}
+		filename = Common::String::format("%03d.att", _mobData._objectSprites[i]._spriteId);
+		_mobData._monsterSprites[i]._attackSprites.load(filename);
 	}
 
 	// Load wall picture sprite resources
-	for (uint i = 0; i < _mobData._wallItems.size(); ++i) {
-		filename = Common::String::format("%03d.pic", _mobData._wallItems[i]._refId);
-		_mobData._wallItems[i]._sprites.load(filename);
+	for (uint i = 0; i < _mobData._wallItemSprites.size(); ++i) {
+		filename = Common::String::format("%03d.pic", _mobData._wallItems[i]._spriteId);
+		_mobData._wallItemSprites[i]._sprites.load(filename);
 	}
 }
 
diff --git a/engines/xeen/map.h b/engines/xeen/map.h
index 7c0344b..1d11bdc 100644
--- a/engines/xeen/map.h
+++ b/engines/xeen/map.h
@@ -204,10 +204,10 @@ public:
 	Common::Point _position;
 	int _id;
 	int _frame;
-	int _refId;
+	int _spriteId;
 	Direction _direction;
 	bool _flipped;
-	SpriteResource _sprites;
+	SpriteResource *_sprites;
 
 	MazeObject();
 };
@@ -216,12 +216,12 @@ struct MazeMonster {
 	Common::Point _position;
 	int _frame;
 	int _id;
-	int _refId;
+	int _spriteId;
 	int _hp;
 	int _effect1, _effect2;
 	int _effect3;
-	SpriteResource _sprites;
-	SpriteResource _attackSprites;
+	SpriteResource *_sprites;
+	SpriteResource *_attackSprites;
 
 	MazeMonster();
 };
@@ -230,16 +230,32 @@ class MazeWallItem {
 public:
 	Common::Point _position;
 	int _id;
-	int _refId;
+	int _spriteId;
 	Direction _direction;
-	SpriteResource _sprites;
+	SpriteResource *_sprites;
 public:
 	MazeWallItem();
 };
 
+class Map;
+
 class MonsterObjectData {
+	friend class Map;
+public:
+	struct SpriteResourceEntry {
+		int _spriteId;
+		SpriteResource _sprites;
+		SpriteResource _attackSprites;
+
+		SpriteResourceEntry() { _spriteId = -1; }
+		SpriteResourceEntry(int spriteId): _spriteId(spriteId) { }
+	};
 private:
 	XeenEngine *_vm;
+	Common::Array<SpriteResourceEntry> _objectSprites;
+	Common::Array<SpriteResourceEntry> _monsterSprites;
+	Common::Array<SpriteResourceEntry> _monsterAttackSprites;
+	Common::Array<SpriteResourceEntry> _wallItemSprites;
 public:
 	Common::Array<MazeObject> _objects;
 	Common::Array<MazeMonster> _monsters;


Commit: 08e64d0a6146b9fde774467cc1906f230571f72d
    https://github.com/scummvm/scummvm/commit/08e64d0a6146b9fde774467cc1906f230571f72d
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-01-09T08:29:28-05:00

Commit Message:
XEEN: Added indoor/outdoor draw structure lists

Changed paths:
    engines/xeen/interface.cpp
    engines/xeen/interface.h
    engines/xeen/sprites.h



diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp
index c27cdb9..6f0d4d5 100644
--- a/engines/xeen/interface.cpp
+++ b/engines/xeen/interface.cpp
@@ -27,6 +27,318 @@
 
 namespace Xeen {
 
+OutdoorDrawList::OutdoorDrawList() : _skySprite(_data[1]), _groundSprite(_data[2]) {
+	_data[0] = DrawStruct(0, 8, 8);
+	_data[1] = DrawStruct(1, 8, 25);
+	_data[2] = DrawStruct(0, 8, 67);
+	_data[3] = DrawStruct(0, 8, 67);
+	_data[4] = DrawStruct(0, 38, 67);
+	_data[5] = DrawStruct(0, 84, 67);
+	_data[6] = DrawStruct(0, 134, 67);
+	_data[7] = DrawStruct(0, 117, 67);
+	_data[8] = DrawStruct(0, 117, 67);
+	_data[9] = DrawStruct(0, 103, 67);
+	_data[10] = DrawStruct(0, 8, 73);
+	_data[11] = DrawStruct(0, 8, 73);
+	_data[12] = DrawStruct(0, 30, 73);
+	_data[13] = DrawStruct(0, 181, 73);
+	_data[14] = DrawStruct(0, 154, 73);
+	_data[15] = DrawStruct(0, 129, 73);
+	_data[16] = DrawStruct(0, 87, 73);
+	_data[17] = DrawStruct(0, 8, 81);
+	_data[18] = DrawStruct(0, 8, 81);
+	_data[19] = DrawStruct(0, 202, 81);
+	_data[20] = DrawStruct(0, 145, 81);
+	_data[21] = DrawStruct(0, 63, 81);
+	_data[22] = DrawStruct(0, 8, 93);
+	_data[23] = DrawStruct(0, 169, 93);
+	_data[24] = DrawStruct(0, 31, 93);
+	_data[25] = DrawStruct(0, 8, 109);
+	_data[26] = DrawStruct(0, 201, 109);
+	_data[27] = DrawStruct(0, 8, 109);
+	_data[28] = DrawStruct(1, 65472, 61, 14, SPRFLAG_2000);
+	_data[29] = DrawStruct(1, 65496, 61, 14, 0);
+	_data[30] = DrawStruct(1, 65520, 61, 14, 0);
+	_data[31] = DrawStruct(1, 8, 61, 14, 0);
+	_data[32] = DrawStruct(1, 128, 61, 14, SPRFLAG_HORIZ_FLIPPED | SPRFLAG_2000);
+	_data[33] = DrawStruct(1, 104, 61, 14, SPRFLAG_HORIZ_FLIPPED);
+	_data[34] = DrawStruct(1, 80, 61, 14, SPRFLAG_HORIZ_FLIPPED);
+	_data[35] = DrawStruct(1, 56, 61, 14, SPRFLAG_HORIZ_FLIPPED);
+	_data[36] = DrawStruct(1, 32, 61, 14, 0);
+	_data[37] = DrawStruct(0, 65527, 61, 14, 0);
+	_data[38] = DrawStruct(0, 65478, 61, 14, 0);
+	_data[39] = DrawStruct(0, 40, 61, 14, 0);
+	_data[40] = DrawStruct(0, 65454, 61, 14, 0);
+	_data[41] = DrawStruct(0, 64, 61, 14, 0);
+	_data[42] = DrawStruct(0, 65495, 61, 14, 0);
+	_data[43] = DrawStruct(0, 65510, 61, 14, 0);
+	_data[44] = DrawStruct(0, 65502, 61, 14, 0);
+	_data[45] = DrawStruct(0, 65520, 61, 14, 0);
+	_data[46] = DrawStruct(0, 23, 61, 14, 0);
+	_data[47] = DrawStruct(0, 16, 61, 14, 0);
+	_data[48] = DrawStruct(0, 65478, 61, 14, 0);
+	_data[49] = DrawStruct(0, 40, 61, 14, 0);
+	_data[50] = DrawStruct(0, 65519, 61, 14, 0);
+	_data[51] = DrawStruct(0, 65535, 58, 14, 0);
+	_data[52] = DrawStruct(0, 65527, 58, 14, 0);
+	_data[53] = DrawStruct(0, 72, 58, 12, 0);
+	_data[54] = DrawStruct(0, 72, 58, 12, SPRFLAG_HORIZ_FLIPPED);
+	_data[55] = DrawStruct(0, 69, 63, 12, 0);
+	_data[56] = DrawStruct(0, 75, 63, 12, SPRFLAG_HORIZ_FLIPPED);
+	_data[57] = DrawStruct(0, 73, 53, 12, 0);
+	_data[58] = DrawStruct(0, 71, 53, 12, SPRFLAG_HORIZ_FLIPPED);
+	_data[59] = DrawStruct(0, 80, 57, 12, 0);
+	_data[60] = DrawStruct(0, 64, 57, 12, SPRFLAG_HORIZ_FLIPPED);
+	_data[61] = DrawStruct(2, 65525, 54, 8, 0);
+	_data[62] = DrawStruct(1, 65515, 54, 11, 0);
+	_data[63] = DrawStruct(2, 165, 54, 8, SPRFLAG_HORIZ_FLIPPED);
+	_data[64] = DrawStruct(1, 86, 54, 11, SPRFLAG_HORIZ_FLIPPED);
+	_data[65] = DrawStruct(1, 33, 54, 11, 0);
+	_data[66] = DrawStruct(0, 65528, 54, 12, 0);
+	_data[67] = DrawStruct(0, 65463, 54, 12, 0);
+	_data[68] = DrawStruct(0, 57, 54, 12, 0);
+	_data[69] = DrawStruct(0, 65471, 54, 12, 0);
+	_data[70] = DrawStruct(0, 65455, 54, 12, 0);
+	_data[71] = DrawStruct(0, 49, 54, 12, 0);
+	_data[72] = DrawStruct(0, 65, 54, 12, 0);
+	_data[73] = DrawStruct(0, 65512, 54, 12, 0);
+	_data[74] = DrawStruct(0, 9, 50, 12, 0);
+	_data[75] = DrawStruct(0, 65528, 50, 12, 0);
+	_data[76] = DrawStruct(0, 72, 53, 8, 0);
+	_data[77] = DrawStruct(0, 72, 53, 8, SPRFLAG_HORIZ_FLIPPED);
+	_data[78] = DrawStruct(0, 77, 58, 8, 0);
+	_data[79] = DrawStruct(0, 67, 58, 8, SPRFLAG_HORIZ_FLIPPED);
+	_data[80] = DrawStruct(0, 81, 47, 8, 0);
+	_data[81] = DrawStruct(0, 63, 47, 8, SPRFLAG_HORIZ_FLIPPED);
+	_data[82] = DrawStruct(0, 94, 52, 8, 0);
+	_data[83] = DrawStruct(0, 50, 52, 8, SPRFLAG_HORIZ_FLIPPED);
+	_data[84] = DrawStruct(2, 8, 40);
+	_data[85] = DrawStruct(2, 146, 40, 0, SPRFLAG_HORIZ_FLIPPED);
+	_data[86] = DrawStruct(1, 32, 40, 6, 0);
+	_data[87] = DrawStruct(0, 65529, 30, 7, 0);
+	_data[88] = DrawStruct(0, 65424, 30, 7, SPRFLAG_2000);
+	_data[89] = DrawStruct(0, 98, 30, 7, SPRFLAG_2000);
+	_data[90] = DrawStruct(0, 65424, 30, 8, SPRFLAG_2000);
+	_data[91] = DrawStruct(0, 98, 30, 8, SPRFLAG_2000);
+	_data[92] = DrawStruct(0, 65498, 30, 8, 0);
+	_data[93] = DrawStruct(0, 25, 30, 8, 0);
+	_data[94] = DrawStruct(0, 65529, 30, 8, 0);
+	_data[95] = DrawStruct(0, 72, 48, 4, 0);
+	_data[96] = DrawStruct(0, 72, 48, 4, SPRFLAG_HORIZ_FLIPPED);
+	_data[97] = DrawStruct(0, 85, 53, 4, 0);
+	_data[98] = DrawStruct(0, 59, 53, 4, SPRFLAG_HORIZ_FLIPPED);
+	_data[99] = DrawStruct(0, 89, 41, 4, 0);
+	_data[100] = DrawStruct(0, 55, 41, 4, SPRFLAG_HORIZ_FLIPPED);
+	_data[101] = DrawStruct(0, 106, 47, 4, 0);
+	_data[102] = DrawStruct(0, 38, 47, 4, SPRFLAG_HORIZ_FLIPPED);
+	_data[103] = DrawStruct(0, 8, 24);
+	_data[104] = DrawStruct(0, 169, 24, 0, SPRFLAG_HORIZ_FLIPPED);
+	_data[105] = DrawStruct(1, 32, 24);
+	_data[106] = DrawStruct(0, 65513, 40, 0, SPRFLAG_2000);
+	_data[107] = DrawStruct(0, 200, 40, 0, SPRFLAG_HORIZ_FLIPPED | SPRFLAG_2000);
+	_data[108] = DrawStruct(0, 8, 47);
+	_data[109] = DrawStruct(0, 169, 47, 0, SPRFLAG_HORIZ_FLIPPED);
+	_data[110] = DrawStruct(1, 65480, 65532, 32768, SPRFLAG_4000 | SPRFLAG_2000);
+	_data[111] = DrawStruct(0, 65531, 2, 0, SPRFLAG_4000 | SPRFLAG_2000);
+	_data[112] = DrawStruct(0, 65469, 2, 0, SPRFLAG_4000 | SPRFLAG_2000);
+	_data[113] = DrawStruct(0, 44, 73);
+	_data[114] = DrawStruct(0, 44, 73);
+	_data[115] = DrawStruct(0, 58, 14, 0, SPRFLAG_4000 | SPRFLAG_2000);
+	_data[116] = DrawStruct(0, 169, 73);
+	_data[117] = DrawStruct(0, 169, 73);
+	_data[118] = DrawStruct(0, 65531, 14, 0, SPRFLAG_4000 | SPRFLAG_2000);
+	_data[119] = DrawStruct(0, 110, 73);
+	_data[120] = DrawStruct(0, 110, 73);
+	_data[121] = DrawStruct(0, 65531, 14, 0, SPRFLAG_4000 | SPRFLAG_2000);
+	_data[122] = DrawStruct(0, 110, 73);
+	_data[123] = DrawStruct(0, 110, 73);
+	_data[124] = DrawStruct(0, 72, 43);
+	_data[125] = DrawStruct(0, 72, 43, 0, SPRFLAG_HORIZ_FLIPPED);
+	_data[126] = DrawStruct(0, 93, 48);
+	_data[127] = DrawStruct(0, 51, 48, 0, SPRFLAG_HORIZ_FLIPPED);
+	_data[128] = DrawStruct(0, 97, 36);
+	_data[129] = DrawStruct(0, 47, 36, 0, SPRFLAG_HORIZ_FLIPPED);
+	_data[130] = DrawStruct(0, 118, 42);
+	_data[131] = DrawStruct(0, 26, 42, 0, SPRFLAG_HORIZ_FLIPPED);
+}
+
+/*------------------------------------------------------------------------*/
+
+IndoorDrawList::IndoorDrawList() : _skySprite(_data[1]), _groundSprite(_data[2]) {
+	_data[0] = DrawStruct(0, 8, 8);
+	_data[1] = DrawStruct(1, 8, 25);
+	_data[2] = DrawStruct(0, 8, 67);
+	_data[3] = DrawStruct(0, 8, 67);
+	_data[4] = DrawStruct(0, 38, 67);
+	_data[5] = DrawStruct(0, 84, 67);
+	_data[6] = DrawStruct(0, 134, 67);
+	_data[7] = DrawStruct(0, 117, 67);
+	_data[8] = DrawStruct(0, 117, 67);
+	_data[9] = DrawStruct(0, 103, 67);
+	_data[10] = DrawStruct(0, 8, 73);
+	_data[11] = DrawStruct(0, 8, 73);
+	_data[12] = DrawStruct(0, 30, 73);
+	_data[13] = DrawStruct(0, 181, 73);
+	_data[14] = DrawStruct(0, 154, 73);
+	_data[15] = DrawStruct(0, 129, 73);
+	_data[16] = DrawStruct(0, 87, 73);
+	_data[17] = DrawStruct(0, 8, 81);
+	_data[18] = DrawStruct(0, 8, 81);
+	_data[19] = DrawStruct(0, 202, 81);
+	_data[20] = DrawStruct(0, 145, 81);
+	_data[21] = DrawStruct(0, 63, 81);
+	_data[22] = DrawStruct(0, 8, 93);
+	_data[23] = DrawStruct(0, 169, 93);
+	_data[24] = DrawStruct(0, 31, 93);
+	_data[25] = DrawStruct(0, 8, 109);
+	_data[26] = DrawStruct(0, 201, 109);
+	_data[27] = DrawStruct(0, 8, 109);
+	_data[28] = DrawStruct(7, 8, 64);
+	_data[29] = DrawStruct(22, 32, 60);
+	_data[30] = DrawStruct(20, 56, 60);
+	_data[31] = DrawStruct(18, 80, 60);
+	_data[32] = DrawStruct(16, 104, 60);
+	_data[33] = DrawStruct(23, 152, 60, 0, SPRFLAG_HORIZ_FLIPPED);
+	_data[34] = DrawStruct(21, 144, 60, 0, SPRFLAG_HORIZ_FLIPPED);
+	_data[35] = DrawStruct(19, 131, 60, 0, SPRFLAG_HORIZ_FLIPPED);
+	_data[36] = DrawStruct(17, 120, 60, 0, SPRFLAG_HORIZ_FLIPPED);
+	_data[37] = DrawStruct(14, 8, 60);
+	_data[38] = DrawStruct(12, 32, 60);
+	_data[39] = DrawStruct(10, 56, 60);
+	_data[40] = DrawStruct(14, 80, 60);
+	_data[41] = DrawStruct(14, 104, 60);
+	_data[42] = DrawStruct(14, 128, 60);
+	_data[43] = DrawStruct(14, 152, 60);
+	_data[44] = DrawStruct(8, 176, 60);
+	_data[45] = DrawStruct(8, 200, 60);
+	_data[46] = DrawStruct(0, 65472, 61, 14, 0);
+	_data[47] = DrawStruct(0, 65496, 61, 14, 0);
+	_data[48] = DrawStruct(0, 65520, 61, 14, 0);
+	_data[49] = DrawStruct(0, 8, 61, 14, 0);
+	_data[50] = DrawStruct(0, 32, 61, 14, 0);
+	_data[51] = DrawStruct(0, 56, 61, 14, 0);
+	_data[52] = DrawStruct(0, 80, 61, 14, 0);
+	_data[53] = DrawStruct(0, 104, 61, 14, 0);
+	_data[54] = DrawStruct(0, 128, 61, 14, 0);
+	_data[55] = DrawStruct(0, 65527, 58, 14, 0);
+	_data[56] = DrawStruct(0, 65502, 58, 14, 0);
+	_data[57] = DrawStruct(0, 16, 58, 14, 0);
+	_data[58] = DrawStruct(0, 65478, 58, 14, 0);
+	_data[59] = DrawStruct(0, 40, 58, 14, 0);
+	_data[60] = DrawStruct(0, 65495, 58, 14, 0);
+	_data[61] = DrawStruct(0, 65510, 58, 14, 0);
+	_data[62] = DrawStruct(0, 65502, 58, 14, 0);
+	_data[63] = DrawStruct(0, 65520, 58, 14, 0);
+	_data[64] = DrawStruct(0, 23, 58, 14, 0);
+	_data[65] = DrawStruct(0, 16, 58, 14, 0);
+	_data[66] = DrawStruct(0, 65478, 58, 14, 0);
+	_data[67] = DrawStruct(0, 40, 58, 14, 0);
+	_data[68] = DrawStruct(0, 65519, 58, 14, 0);
+	_data[69] = DrawStruct(0, 65535, 58, 14, 0);
+	_data[70] = DrawStruct(0, 65527, 58, 14, 0);
+	_data[71] = DrawStruct(14, 8, 58);
+	_data[72] = DrawStruct(12, 8, 55);
+	_data[73] = DrawStruct(10, 32, 52);
+	_data[74] = DrawStruct(14, 88, 52);
+	_data[75] = DrawStruct(14, 128, 52, 0, SPRFLAG_HORIZ_FLIPPED);
+	_data[76] = DrawStruct(14, 152, 52, 0, SPRFLAG_HORIZ_FLIPPED);
+	_data[77] = DrawStruct(0, 176, 55, 0, SPRFLAG_HORIZ_FLIPPED);
+	_data[78] = DrawStruct(0, 200, 58, 0, SPRFLAG_HORIZ_FLIPPED);
+	_data[79] = DrawStruct(0, 72, 58, 12, 0);
+	_data[80] = DrawStruct(0, 72, 58, 12, SPRFLAG_HORIZ_FLIPPED);
+	_data[81] = DrawStruct(0, 69, 63, 12, 0);
+	_data[82] = DrawStruct(0, 75, 63, 12, SPRFLAG_HORIZ_FLIPPED);
+	_data[83] = DrawStruct(0, 73, 53, 12, 0);
+	_data[84] = DrawStruct(0, 71, 53, 12, SPRFLAG_HORIZ_FLIPPED);
+	_data[85] = DrawStruct(0, 80, 57, 12, 0);
+	_data[86] = DrawStruct(0, 64, 57, 12, SPRFLAG_HORIZ_FLIPPED);
+	_data[87] = DrawStruct(7, 65512, 52, 0, SPRFLAG_2000);
+	_data[88] = DrawStruct(7, 32, 52);
+	_data[89] = DrawStruct(7, 88, 52);
+	_data[90] = DrawStruct(0, 144, 52);
+	_data[91] = DrawStruct(0, 200, 52, 0, SPRFLAG_2000);
+	_data[92] = DrawStruct(0, 65457, 52, 11, SPRFLAG_2000);
+	_data[93] = DrawStruct(0, 65509, 52, 11, 0);
+	_data[94] = DrawStruct(0, 32, 52, 11, 0);
+	_data[95] = DrawStruct(0, 89, 52, 11, 0);
+	_data[96] = DrawStruct(0, 145, 52, 11, SPRFLAG_2000);
+	_data[97] = DrawStruct(0, 65528, 50, 12, 0);
+	_data[98] = DrawStruct(0, 65471, 50, 12, 0);
+	_data[99] = DrawStruct(0, 49, 50, 12, 0);
+	_data[100] = DrawStruct(0, 65471, 50, 12, 0);
+	_data[101] = DrawStruct(0, 65455, 50, 12, 0);
+	_data[102] = DrawStruct(0, 49, 50, 12, 0);
+	_data[103] = DrawStruct(0, 65, 50, 12, 0);
+	_data[104] = DrawStruct(0, 65512, 50, 12, 0);
+	_data[105] = DrawStruct(0, 9, 50, 12, 0);
+	_data[106] = DrawStruct(0, 65528, 50, 12, 0);
+	_data[107] = DrawStruct(7, 8, 48);
+	_data[108] = DrawStruct(7, 64, 40);
+	_data[109] = DrawStruct(6, 144, 40, 0, SPRFLAG_HORIZ_FLIPPED);
+	_data[110] = DrawStruct(6, 200, 48, 0, SPRFLAG_HORIZ_FLIPPED);
+	_data[111] = DrawStruct(0, 72, 53, 8, 0);
+	_data[112] = DrawStruct(0, 72, 53, 8, SPRFLAG_HORIZ_FLIPPED);
+	_data[113] = DrawStruct(0, 77, 58, 8, 0);
+	_data[114] = DrawStruct(0, 67, 58, 8, SPRFLAG_HORIZ_FLIPPED);
+	_data[115] = DrawStruct(0, 81, 47, 8, 0);
+	_data[116] = DrawStruct(0, 63, 47, 8, SPRFLAG_HORIZ_FLIPPED);
+	_data[117] = DrawStruct(0, 94, 52, 8, 0);
+	_data[118] = DrawStruct(0, 50, 52, 8, SPRFLAG_HORIZ_FLIPPED);
+	_data[119] = DrawStruct(6, 65496, 40, 0, SPRFLAG_2000);
+	_data[120] = DrawStruct(6, 64, 40);
+	_data[121] = DrawStruct(0, 168, 40, 0, SPRFLAG_2000);
+	_data[122] = DrawStruct(0, 65464, 40, 6, SPRFLAG_2000);
+	_data[123] = DrawStruct(0, 32, 40, 6, 0);
+	_data[124] = DrawStruct(0, 137, 40, 6, SPRFLAG_2000);
+	_data[125] = DrawStruct(0, 65529, 25, 7, 0);
+	_data[126] = DrawStruct(0, 65424, 25, 7, SPRFLAG_2000);
+	_data[127] = DrawStruct(0, 98, 25, 7, SPRFLAG_2000);
+	_data[128] = DrawStruct(0, 65424, 29, 8, SPRFLAG_2000);
+	_data[129] = DrawStruct(0, 98, 29, 8, SPRFLAG_2000);
+	_data[130] = DrawStruct(0, 65498, 29, 8, 0);
+	_data[131] = DrawStruct(0, 25, 29, 8, 0);
+	_data[132] = DrawStruct(0, 65529, 29, 8, 0);
+	_data[133] = DrawStruct(6, 32, 24);
+	_data[134] = DrawStruct(0, 168, 24, 0, SPRFLAG_HORIZ_FLIPPED);
+	_data[135] = DrawStruct(0, 72, 48, 4, 0);
+	_data[136] = DrawStruct(0, 72, 48, 4, SPRFLAG_HORIZ_FLIPPED);
+	_data[137] = DrawStruct(0, 85, 53, 4, 0);
+	_data[138] = DrawStruct(0, 59, 53, 4, SPRFLAG_HORIZ_FLIPPED);
+	_data[139] = DrawStruct(0, 89, 41, 4, 0);
+	_data[140] = DrawStruct(0, 55, 41, 4, SPRFLAG_HORIZ_FLIPPED);
+	_data[141] = DrawStruct(0, 106, 47, 4, 0);
+	_data[142] = DrawStruct(0, 38, 47, 4, SPRFLAG_HORIZ_FLIPPED);
+	_data[143] = DrawStruct(0, 65400, 24, 0, SPRFLAG_2000);
+	_data[144] = DrawStruct(0, 8, 12);
+	_data[145] = DrawStruct(0, 32, 24);
+	_data[146] = DrawStruct(0, 200, 12, 0, SPRFLAG_HORIZ_FLIPPED);
+	_data[147] = DrawStruct(0, 200, 24, 0, SPRFLAG_2000);
+	_data[148] = DrawStruct(0, 32, 24);
+	_data[149] = DrawStruct(0, 65531, 2, 0, SPRFLAG_4000 | SPRFLAG_2000);
+	_data[150] = DrawStruct(0, 65469, 10, 0, SPRFLAG_4000 | SPRFLAG_2000);
+	_data[151] = DrawStruct(0, 44, 73);
+	_data[152] = DrawStruct(0, 44, 73);
+	_data[153] = DrawStruct(0, 58, 14, 0, SPRFLAG_4000 | SPRFLAG_2000);
+	_data[154] = DrawStruct(0, 169, 73);
+	_data[155] = DrawStruct(0, 169, 73);
+	_data[156] = DrawStruct(0, 65531, 14, 0, SPRFLAG_4000 | SPRFLAG_2000);
+	_data[157] = DrawStruct(0, 110, 73);
+	_data[158] = DrawStruct(0, 110, 73);
+	_data[159] = DrawStruct(0, 65531, 14, 0, SPRFLAG_4000 | SPRFLAG_2000);
+	_data[160] = DrawStruct(0, 110, 73);
+	_data[161] = DrawStruct(0, 110, 73);
+	_data[162] = DrawStruct(0, 72, 43);
+	_data[163] = DrawStruct(0, 72, 43, 0, SPRFLAG_HORIZ_FLIPPED);
+	_data[164] = DrawStruct(0, 93, 48);
+	_data[165] = DrawStruct(0, 51, 48, 0, SPRFLAG_HORIZ_FLIPPED);
+	_data[166] = DrawStruct(0, 97, 36);
+	_data[167] = DrawStruct(0, 47, 36, 0, SPRFLAG_HORIZ_FLIPPED);
+	_data[168] = DrawStruct(0, 118, 42);
+	_data[169] = DrawStruct(0, 26, 42, 0, SPRFLAG_HORIZ_FLIPPED);
+}
+
+/*------------------------------------------------------------------------*/
+
 Interface::Interface(XeenEngine *vm) : ButtonContainer(), _vm(vm) {
 	Common::fill(&_partyFaces[0], &_partyFaces[MAX_ACTIVE_PARTY], nullptr);
 	_batUIFrame = 0;
diff --git a/engines/xeen/interface.h b/engines/xeen/interface.h
index 475e71b..60250bd 100644
--- a/engines/xeen/interface.h
+++ b/engines/xeen/interface.h
@@ -32,6 +32,29 @@ namespace Xeen {
 
 class XeenEngine;
 
+class OutdoorDrawList {
+public:
+	DrawStruct _data[132];
+	DrawStruct &_skySprite;
+	DrawStruct &_groundSprite;
+public:
+	OutdoorDrawList();
+
+	DrawStruct &operator[](int idx) { return _data[idx]; }
+};
+
+class IndoorDrawList {
+public:
+	DrawStruct _data[170];
+	DrawStruct &_skySprite;
+	DrawStruct &_groundSprite;
+public:
+	IndoorDrawList();
+
+	DrawStruct &operator[](int idx) { return _data[idx]; }
+};
+
+
 class Interface: public ButtonContainer {
 private:
 	XeenEngine *_vm;
@@ -49,6 +72,8 @@ private:
 	SpriteResource *_partyFaces[MAX_ACTIVE_PARTY];
 	DrawStruct _faceDrawStructs[4];
 	DrawStruct _mainList[16];
+	OutdoorDrawList _outdoorList;
+	IndoorDrawList _indoorList;
 	int _combatCharIds[8];
 
 	int _batUIFrame;
diff --git a/engines/xeen/sprites.h b/engines/xeen/sprites.h
index 7f937ab..59c1ed1 100644
--- a/engines/xeen/sprites.h
+++ b/engines/xeen/sprites.h
@@ -33,7 +33,8 @@ namespace Xeen {
 
 class XeenEngine;
 
-enum SpriteFlags { SPRFLAG_HORIZ_FLIPPED = 0x8000 };
+enum SpriteFlags { SPRFLAG_2000 = 0x2000, SPRFLAG_4000 = 0x4000, 
+	SPRFLAG_HORIZ_FLIPPED = 0x8000 };
 
 class SpriteResource {
 private:


Commit: 8f0c5543fbac066a9b0f216ae0747e6cff528a2c
    https://github.com/scummvm/scummvm/commit/8f0c5543fbac066a9b0f216ae0747e6cff528a2c
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-01-09T22:27:48-05:00

Commit Message:
XEEN: Beginning to implement setIndoorObjects

Changed paths:
    engines/xeen/interface.cpp
    engines/xeen/interface.h
    engines/xeen/map.h
    engines/xeen/resources.cpp
    engines/xeen/resources.h



diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp
index 6f0d4d5..e960b3d 100644
--- a/engines/xeen/interface.cpp
+++ b/engines/xeen/interface.cpp
@@ -164,7 +164,11 @@ OutdoorDrawList::OutdoorDrawList() : _skySprite(_data[1]), _groundSprite(_data[2
 
 /*------------------------------------------------------------------------*/
 
-IndoorDrawList::IndoorDrawList() : _skySprite(_data[1]), _groundSprite(_data[2]) {
+IndoorDrawList::IndoorDrawList() : _skySprite(_data[1]), _groundSprite(_data[2]),
+	_objects0(_data[149]), _objects1(_data[125]), _objects2(_data[126]),
+	_objects3(_data[127]), _objects4(_data[97]), _objects5(_data[98]),
+	_objects6(_data[99]), _objects7(_data[55]), _objects8(_data[56]),
+	_objects9(_data[58]), _objects10(_data[57]), _objects11(_data[59]) {
 	_data[0] = DrawStruct(0, 8, 8);
 	_data[1] = DrawStruct(1, 8, 25);
 	_data[2] = DrawStruct(0, 8, 67);
@@ -360,6 +364,9 @@ Interface::Interface(XeenEngine *vm) : ButtonContainer(), _vm(vm) {
 	_flag1 = false;
 	_flag2 = false;
 	_tillMove = 0;
+	_objNumber = 0;
+	_objectFlag2 = _objectFlag3 = _objectFlag4 = _objectFlag5 = false;
+	_objectFlag6 = _objectFlag7 = _objectFlag8 = false;
 
 	initDrawStructs();
 }
@@ -846,7 +853,7 @@ void Interface::addCharacterToRoster() {
 
 void Interface::draw3d(bool flag) {
 	Screen &screen = *_vm->_screen;
-	EventsManager &events = *_vm->_events;
+//	EventsManager &events = *_vm->_events;
 
 	if (!screen._windows[11]._enabled)
 		return;
@@ -869,12 +876,73 @@ void Interface::animate3d() {
 
 }
 
-void Interface::setMonsters() {
+void Interface::setIndoorsMonsters() {
 
 }
 
-void Interface::setObjects() {
+void Interface::setIndoorObjects() {
+	Common::Point mazePos = _vm->_party._mazePosition;
+	_objNumber = 0;
+	int objIndx = 0;
+	const int8 *posOffset = &SCREEN_POSITIONING[_vm->_party._mazeDirection * 48];
+	Common::Point pt;
+
+	// TODO: Fields loading
 
+	Common::Array<MazeObject> &objects = _vm->_map->_mobData._objects;
+	for (uint idx = 0; idx < objects.size(); ++idx) {
+		MazeObject &mazeObject = objects[idx];
+
+		// Determine which half of the X/Y lists to use
+		int listOffset;
+		if (_vm->_files->_isDarkCc) {
+			listOffset = mazeObject._spriteId == 47 ? 1 : 0;
+		} else {
+			listOffset = mazeObject._spriteId == 113 ? 1 : 0;
+		}
+
+		// Position 1
+		pt = Common::Point(mazePos.x + posOffset[2], mazePos.y + posOffset[194]);
+		if (pt == mazeObject._position && _indoorList._objects0._frame == -1) {
+			_indoorList._objects0._x = INDOOR_OBJECT_X[listOffset][0];
+			_indoorList._objects0._y = INDOOR_OBJECT_Y[listOffset][0];
+			_indoorList._objects0._frame = mazeObject._frame;
+			_indoorList._objects0._sprites = mazeObject._sprites;
+			_indoorList._objects0._flags &= ~SPRFLAG_HORIZ_FLIPPED;
+			if (mazeObject._flipped)
+				_indoorList._objects0._flags |= SPRFLAG_HORIZ_FLIPPED;
+			_objNumber = idx;
+		}
+
+		// Position 2
+		pt = Common::Point(mazePos.x + posOffset[7], mazePos.y + posOffset[199]);
+		if (pt == mazeObject._position && !_objectFlag2 && _indoorList._objects1._frame == -1) {
+			_indoorList._objects1._x = INDOOR_OBJECT_X[listOffset][1];
+			_indoorList._objects1._y = INDOOR_OBJECT_Y[listOffset][1];
+			_indoorList._objects1._frame = mazeObject._frame;
+			_indoorList._objects1._sprites = mazeObject._sprites;
+			_indoorList._objects1._flags &= ~SPRFLAG_HORIZ_FLIPPED;
+			if (mazeObject._flipped)
+				_indoorList._objects1._flags |= SPRFLAG_HORIZ_FLIPPED;
+			_objNumber = idx;
+		}
+
+		// Position 3
+		pt = Common::Point(mazePos.x + posOffset[5], mazePos.y + posOffset[197]);
+		if (pt == mazeObject._position && !_objectFlag2 && _indoorList._objects2._frame == -1) {
+			_indoorList._objects2._x = INDOOR_OBJECT_X[listOffset][1];
+			_indoorList._objects2._y = INDOOR_OBJECT_Y[listOffset][1];
+			_indoorList._objects2._frame = mazeObject._frame;
+			_indoorList._objects2._sprites = mazeObject._sprites;
+			_indoorList._objects2._flags &= ~SPRFLAG_HORIZ_FLIPPED;
+			if (mazeObject._flipped)
+				_indoorList._objects2._flags |= SPRFLAG_HORIZ_FLIPPED;
+			_objNumber = idx;
+		}
+
+		// Position 4 onwards
+		// TODO: Also resolve usage of _objectFlag* flags
+	}
 }
 
 void Interface::setOutdoorsMonsters() {
@@ -892,8 +960,8 @@ void Interface::startup() {
 
 	animate3d();
 	if (_vm->_map->_isOutdoors) {
-		setMonsters();
-		setObjects();
+		setIndoorsMonsters();
+		setIndoorObjects();
 	} else {
 		setOutdoorsMonsters();
 		setOutdoorsObjects();
diff --git a/engines/xeen/interface.h b/engines/xeen/interface.h
index 60250bd..5dc5e1f 100644
--- a/engines/xeen/interface.h
+++ b/engines/xeen/interface.h
@@ -48,6 +48,9 @@ public:
 	DrawStruct _data[170];
 	DrawStruct &_skySprite;
 	DrawStruct &_groundSprite;
+	DrawStruct &_objects0, _objects1, _objects2, _objects3;
+	DrawStruct &_objects4, _objects5, _objects6, _objects7;
+	DrawStruct &_objects8, _objects9, _objects10, _objects11;
 public:
 	IndoorDrawList();
 
@@ -95,6 +98,9 @@ private:
 	bool _flag1;
 	bool _flag2;
 	byte _tillMove;
+	int _objNumber;
+	bool _objectFlag2, _objectFlag3, _objectFlag4, _objectFlag5;
+	bool _objectFlag6, _objectFlag7, _objectFlag8;
 
 	void loadSprites();
 
@@ -114,9 +120,9 @@ private:
 
 	void animate3d();
 
-	void setMonsters();
+	void setIndoorsMonsters();
 
-	void setObjects();
+	void setIndoorObjects();
 
 	void setOutdoorsMonsters();
 
diff --git a/engines/xeen/map.h b/engines/xeen/map.h
index 1d11bdc..30c2c64 100644
--- a/engines/xeen/map.h
+++ b/engines/xeen/map.h
@@ -285,7 +285,6 @@ private:
 	XeenEngine *_vm;
 	MazeData _mazeData[9];
 	Common::String _mazeName;
-	MonsterObjectData _mobData;
 	HeadData _headData;
 	SpriteResource _objPicSprites;
 	MonsterData _monsterData;
@@ -296,6 +295,7 @@ private:
 	bool _stepped;
 public:
 	bool _isOutdoors;
+	MonsterObjectData _mobData;
 public:
 	Map(XeenEngine *vm);
 
diff --git a/engines/xeen/resources.cpp b/engines/xeen/resources.cpp
index 3f59f3e..35fa2cb 100644
--- a/engines/xeen/resources.cpp
+++ b/engines/xeen/resources.cpp
@@ -303,4 +303,51 @@ const char *const PLEASE_WAIT = "\014""d\003""c\011""000"
 
 const char *const OOPS = "\003""c\011""000\013""002Oops...";
 
+const int8 SCREEN_POSITIONING[384] = {
+	-1,  0,  0,  0,  1, -1,  0,  0,  0,  1, -2, -1, -1,  0,  0,  0,
+	 1,  1,  2, -4, -3, -3, -2, -2, -1, -1,  0,  0,  0,  1,  1,  2,
+	 2,  3,  3,  4, -3, -2, -1,  0,  0,  1,  2,  3, -4,  4,  0,  0,
+	 0,  0,  0,  0,  0,  1,  1,  1,  1,  1,  2,  2,  2,  2,  2,  2,
+	 2,  2,  2,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,
+	 3,  3,  3,  3,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  0,  1,
+	 1,  0,  0,  0, -1,  1,  0,  0,  0, -1,  2,  1,  1,  0,  0,  0,
+	-1, -1, -2,  4,  3,  3,  2,  2,  1,  1,  0,  0,  0, -1, -1, -2,
+	-2, -3, -3, -4,  3,  2,  1,  0,  0, -1, -2, -3,  4, -4,  0,  0,
+	 0,  0,  0,  0,  0, -1, -1, -1, -1, -1, -2, -2, -2, -2, -2, -2,
+	-2, -2, -2, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3,
+	-3, -3, -3, -3, -4, -4, -4, -4, -4, -4, -4, -4, -4, -4,  0, -1,
+	 0,  0,  0,  0,  0,  1,  1,  1,  1,  1,  2,  2,  2,  2,  2,  2,
+	 2,  2,  2,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,
+	 3,  3,  3,  3,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  0,  1,
+	 1,  0,  0,  0, -1,  1,  0,  0,  0, -1,  2,  1,  1,  0,  0,  0,
+	-1, -1, -2,  4,  3,  3,  2,  2,  1,  1,  0,  0,  0, -1, -1, -2,
+	-2, -3, -3, -4,  3,  2,  1,  0,  0, -1, -2, -3,  4, -4,  0,  0,
+	 0,  0,  0,  0,  0, -1, -1, -1, -1, -1, -2, -2, -2, -2, -2, -2,
+	-2, -2, -2, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3,
+	-3, -3, -3, -3, -4, -4, -4, -4, -4, -4, -4, -4, -4, -4,  0, -1,
+	-1,  0,  0,  0,  1, -1,  0,  0,  0,  1, -2, -1, -1,  0,  0,  0,
+	 1,  1,  2, -4, -3, -3, -2, -2, -1, -1,  0,  0,  0,  1,  1,  2,
+	 2,  3,  3,  4, -3, -2, -1,  0,  0,  1,  2,  3, -4,  4,  0,  0,
+};
+
+const int INDOOR_OBJECT_X[2][12] = {
+	{ 5, -7, -112, 98, -8, -65, 49, -9, -34, 16, -58, 40 },
+	{ -35, -35, -142, 68, -35, -95, 19, -35, -62, -14, -98, 16 }
+};
+
+const int INDOOR_OBJECT_Y[2][12] = {
+	{ 2, 25, 25, 25, 50, 50, 50, 58, 58, 58, 58, 58 },
+	{ -65, -6, -6, -6, 36, 36, 36, 54, 54, 54, 54, 54 }
+};
+
+const int OUTDOOR_OBJECT_X[2][12] = {
+	{ -5, -7, -112, 98, -8, -77, 61, -9, -43, 25, -74, 56 },
+	{ -35, -35, -142, 68, -35, -95, 19, -35, -62, -24, -98, 16 }
+};
+
+const int OUTDOOR_OBJECT_Y[2][12] = {
+	{ 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 69 },
+	{ 70, 71, 72, 73, 74, 75, 90, 91, 92, 93, 94, 112 }
+};
+
 } // End of namespace Xeen
diff --git a/engines/xeen/resources.h b/engines/xeen/resources.h
index 78104b2..d8cc93b 100644
--- a/engines/xeen/resources.h
+++ b/engines/xeen/resources.h
@@ -68,6 +68,16 @@ extern const char *const PLEASE_WAIT;
 
 extern const char *const OOPS;
 
+extern const int8 SCREEN_POSITIONING[384];
+
+extern const int INDOOR_OBJECT_X[2][12];
+
+extern const int INDOOR_OBJECT_Y[2][12];
+
+extern const int OUTDOOR_OBJECT_X[2][12];
+
+extern const int OUTDOOR_OBJECT_Y[2][12];
+
 } // End of namespace Xeen
 
 #endif	/* XEEN_RESOURCES_H */


Commit: 49787629ffb86569faebd3155fd65c0cedea0bad
    https://github.com/scummvm/scummvm/commit/49787629ffb86569faebd3155fd65c0cedea0bad
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-01-11T08:54:42-05:00

Commit Message:
XEEN: Various renamings

Changed paths:
    engines/xeen/darkside/darkside_game.cpp
    engines/xeen/dialogs_options.cpp
    engines/xeen/interface.cpp
    engines/xeen/interface.h
    engines/xeen/map.cpp
    engines/xeen/map.h
    engines/xeen/party.cpp
    engines/xeen/party.h
    engines/xeen/sound.h
    engines/xeen/xeen.cpp
    engines/xeen/xeen.h



diff --git a/engines/xeen/darkside/darkside_game.cpp b/engines/xeen/darkside/darkside_game.cpp
index 30f5458..60cb693 100644
--- a/engines/xeen/darkside/darkside_game.cpp
+++ b/engines/xeen/darkside/darkside_game.cpp
@@ -220,8 +220,8 @@ void DarkSideEngine::showStartSequence() {
 	pause(30);
 
 	// TODO: More
-	_sound->playMusic(voc[0]);
-	_sound->playMusic(voc[1]);
+	_sound->playSong(voc[0]);
+	_sound->playSong(voc[1]);
 }
 
 } // End of namespace Xeen
diff --git a/engines/xeen/dialogs_options.cpp b/engines/xeen/dialogs_options.cpp
index fb7366c..8f02559 100644
--- a/engines/xeen/dialogs_options.cpp
+++ b/engines/xeen/dialogs_options.cpp
@@ -54,7 +54,7 @@ void OptionsMenu::execute() {
 	EventsManager &events = *_vm->_events;
 	
 	File newBright("newbrigh.m");
-	_vm->_sound->playMusic(newBright);
+	_vm->_sound->playSong(newBright);
 
 	screen._windows[GAME_WINDOW].setBounds(Common::Rect(72, 25, 248, 175));
 
diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp
index e960b3d..f952425 100644
--- a/engines/xeen/interface.cpp
+++ b/engines/xeen/interface.cpp
@@ -355,7 +355,7 @@ Interface::Interface(XeenEngine *vm) : ButtonContainer(), _vm(vm) {
 	_holyBonusUIFrame = 0;
 	_heroismUIFrame = 0;
 	_flipUIFrame = 0;
-	_isEarlyGame = false;
+	_newDay = false;
 	_buttonsLoaded = false;
 	_hiliteChar = -1;
 	Common::fill(&_combatCharIds[0], &_combatCharIds[8], 0);
@@ -411,7 +411,7 @@ void Interface::setup() {
 		_vm->_party._activeParty[i] = _vm->_roster[_vm->_party._partyMembers[i]];
 	}
 
-	_isEarlyGame = _vm->_party._minutes >= 300;
+	_newDay = _vm->_party._minutes >= 300;
 }
 
 void Interface::manageCharacters(bool soundPlayed) {
@@ -546,7 +546,7 @@ start:
 				} else {
 					screen.fadeOut(4);
 					w.close();
-					addCharacterToRoster();
+					moveCharacterToRoster();
 					_vm->_saves->writeCharFile();
 					screen.fadeOut(4);
 					flag = true;
@@ -636,7 +636,7 @@ void Interface::assembleBorder() {
 
 	// Draw UI element to indicate whether can spot hidden doors
 	_borderSprites.draw(screen,
-		(_vm->_spotDoorsAllowed && _vm->_party.checkSkill(SPOT_DOORS)) ? _spotDoorsUIFrame + 28 : 28,
+		(_vm->_thinWall && _vm->_party.checkSkill(SPOT_DOORS)) ? _spotDoorsUIFrame + 28 : 28,
 		Common::Point(194, 91));
 	_spotDoorsUIFrame = (_spotDoorsUIFrame + 1) % 12;
 
@@ -788,7 +788,7 @@ void Interface::charIconsPrint(bool updateFlag) {
 			_vm->_party._partyCount); ++idx) {
 		int charIndex = stateFlag ? _combatCharIds[idx] : idx;
 		PlayerStruct &ps = _vm->_party._activeParty[charIndex];
-		Condition charCondition = ps.findCondition();
+		Condition charCondition = ps.worstCondition();
 		int charFrame = FACE_CONDITION_FRAMES[charCondition];
 		
 		SpriteResource *sprites = (charFrame > 4 && !_charFaces[0].empty()) ?
@@ -847,7 +847,7 @@ void Interface::drawViewBackground(int bgType) {
 	}
 }
 
-void Interface::addCharacterToRoster() {
+void Interface::moveCharacterToRoster() {
 	error("TODO");
 }
 
@@ -975,7 +975,7 @@ void Interface::startup() {
 	for (int i = 1; i < 16; ++i)
 		_mainList[i]._sprites = &_iconSprites;
 
-	setIconButtons();
+	setMainButtons();
 
 	_tillMove = false;
 }
@@ -992,7 +992,7 @@ void Interface::moveMonsters() {
 
 }
 
-void Interface::setIconButtons() {
+void Interface::setMainButtons() {
 	clearButtons();
 
 	addButton(Common::Rect(235,  75, 259,  95),  83, &_iconSprites);
diff --git a/engines/xeen/interface.h b/engines/xeen/interface.h
index 5dc5e1f..3bb0fa7 100644
--- a/engines/xeen/interface.h
+++ b/engines/xeen/interface.h
@@ -89,7 +89,7 @@ private:
 	int _holyBonusUIFrame;
 	int _heroismUIFrame;
 	int _flipUIFrame;
-	bool _isEarlyGame;
+	bool _newDay;
 	bool _buttonsLoaded;
 	Common::String _interfaceText;
 	int _hiliteChar;
@@ -116,7 +116,7 @@ private:
 
 	void drawViewBackground(int bgType);
 
-	void addCharacterToRoster();
+	void moveCharacterToRoster();
 
 	void animate3d();
 
@@ -130,7 +130,7 @@ private:
 
 	void moveMonsters();
 
-	void setIconButtons();
+	void setMainButtons();
 public:
 	Interface(XeenEngine *vm);
 
diff --git a/engines/xeen/map.cpp b/engines/xeen/map.cpp
index 52dbc83..e2050bd 100644
--- a/engines/xeen/map.cpp
+++ b/engines/xeen/map.cpp
@@ -536,8 +536,8 @@ void MazeDifficulties::synchronize(Common::SeekableReadStream &s) {
 
 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);
+		for (int x = 0; x < MAP_WIDTH; ++x)
+			_wallData[y][x]._data = 0;
 		Common::fill(&_seenTiles[y][0], &_seenTiles[y][MAP_WIDTH], 0);
 		Common::fill(&_steppedOnTiles[y][0], &_steppedOnTiles[y][MAP_WIDTH], 0);
 		_wallTypes[y] = 0;
@@ -554,11 +554,14 @@ MazeData::MazeData() {
 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();
+			_wallData[y][x]._data = s.readUint16LE();
 	}
 	for (int y = 0; y < MAP_HEIGHT; ++y) {
-		for (int x = 0; x < MAP_WIDTH; ++x)
-			_cellFlag[y][x] = s.readByte();
+		for (int x = 0; x < MAP_WIDTH; ++x) {
+			byte b = s.readByte();
+			_cells[y][x]._surfaceId = b & 7;
+			_cells[y][x]._flags = b & 0xF8;
+		}
 	}
 
 	_mazeNumber = s.readUint16LE();
@@ -594,10 +597,10 @@ void MazeData::setAllTilesStepped() {
 		Common::fill(&_steppedOnTiles[y][0], &_steppedOnTiles[y][MAP_WIDTH], true);
 }
 
-void MazeData::clearCellBits() {
+void MazeData::clearCellSurfaces() {
 	for (int y = 0; y < MAP_HEIGHT; ++y) {
 		for (int x = 0; x < MAP_WIDTH; ++x)
-			_cellFlag[y][x] &= 0xF8;
+			_cells[y][x]._surfaceId = 0;
 	}
 }
 
@@ -763,6 +766,15 @@ Map::Map(XeenEngine *vm) : _vm(vm), _mobData(vm) {
 	_sideMon = 0;
 	_isOutdoors = false;
 	_stepped = false;
+	_mazeDataIndex = 0;
+	_currentSteppedOn = false;
+	_currentSurfaceId = 0;
+	_currentIsGrate = false;
+	_currentCantRest = false;
+	_currentIsDrain = false;
+	_currentIsEvent = false;
+	_currentIsObject = false;
+	_currentMonsterFlags = 0;
 }
 
 void Map::load(int mapId) {
@@ -851,7 +863,7 @@ void Map::load(int mapId) {
 				mazeData->setAllTilesStepped();
 			if (!isDarkCc && _vm->_party._gameFlags[25] &&
 					(mapId == 42 || mapId == 43 || mapId == 4)) {
-				mazeData->clearCellBits();
+				mazeData->clearCellSurfaces();
 			}
 
 			_isOutdoors = (mazeData->_mazeFlags2 & FLAG_IS_OUTDOORS) != 0;
@@ -948,4 +960,128 @@ void Map::load(int mapId) {
 	}
 }
 
+int Map::mazeLookup(const Common::Point &pt, int directionLayerIndex) {
+	Common::Point pos = pt;
+	int mapId = _vm->_party._mazeId;
+
+	if (pt.x < -16 || pt.y < -16 || pt.x >= 32 || pt.y >= 32)
+		error("Invalid coordinate");
+
+	// Find the correct maze data out of the set to use
+	_mazeDataIndex = 0;
+	while (_mazeData[_mazeDataIndex]._mazeId != _vm->_party._mazeId)
+		++_mazeDataIndex;
+
+	// Handle map changing to the north or south as necessary
+	if (pos.y & 16) {
+		if (pos.y >= 0) {
+			pos.y -= 16;
+			mapId = _mazeData[_mazeDataIndex]._surroundingMazes._north;
+		} else {
+			pos.y += 16;
+			mapId = _mazeData[_mazeDataIndex]._surroundingMazes._south;
+		}
+
+		if (mapId) {
+			// Move to the correct map to north/south
+			_mazeDataIndex = 0;
+			while (_mazeData[_mazeDataIndex]._mazeId != mapId)
+				++_mazeDataIndex;
+		} else {
+			// No map, so reached outside indoor area or outer space outdoors
+			_currentSteppedOn = true;
+			return _isOutdoors ? SURFTYPE_SPACE : 0x8888;
+		}
+	}
+
+	// Handle map changing to the east or west as necessary
+	if (pos.x & 16) {
+		if (pos.x >= 0) {
+			pos.x -= 16;
+			mapId = _mazeData[_mazeDataIndex]._surroundingMazes._east;
+		} else {
+			pos.x += 16;
+			mapId = _mazeData[_mazeDataIndex]._surroundingMazes._west;
+		}
+
+		if (mapId) {
+			_mazeDataIndex = 0;
+			while (_mazeData[_mazeDataIndex]._mazeId != mapId)
+				++_mazeDataIndex;
+		}
+	}
+
+	if (mapId) {
+		if (_isOutdoors) {
+			_currentSurfaceId = _mazeData[_mazeDataIndex]._wallData[pos.y][pos.x]._outdoors._surfaceId;
+		} else {
+			_currentSurfaceId = _mazeData[_mazeDataIndex]._cells[pos.y][pos.x]._surfaceId;
+		}
+
+		if (_currentSurfaceId == SURFTYPE_SPACE || _currentSurfaceId == SURFTYPE_SKY) {
+			_currentSteppedOn = true;
+		} else {
+			_currentSteppedOn = _mazeData[_mazeDataIndex]._steppedOnTiles[pos.y][pos.x];
+		}
+
+		return (_mazeData[_mazeDataIndex]._wallData[pos.y][pos.x]._data >> (directionLayerIndex * 4)) & 0xF;
+
+	} else {
+		_currentSteppedOn = _isOutdoors;
+		return _isOutdoors ? SURFTYPE_SPACE : 0x8888;
+	}
+}
+
+void Map::cellFlagLookup(const Common::Point &pt) {
+	Common::Point pos = pt;
+	int mapId = _vm->_party._mazeId;
+	_mazeDataIndex = 0;
+	while (_mazeData[_mazeDataIndex]._mazeId != mapId)
+		++_mazeDataIndex;
+
+	// Handle map changing to the north or south as necessary
+	if (pos.y & 16) {
+		if (pos.y >= 0) {
+			pos.y -= 16;
+			mapId = _mazeData[_mazeDataIndex]._surroundingMazes._north;
+		} else {
+			pos.y += 16;
+			mapId = _mazeData[_mazeDataIndex]._surroundingMazes._south;
+		}
+
+		_mazeDataIndex = 0;
+		while (_mazeData[_mazeDataIndex]._mazeId != mapId)
+			++_mazeDataIndex;
+	}
+
+	// Handle map changing to the east or west as necessary
+	if (pos.x & 16) {
+		if (pos.x >= 0) {
+			pos.x -= 16;
+			mapId = _mazeData[_mazeDataIndex]._surroundingMazes._east;
+		} else {
+			pos.x += 16;
+			mapId = _mazeData[_mazeDataIndex]._surroundingMazes._west;
+		}
+
+		_mazeDataIndex = 0;
+		while (_mazeData[_mazeDataIndex]._mazeId != mapId)
+			++_mazeDataIndex;
+	}
+
+	// Get the cell flags
+	const MazeCell &cell = _mazeData[_mazeDataIndex]._cells[pos.y][pos.x];
+	_currentIsGrate = cell._flags & OUTFLAG_GRATE;
+	_currentCantRest = cell._flags & FLAG_WATER;
+	_currentIsDrain = cell._flags & OUTFLAG_DRAIN;
+	_currentIsEvent = cell._flags & FLAG_AUTOEXECUTE_EVENT;
+	_currentIsObject = cell._flags & OUTFLAG_OBJECT_EXISTS;
+	_currentMonsterFlags = cell._flags & 7;
+}
+
+void Map::setCellSurfaceFlags(const Common::Point &pt, int bits) {
+	mazeLookup(pt, 0);
+	_mazeData[0]._cells[pt.y][pt.x]._surfaceId |= bits;
+}
+
 } // End of namespace Xeen
diff --git a/engines/xeen/map.h b/engines/xeen/map.h
index 30c2c64..3a1073e 100644
--- a/engines/xeen/map.h
+++ b/engines/xeen/map.h
@@ -36,7 +36,7 @@ namespace Xeen {
 
 class XeenEngine;
 
-enum DamageType { 
+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,
@@ -156,11 +156,42 @@ enum MazeFlags {
 
 enum MazeFlags2 { FLAG_IS_OUTDOORS = 0x8000, FLAG_IS_DARK = 0x4000 };
 
+enum SurfaceType {
+	SURFTYPE_DEFAULT = 0, SURFTYPE_DIRT = 1, SURFTYPE_GRASS = 2,
+	SURFTYPE_SNOW = 3, SURFTYPE_SWAMP = 4, SURFTYPE_LAVA = 5,
+	SURFTYPE_DESERT = 6, SURFTYPE_ROAD = 7, SURFTYPE_WATER = 8,
+	SURFTYPE_TFLR = 9, SURFTYPE_SKY = 10, SURFTYPE_CROAD = 11,
+	SURFTYPE_SEWER = 12, SURFTYPE_CLOUD = 13, SURFTYPE_SCORCH = 14,
+	SURFTYPE_SPACE = 15
+};
+
+union MazeWallLayers {
+	struct MazeWallIndoors {
+		int _wallNorth : 4;
+		int _wallEast : 4;
+		int _wallSouth : 4;
+		int _wallWest : 4;
+	} _indoors;
+	struct MazeWallOutdoors {
+		SurfaceType _surfaceId : 4;
+		int _iMiddle : 4;
+		int _iTop : 4;
+		int _iOverlay : 4;
+	} _outdoors;
+	uint16 _data;
+};
+
+struct MazeCell {
+	int _flags;
+	int _surfaceId;
+	MazeCell() : _flags(0), _surfaceId(0) {}
+};
+
 class MazeData {
 public:
 	// Resource fields
-	int _wallData[MAP_HEIGHT][MAP_WIDTH];
-	int _cellFlag[MAP_HEIGHT][MAP_WIDTH];
+	MazeWallLayers _wallData[MAP_HEIGHT][MAP_WIDTH];
+	MazeCell _cells[MAP_HEIGHT][MAP_WIDTH];
 	int _mazeNumber;
 	SurroundingMazes _surroundingMazes;
 	int _mazeFlags;
@@ -185,7 +216,7 @@ public:
 
 	void setAllTilesStepped();
 
-	void clearCellBits();
+	void clearCellSurfaces();
 };
 
 class MobStruct {
@@ -293,13 +324,28 @@ private:
 	int _sideObj;
 	int _sideMon;
 	bool _stepped;
+	int _mazeDataIndex;
+	bool _currentSteppedOn;
+	int _currentSurfaceId;
+
+	void cellFlagLookup(const Common::Point &pt);
 public:
 	bool _isOutdoors;
 	MonsterObjectData _mobData;
+	bool _currentIsGrate;
+	bool _currentCantRest;
+	bool _currentIsDrain;
+	bool _currentIsEvent;
+	bool _currentIsObject;
+	int _currentMonsterFlags;
 public:
 	Map(XeenEngine *vm);
 
 	void load(int mapId);
+
+	int mazeLookup(const Common::Point &pt, int directionLayerIndex);
+
+	void setCellSurfaceFlags(const Common::Point &pt, int bits);
 };
 
 } // End of namespace Xeen
diff --git a/engines/xeen/party.cpp b/engines/xeen/party.cpp
index ec25f4a..ad6d214 100644
--- a/engines/xeen/party.cpp
+++ b/engines/xeen/party.cpp
@@ -135,7 +135,7 @@ void PlayerStruct::synchronize(Common::Serializer &s) {
 	s.syncAsByte(_currentCombatSpell);
 }
 
-Condition PlayerStruct::findCondition() const {
+Condition PlayerStruct::worstCondition() const {
 	for (int cond = ERADICATED; cond >= CURSED; --cond) {
 		if (_conditions[cond])
 			return (Condition)cond;
@@ -144,7 +144,7 @@ Condition PlayerStruct::findCondition() const {
 	return NO_CONDITION;
 }
 
-int PlayerStruct::getYear(int partyYear, bool ignoreTemp) {
+int PlayerStruct::getAge(int partyYear, bool ignoreTemp) {
 	int year = MIN(partyYear - _ybDay, 254);
 
 	return ignoreTemp ? year : year + _tempAge;
diff --git a/engines/xeen/party.h b/engines/xeen/party.h
index b415707..f1220c8 100644
--- a/engines/xeen/party.h
+++ b/engines/xeen/party.h
@@ -126,9 +126,9 @@ public:
 	PlayerStruct();
 	void synchronize(Common::Serializer &s);
 
-	Condition findCondition() const;
+	Condition worstCondition() const;
 
-	int getYear(int partyYear, bool ignoreTemp);
+	int getAge(int partyYear, bool ignoreTemp);
 
 	int getMaxHp();
 };
diff --git a/engines/xeen/sound.h b/engines/xeen/sound.h
index f375b98..da6548b 100644
--- a/engines/xeen/sound.h
+++ b/engines/xeen/sound.h
@@ -39,7 +39,7 @@ public:
 
 	void startMusic(int v1);
 
-	void playMusic(const File &f) {}
+	void playSong(const File &f) {}
 
 	void playSample(const Common::SeekableReadStream *stream, int v2) {}
 };
diff --git a/engines/xeen/xeen.cpp b/engines/xeen/xeen.cpp
index c2abdd9..9cc51e1 100644
--- a/engines/xeen/xeen.cpp
+++ b/engines/xeen/xeen.cpp
@@ -46,7 +46,7 @@ XeenEngine::XeenEngine(OSystem *syst, const XeenGameDescription *gameDesc)
 	_sound = nullptr;
 	_eventData = nullptr;
 	_loadDarkSide = 1;
-	_spotDoorsAllowed = false;
+	_thinWall = false;
 	_dangerSenseAllowed = false;
 	_face1State = 0;
 	_face2State = 0;
diff --git a/engines/xeen/xeen.h b/engines/xeen/xeen.h
index 44deaee..efeacf0 100644
--- a/engines/xeen/xeen.h
+++ b/engines/xeen/xeen.h
@@ -138,7 +138,7 @@ public:
 	Roster _roster;
 	Party _party;
 	int _loadDarkSide;
-	bool _spotDoorsAllowed;
+	bool _thinWall;
 	bool _dangerSenseAllowed;
 	int _face1State;
 	int _face2State;


Commit: 0b5f79afb7dbf0d2bcf3cb14747f93f348b1aaa5
    https://github.com/scummvm/scummvm/commit/0b5f79afb7dbf0d2bcf3cb14747f93f348b1aaa5
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-01-11T10:43:02-05:00

Commit Message:
XEEN: Added loading of event data for maps

Changed paths:
  A engines/xeen/scripts.cpp
  A engines/xeen/scripts.h
    engines/xeen/map.cpp
    engines/xeen/map.h
    engines/xeen/module.mk
    engines/xeen/party.h



diff --git a/engines/xeen/map.cpp b/engines/xeen/map.cpp
index e2050bd..d07ca2d 100644
--- a/engines/xeen/map.cpp
+++ b/engines/xeen/map.cpp
@@ -842,12 +842,15 @@ void Map::load(int mapId) {
 		}
 	}
 
+	// Load any events for the new map
+	loadEvents(mapId);
+
+	// Iterate through loading the given maze as well as the two successive
+	// mazes in each of the four cardinal directions
 	bool isDarkCc = _vm->getGameID() == GType_DarkSide;
 	MazeData *mazeData = &_mazeData[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, ++mazeData) {
 		mazeData->_mazeId = mapId;
 
@@ -1032,6 +1035,28 @@ int Map::mazeLookup(const Common::Point &pt, int directionLayerIndex) {
 	}
 }
 
+/**
+ * Load the events for a new map
+ */
+void Map::loadEvents(int mapId) {
+	// Load events
+	Common::String filename = Common::String::format("maze%c%03d.evt",
+		(mapId >= 100) ? 'x' : '0', mapId);
+	File fEvents(filename);
+	_events.synchronize(fEvents);
+	fEvents.close();
+
+	// Load text data
+	filename = Common::String::format("aaze%c%03d.txt",
+		(mapId >= 100) ? 'x' : '0', mapId);
+	File fText(filename);
+	_events._text.resize(fText.size());
+	fText.read(&_events._text[0], fText.size());
+	
+	_events.synchronize(fText);
+	fText.close();
+}
+
 void Map::cellFlagLookup(const Common::Point &pt) {
 	Common::Point pos = pt;
 	int mapId = _vm->_party._mazeId;
diff --git a/engines/xeen/map.h b/engines/xeen/map.h
index 3a1073e..bc1b024 100644
--- a/engines/xeen/map.h
+++ b/engines/xeen/map.h
@@ -27,6 +27,7 @@
 #include "common/array.h"
 #include "common/rect.h"
 #include "xeen/party.h"
+#include "xeen/scripts.h"
 #include "xeen/sprites.h"
 
 namespace Xeen {
@@ -328,10 +329,13 @@ private:
 	bool _currentSteppedOn;
 	int _currentSurfaceId;
 
+	void loadEvents(int mapId);
+
 	void cellFlagLookup(const Common::Point &pt);
 public:
 	bool _isOutdoors;
 	MonsterObjectData _mobData;
+	MazeEvents _events;
 	bool _currentIsGrate;
 	bool _currentCantRest;
 	bool _currentIsDrain;
diff --git a/engines/xeen/module.mk b/engines/xeen/module.mk
index 5cbb1bb..076a31a 100644
--- a/engines/xeen/module.mk
+++ b/engines/xeen/module.mk
@@ -20,6 +20,7 @@ MODULE_OBJS := \
 	resources.o \
 	saves.o \
 	screen.o \
+	scripts.o \
 	sound.o \
 	sprites.o \
 	xeen.o \
diff --git a/engines/xeen/party.h b/engines/xeen/party.h
index f1220c8..d8fe2ab 100644
--- a/engines/xeen/party.h
+++ b/engines/xeen/party.h
@@ -31,7 +31,9 @@
 
 namespace Xeen {
 
-enum Direction { DIR_NORTH = 0, DIR_EAST = 1, DIR_SOUTH = 2, DIR_WEST = 3 };
+enum Direction { 
+	DIR_NORTH = 0, DIR_EAST = 1, DIR_SOUTH = 2, DIR_WEST = 3, DIR_ALL = 4
+};
 
 enum Difficulty { ADVENTURER = 0, WARRIOR = 1 };
 
diff --git a/engines/xeen/scripts.cpp b/engines/xeen/scripts.cpp
new file mode 100644
index 0000000..ee80431
--- /dev/null
+++ b/engines/xeen/scripts.cpp
@@ -0,0 +1,54 @@
+/* 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 "xeen/scripts.h"
+
+namespace Xeen {
+
+MazeEvent::MazeEvent() : _direction(DIR_ALL), _line(-1), _opcode(OP_None) {
+}
+
+void MazeEvent::synchronize(Common::SeekableReadStream &s) {
+	int len = s.readByte();
+	_position.x = s.readByte();
+	_position.y = s.readByte();
+	_direction = (Direction)s.readByte();
+	_line = s.readByte();
+	_opcode = (Opcode)s.readByte();
+
+	for (int i = 0; i < (len - 5); ++i)
+		_parameters.push_back(s.readByte());
+}
+
+/*------------------------------------------------------------------------*/
+
+void MazeEvents::synchronize(Common::SeekableReadStream &s) {
+	MazeEvent e;
+
+	clear();
+	while (!s.eos()) {
+		e.synchronize(s);
+		push_back(e);
+	}
+}
+
+} // End of namespace Xeen
diff --git a/engines/xeen/scripts.h b/engines/xeen/scripts.h
new file mode 100644
index 0000000..1ab08fa
--- /dev/null
+++ b/engines/xeen/scripts.h
@@ -0,0 +1,119 @@
+/* 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_SCRIPTS_H
+#define XEEN_SCRIPTS_H
+
+#include "common/scummsys.h"
+#include "common/system.h"
+#include "common/stream.h"
+#include "xeen/party.h"
+
+namespace Xeen {
+
+enum Opcode {
+	OP_None			= 0x00,
+	OP_Display0x01	= 0x01,
+	OP_DoorTextSml	= 0x02,
+	OP_DoorTextLrg	= 0x03,
+	OP_SignText		= 0x04,
+	OP_NPC			= 0x05,
+	OP_PlayFX		= 0x06,
+	OP_TeleportAndExit = 0x07,
+	OP_If_1			= 0x08,
+	OP_If_2			= 0x09,
+	OP_If3			= 0x0A,
+	OP_MoveObj		= 0x0B,
+	OP_TakeOrGive	= 0x0C,
+	OP_NoAction		= 0x0D,
+	OP_Remove		= 0x0E,
+	OP_SetChar		= 0x0F,
+	OP_Spawn		= 0x10,
+	OP_DoTownEvent	= 0x11,
+	OP_Exit			= 0x12,
+	OP_AfterMap		= 0x13,
+	OP_GiveExtended = 0x14,
+	OP_ConfirmWord	= 0x15,
+	OP_Damage		= 0x16,
+	OP_JumpRnd		= 0x17,
+	OP_AfterEvent	= 0x18,
+	OP_CallEvent	= 0x19,
+	OP_Return		= 0x1A,
+	OP_SetVar		= 0x1B,
+	OP_TakeOrGive_2 = 0x1C,
+	OP_TakeOrGive_3 = 0x1D,
+	OP_CutsceneEndClouds = 0x1E,
+	OP_TeleportAndContinue = 0x1F,
+	OP_WhoWill		= 0x20,
+	OP_RndDamage	= 0x21,
+	OP_MoveWallObj	= 0x22,
+	OP_AlterCellFlag= 0x23,
+	OP_AlterHed		= 0x24,
+	OP_DisplayStat	= 0x25,
+	OP_TakeOrGive_4	= 0x26,
+	OP_SeatTextSml	= 0x27,
+	OP_PlayEventVoc = 0x28,
+	OP_DisplayBottom = 0x29,
+	OP_IfMapFlag	= 0x2A,
+	OP_SelRndChar	= 0x2B,
+	OP_GiveEnchanted= 0x2C,
+	OP_ItemType		= 0x2D,
+	OP_MakeNothingHere = 0x2E,
+	OP_NoAction_2	= 0x2F,
+	OP_ChooseNumeric= 0x30,
+	OP_DisplayBottomTwoLines = 0x31,
+	OP_DisplayLarge	= 0x32,
+	OP_ExchObj		= 0x33,
+	OP_FallToMap	= 0x34,
+	OP_DisplayMain	= 0x35,
+	OP_Goto			= 0x36,
+	OP_ConfirmWord_2= 0x37,
+	OP_GotoRandom	= 0x38,
+	OP_CutsceneEndDarkside = 0x39,
+	OP_CutsceneEdWorld = 0x3A,
+	OP_FlipWorld	= 0x3B,
+	OP_PlayCD		= 0x3C
+};
+
+class MazeEvent {
+public:
+	Common::Point _position;
+	int _direction;
+	int _line;
+	Opcode _opcode;
+	Common::Array<byte> _parameters;
+public:
+	MazeEvent();
+
+	void synchronize(Common::SeekableReadStream &s);
+};
+
+class MazeEvents : public Common::Array<MazeEvent> {
+public:
+	Common::Array<byte> _text;
+public:
+	void synchronize(Common::SeekableReadStream &s);
+};
+
+} // End of namespace Xeen
+
+#endif /* XEEN_SCRIPTS_H */


Commit: 3b1edcdf36fc7a207a70cb28e7dcf7879ea9b7e5
    https://github.com/scummvm/scummvm/commit/3b1edcdf36fc7a207a70cb28e7dcf7879ea9b7e5
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-01-11T14:21:57-05:00

Commit Message:
XEEN: Implemented code for 'saving' resources to the loaded savefile

Changed paths:
    engines/xeen/files.cpp
    engines/xeen/files.h
    engines/xeen/map.cpp
    engines/xeen/map.h
    engines/xeen/saves.cpp
    engines/xeen/saves.h
    engines/xeen/scripts.cpp
    engines/xeen/scripts.h



diff --git a/engines/xeen/files.cpp b/engines/xeen/files.cpp
index 79387f2..8ab1f35 100644
--- a/engines/xeen/files.cpp
+++ b/engines/xeen/files.cpp
@@ -32,7 +32,7 @@ namespace Xeen {
 /**
 * Hash a given filename to produce the Id that represents it
 */
-uint16 BaseCCArchive::convertNameToId(const Common::String &resourceName) const {
+uint16 BaseCCArchive::convertNameToId(const Common::String &resourceName) {
 	if (resourceName.empty())
 		return 0xffff;
 
diff --git a/engines/xeen/files.h b/engines/xeen/files.h
index 343aea1..7c0817a 100644
--- a/engines/xeen/files.h
+++ b/engines/xeen/files.h
@@ -26,6 +26,7 @@
 #include "common/scummsys.h"
 #include "common/array.h"
 #include "common/file.h"
+#include "common/serializer.h"
 #include "graphics/surface.h"
 #include "xeen/xsurface.h"
 
@@ -61,6 +62,16 @@ public:
 	void openFile(const Common::String &filename, Common::Archive &archive);
 };
 
+class XeenSerializer : public Common::Serializer {
+private:
+	Common::SeekableReadStream *_in;
+public:
+	XeenSerializer(Common::SeekableReadStream *in, Common::WriteStream *out) :
+		Common::Serializer(in, out), _in(in) {}
+
+	bool finished() const { return _in != nullptr && _in->pos() >= _in->size(); }
+};
+
 /**
 * Details of a single entry in a CC file index
 */
@@ -79,8 +90,6 @@ struct CCEntry {
 * Base Xeen CC file implementation
 */
 class BaseCCArchive : public Common::Archive {
-private:
-	uint16 convertNameToId(const Common::String &resourceName) const;
 protected:
 	Common::Array<CCEntry> _index;
 
@@ -88,6 +97,8 @@ protected:
 
 	virtual bool getHeaderEntry(const Common::String &resourceName, CCEntry &ccEntry) const;
 public:
+	static uint16 convertNameToId(const Common::String &resourceName);
+public:
 	BaseCCArchive() {}
 
 	// Archive implementation
diff --git a/engines/xeen/map.cpp b/engines/xeen/map.cpp
index d07ca2d..d65e09d 100644
--- a/engines/xeen/map.cpp
+++ b/engines/xeen/map.cpp
@@ -1042,8 +1042,9 @@ void Map::loadEvents(int mapId) {
 	// Load events
 	Common::String filename = Common::String::format("maze%c%03d.evt",
 		(mapId >= 100) ? 'x' : '0', mapId);
-	File fEvents(filename);
-	_events.synchronize(fEvents);
+	File fEvents(filename, *_vm->_saves);
+	XeenSerializer sEvents(&fEvents, nullptr);
+	_events.synchronize(sEvents);
 	fEvents.close();
 
 	// Load text data
@@ -1052,11 +1053,23 @@ void Map::loadEvents(int mapId) {
 	File fText(filename);
 	_events._text.resize(fText.size());
 	fText.read(&_events._text[0], fText.size());
-	
-	_events.synchronize(fText);
 	fText.close();
 }
 
+void Map::saveMaze() {
+	int mazeNum = _mazeData[0]._mazeNumber;
+	if (!mazeNum || (mazeNum == 85 && !_vm->_files->_isDarkCc))
+		return;
+
+	// Save the event data
+	Common::String filename = Common::String::format("maze%c%03d.evt",
+		(mazeNum >= 100) ? 'x' : '0', mazeNum);
+	OutFile fEvents(_vm, filename);
+	XeenSerializer sEvents(nullptr, &fEvents);
+	_events.synchronize(sEvents);
+	fEvents.finalize();
+}
+
 void Map::cellFlagLookup(const Common::Point &pt) {
 	Common::Point pos = pt;
 	int mapId = _vm->_party._mazeId;
diff --git a/engines/xeen/map.h b/engines/xeen/map.h
index bc1b024..c23b214 100644
--- a/engines/xeen/map.h
+++ b/engines/xeen/map.h
@@ -350,6 +350,8 @@ public:
 	int mazeLookup(const Common::Point &pt, int directionLayerIndex);
 
 	void setCellSurfaceFlags(const Common::Point &pt, int bits);
+
+	void saveMaze();
 };
 
 } // End of namespace Xeen
diff --git a/engines/xeen/saves.cpp b/engines/xeen/saves.cpp
index e6bfa80..c2b1510 100644
--- a/engines/xeen/saves.cpp
+++ b/engines/xeen/saves.cpp
@@ -29,6 +29,22 @@
 
 namespace Xeen {
 
+OutFile::OutFile(XeenEngine *vm, const Common::String filename) :
+	_vm(vm), _filename(filename) {
+}
+
+void OutFile::finalize() {
+	uint16 id = BaseCCArchive::convertNameToId(_filename);
+
+	if (!_vm->_saves->_newData.contains(id))
+		_vm->_saves->_newData[id] = Common::MemoryWriteStreamDynamic(DisposeAfterUse::YES);
+
+	Common::MemoryWriteStreamDynamic &out = _vm->_saves->_newData[id];
+	out.write(getData(), size());
+}
+
+/*------------------------------------------------------------------------*/
+
 SavesManager::SavesManager(XeenEngine *vm, Party &party, Roster &roster) : 
 		BaseCCArchive(), _vm(vm), _party(party), _roster(roster) {
 	SearchMan.add("saves", this, 0, false);
@@ -67,6 +83,15 @@ void SavesManager::syncBitFlags(Common::Serializer &s, bool *startP, bool *endP)
 Common::SeekableReadStream *SavesManager::createReadStreamForMember(const Common::String &name) const {
 	CCEntry ccEntry;
 
+	// If the given resource has already been perviously "written" to the 
+	// save manager, then return that new resource
+	uint16 id = BaseCCArchive::convertNameToId(name);
+	if (_newData.contains(id)) {
+		Common::MemoryWriteStreamDynamic stream = _newData[id];
+		return new Common::MemoryReadStream(stream.getData(), stream.size());
+	}
+
+	// Retrieve the resource from the loaded savefile
 	if (getHeaderEntry(name, ccEntry)) {
 		// Open the correct CC entry
 		return new Common::MemoryReadStream(_data + ccEntry._offset, ccEntry._size);
diff --git a/engines/xeen/saves.h b/engines/xeen/saves.h
index ed4b80b..6b73625 100644
--- a/engines/xeen/saves.h
+++ b/engines/xeen/saves.h
@@ -24,6 +24,7 @@
 #define XEEN_SAVES_H
 
 #include "common/scummsys.h"
+#include "common/memstream.h"
 #include "common/savefile.h"
 #include "graphics/surface.h"
 #include "xeen/party.h"
@@ -40,12 +41,27 @@ struct XeenSavegameHeader {
 	int _totalFrames;
 };
 
+class XeenEngine;
+class SavesManager;
+
+class OutFile : public Common::MemoryWriteStreamDynamic {
+private:
+	XeenEngine *_vm;
+	Common::String _filename;
+public:
+	OutFile(XeenEngine *vm, const Common::String filename);
+
+	void finalize();
+};
+
 class SavesManager: public BaseCCArchive {
+	friend class OutFile;
 private:
 	XeenEngine *_vm;
 	Party &_party;
 	Roster &_roster;
 	byte *_data;
+	Common::HashMap<uint16, Common::MemoryWriteStreamDynamic > _newData;
 
 	void load(Common::SeekableReadStream *stream);
 public:
diff --git a/engines/xeen/scripts.cpp b/engines/xeen/scripts.cpp
index ee80431..0a864aa 100644
--- a/engines/xeen/scripts.cpp
+++ b/engines/xeen/scripts.cpp
@@ -27,27 +27,37 @@ namespace Xeen {
 MazeEvent::MazeEvent() : _direction(DIR_ALL), _line(-1), _opcode(OP_None) {
 }
 
-void MazeEvent::synchronize(Common::SeekableReadStream &s) {
-	int len = s.readByte();
-	_position.x = s.readByte();
-	_position.y = s.readByte();
-	_direction = (Direction)s.readByte();
-	_line = s.readByte();
-	_opcode = (Opcode)s.readByte();
-
-	for (int i = 0; i < (len - 5); ++i)
-		_parameters.push_back(s.readByte());
+void MazeEvent::synchronize(Common::Serializer &s) {
+	int len = 5 + _parameters.size();
+	s.syncAsByte(len);
+
+	s.syncAsByte(_position.x);
+	s.syncAsByte(_position.y);
+	s.syncAsByte(_direction);
+	s.syncAsByte(_line);
+	s.syncAsByte(_opcode);
+
+	len -= 5;
+	if (s.isLoading())
+		_parameters.resize(len);
+	for (int i = 0; i < len; ++i)
+		s.syncAsByte(_parameters[i]);
 }
 
 /*------------------------------------------------------------------------*/
 
-void MazeEvents::synchronize(Common::SeekableReadStream &s) {
+void MazeEvents::synchronize(XeenSerializer &s) {
 	MazeEvent e;
 
-	clear();
-	while (!s.eos()) {
-		e.synchronize(s);
-		push_back(e);
+	if (s.isLoading()) {
+		clear();
+		while (!s.finished()) {
+			e.synchronize(s);
+			push_back(e);
+		}
+	} else {
+		for (uint i = 0; i < size(); ++i)
+			(*this).operator[](i).synchronize(s);
 	}
 }
 
diff --git a/engines/xeen/scripts.h b/engines/xeen/scripts.h
index 1ab08fa..727d37f 100644
--- a/engines/xeen/scripts.h
+++ b/engines/xeen/scripts.h
@@ -25,7 +25,8 @@
 
 #include "common/scummsys.h"
 #include "common/system.h"
-#include "common/stream.h"
+#include "common/serializer.h"
+#include "xeen/files.h"
 #include "xeen/party.h"
 
 namespace Xeen {
@@ -104,14 +105,14 @@ public:
 public:
 	MazeEvent();
 
-	void synchronize(Common::SeekableReadStream &s);
+	void synchronize(Common::Serializer &s);
 };
 
 class MazeEvents : public Common::Array<MazeEvent> {
 public:
 	Common::Array<byte> _text;
 public:
-	void synchronize(Common::SeekableReadStream &s);
+	void synchronize(XeenSerializer &s);
 };
 
 } // End of namespace Xeen


Commit: edccbe63f24e26944dcd7cd3da59b6842cb36b46
    https://github.com/scummvm/scummvm/commit/edccbe63f24e26944dcd7cd3da59b6842cb36b46
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-01-11T16:01:10-05:00

Commit Message:
XEEN: Added saving of maze monster/object data

Changed paths:
    engines/xeen/files.h
    engines/xeen/interface.cpp
    engines/xeen/map.cpp
    engines/xeen/map.h



diff --git a/engines/xeen/files.h b/engines/xeen/files.h
index 7c0817a..a8343c1 100644
--- a/engines/xeen/files.h
+++ b/engines/xeen/files.h
@@ -34,6 +34,19 @@ namespace Xeen {
 
 class XeenEngine;
 
+#define SYNC_AS(SUFFIX,STREAM,TYPE,SIZE) \
+	template<typename T> \
+	void syncAs ## SUFFIX(T &val, Version minVersion = 0, Version maxVersion = kLastVersion) { \
+		if (_version < minVersion || _version > maxVersion) \
+			return;	\
+		if (_loadStream) \
+			val = static_cast<TYPE>(_loadStream->read ## STREAM()); \
+		else { \
+			TYPE tmp = (TYPE)val; \
+			_saveStream->write ## STREAM(tmp); \
+		} \
+		_bytesSynced += SIZE; \
+	}
 /*
  * Main resource manager
  */
@@ -69,6 +82,8 @@ public:
 	XeenSerializer(Common::SeekableReadStream *in, Common::WriteStream *out) :
 		Common::Serializer(in, out), _in(in) {}
 
+	SYNC_AS(Sint8, Byte, int8, 1)
+
 	bool finished() const { return _in != nullptr && _in->pos() >= _in->size(); }
 };
 
diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp
index f952425..c2c907b 100644
--- a/engines/xeen/interface.cpp
+++ b/engines/xeen/interface.cpp
@@ -883,7 +883,6 @@ void Interface::setIndoorsMonsters() {
 void Interface::setIndoorObjects() {
 	Common::Point mazePos = _vm->_party._mazePosition;
 	_objNumber = 0;
-	int objIndx = 0;
 	const int8 *posOffset = &SCREEN_POSITIONING[_vm->_party._mazeDirection * 48];
 	Common::Point pt;
 
diff --git a/engines/xeen/map.cpp b/engines/xeen/map.cpp
index d65e09d..c70b0cf 100644
--- a/engines/xeen/map.cpp
+++ b/engines/xeen/map.cpp
@@ -611,11 +611,11 @@ MobStruct::MobStruct() {
 	_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();
+bool MobStruct::synchronize(XeenSerializer &s) {
+	s.syncAsSint8(_pos.x);
+	s.syncAsSint8(_pos.y);
+	s.syncAsByte(_id);
+	s.syncAsByte(_direction);
 
 	return _id != 0xff || _pos.x != -1 || _pos.y != -1;
 }
@@ -658,85 +658,134 @@ MazeWallItem::MazeWallItem() {
 MonsterObjectData::MonsterObjectData(XeenEngine *vm): _vm(vm) {
 }
 
-void MonsterObjectData::synchronize(Common::SeekableReadStream &s, 
-		bool isOutdoors, MonsterData monsterData) {
-	_objectSprites.clear();
-	_monsterSprites.clear();
-	_monsterAttackSprites.clear();
-	_wallItemSprites.clear();
-	_objects.clear();
-	_monsters.clear();
-	_wallItems.clear();
-
+void MonsterObjectData::synchronize(XeenSerializer &s, MonsterData monsterData) {
 	Common::Array<MobStruct> mobStructs;
+	MobStruct mobStruct;
 	byte b;
 
-	for (int i = 0; i < 16; ++i) {
-		if ((b = s.readByte()) != 0xff)
+	if (s.isLoading()) {
+		_objectSprites.clear();
+		_monsterSprites.clear();
+		_monsterAttackSprites.clear();
+		_wallItemSprites.clear();
+		_objects.clear();
+		_monsters.clear();
+		_wallItems.clear();
+	}
+
+	for (uint i = 0; i < 16; ++i) {
+		b = (i >= _objectSprites.size()) ? 0xff : _objectSprites[i]._spriteId;
+		s.syncAsByte(b);
+		if (b != 0xff)
 			_objectSprites.push_back(SpriteResourceEntry(b));
 	}
-	for (int i = 0; i < 16; ++i) {
-		if ((b = s.readByte()) != 0xff)
+	for (uint i = 0; i < 16; ++i) {
+		b = (i >= _monsterSprites.size()) ? 0xff : _monsterSprites[i]._spriteId;
+		s.syncAsByte(b);
+		if (b != 0xff)
 			_monsterSprites.push_back(SpriteResourceEntry(b));
 	}
-	for (int i = 0; i < 16; ++i) {
-		if ((b = s.readByte()) != 0xff)
+	for (uint i = 0; i < 16; ++i) {
+		b = (i >= _wallItemSprites.size()) ? 0xff : _wallItemSprites[i]._spriteId;
+		s.syncAsByte(b);
+		if (b != 0xff)
 			_wallItemSprites.push_back(SpriteResourceEntry(b));
 	}
 
-	// Merge together object data
-	MobStruct mobStruct;
-	mobStruct.synchronize(s);
-	do {
-		MazeObject obj;
-		obj._position = mobStruct._pos;
-		obj._id = mobStruct._id;
-		obj._direction = mobStruct._direction;
-		obj._frame = 100;
-		obj._spriteId = _objectSprites[obj._id]._spriteId;
-		obj._sprites = &_objectSprites[obj._id]._sprites;
-
-		_objects.push_back(obj);
+	if (s.isSaving()) {
+		// Save objects
+		for (uint i = 0; i < _objects.size(); ++i) {
+			mobStruct._pos = _objects[i]._position;
+			mobStruct._id = _objects[i]._id;
+			mobStruct._direction = _objects[i]._direction;
+			mobStruct.synchronize(s);
+		}
+		mobStruct._pos.x = mobStruct._pos.y = -1;
+		mobStruct._id = 0xff;
 		mobStruct.synchronize(s);
-	} while (mobStruct._id != 255 || mobStruct._pos.x != -1);
-
-	// Merge together monster data
-	mobStruct.synchronize(s);
-	do {
-		MazeMonster mon;
-		mon._position = mobStruct._pos;
-		mon._id = mobStruct._id;
-		mon._spriteId = _monsterSprites[mon._id]._spriteId;
-		mon._sprites = &_monsterSprites[mon._id]._sprites;
-		mon._attackSprites = &_monsterSprites[mon._id]._attackSprites;
-
-		MonsterStruct &md = monsterData[mon._spriteId];
-		mon._hp = md._hp;
-		mon._frame = _vm->getRandomNumber(7);
-		mon._effect1 = mon._effect2 = md._animationEffect;
-		if (md._animationEffect)
-			mon._effect3 = _vm->getRandomNumber(7);
-
-		_monsters.push_back(mon);
+
+		// Save monsters
+		for (uint i = 0; i < _monsters.size(); ++i) {
+			mobStruct._pos = _monsters[i]._position;
+			mobStruct._id = _monsters[i]._id;
+			mobStruct._direction = DIR_NORTH;
+			mobStruct.synchronize(s);
+		}
+		mobStruct._pos.x = mobStruct._pos.y = -1;
+		mobStruct._id = 0xff;
 		mobStruct.synchronize(s);
-	} while (mobStruct._id != 255 || mobStruct._pos.x != -1);
-
-	// Merge together wall item data
-	mobStruct.synchronize(s);
-	do {
-		if (mobStruct._id < (int)_wallItemSprites.size()) {
-			MazeWallItem wi;
-			wi._position = mobStruct._pos;
-			wi._id = mobStruct._id;
-			wi._direction = mobStruct._direction;
-			wi._spriteId = _wallItemSprites[wi._id]._spriteId;
-			wi._sprites = &_wallItemSprites[wi._id]._sprites;
-
-			_wallItems.push_back(wi);
+
+		// Save wall items
+		if (_wallItems.size() == 0) {
+			MobStruct nullStruct;
+			nullStruct.synchronize(s);
+		} else {
+			for (uint i = 0; i < _wallItems.size(); ++i) {
+				mobStruct._pos = _wallItems[i]._position;
+				mobStruct._id = _wallItems[i]._id;
+				mobStruct._direction = _wallItems[i]._direction;
+				mobStruct.synchronize(s);
+			}
 		}
+		mobStruct._pos.x = mobStruct._pos.y = -1;
+		mobStruct._id = 0xff;
+		mobStruct.synchronize(s);
 
+	} else {
+		// Load monster/obbject data and merge together with sprite Ids
+		// Merge together object data
+		mobStruct.synchronize(s);
+		do {
+			MazeObject obj;
+			obj._position = mobStruct._pos;
+			obj._id = mobStruct._id;
+			obj._direction = mobStruct._direction;
+			obj._frame = 100;
+			obj._spriteId = _objectSprites[obj._id]._spriteId;
+			obj._sprites = &_objectSprites[obj._id]._sprites;
+
+			_objects.push_back(obj);
+			mobStruct.synchronize(s);
+		} while (mobStruct._id != 255 || mobStruct._pos.x != -1);
+
+		// Merge together monster data
 		mobStruct.synchronize(s);
-	} while (mobStruct._id != 255 || mobStruct._pos.x != -1);
+		do {
+			MazeMonster mon;
+			mon._position = mobStruct._pos;
+			mon._id = mobStruct._id;
+			mon._spriteId = _monsterSprites[mon._id]._spriteId;
+			mon._sprites = &_monsterSprites[mon._id]._sprites;
+			mon._attackSprites = &_monsterSprites[mon._id]._attackSprites;
+
+			MonsterStruct &md = monsterData[mon._spriteId];
+			mon._hp = md._hp;
+			mon._frame = _vm->getRandomNumber(7);
+			mon._effect1 = mon._effect2 = md._animationEffect;
+			if (md._animationEffect)
+				mon._effect3 = _vm->getRandomNumber(7);
+
+			_monsters.push_back(mon);
+			mobStruct.synchronize(s);
+		} while (mobStruct._id != 255 || mobStruct._pos.x != -1);
+
+		// Merge together wall item data
+		mobStruct.synchronize(s);
+		do {
+			if (mobStruct._id < (int)_wallItemSprites.size()) {
+				MazeWallItem wi;
+				wi._position = mobStruct._pos;
+				wi._id = mobStruct._id;
+				wi._direction = mobStruct._direction;
+				wi._spriteId = _wallItemSprites[wi._id]._spriteId;
+				wi._sprites = &_wallItemSprites[wi._id]._sprites;
+
+				_wallItems.push_back(wi);
+			}
+
+			mobStruct.synchronize(s);
+		} while (mobStruct._id != 255 || mobStruct._pos.x != -1);
+	}
 }
 
 /*------------------------------------------------------------------------*/
@@ -888,7 +937,8 @@ void Map::load(int mapId) {
 				Common::String mobName = Common::String::format("maze%c%03d.mob",
 					(mapId >= 100) ? 'x' : '0', mapId);
 				File mobFile(mobName);
-				_mobData.synchronize(mobFile, _isOutdoors, _monsterData);
+				XeenSerializer sMob(&mobFile, nullptr);
+				_mobData.synchronize(sMob, _monsterData);
 				mobFile.close();
 
 				Common::String headName = Common::String::format("aaze%c%03d.hed",
@@ -925,7 +975,8 @@ void Map::load(int mapId) {
 	Common::String filename = Common::String::format("maze%c%03d.mob",
 		(_vm->_party._mazeId >= 100) ? 'x' : '0', _vm->_party._mazeId);
 	File mobFile(filename, *_vm->_saves);
-	_mobData.synchronize(mobFile, _isOutdoors, _monsterData);
+	XeenSerializer sMob(&mobFile, nullptr);
+	_mobData.synchronize(sMob, _monsterData);
 	mobFile.close();
 
 	// Load sprites for the objects
@@ -1068,6 +1119,14 @@ void Map::saveMaze() {
 	XeenSerializer sEvents(nullptr, &fEvents);
 	_events.synchronize(sEvents);
 	fEvents.finalize();
+
+	// Save the maze MOB file
+	filename = Common::String::format("maze%c%03d.mob",
+		(mazeNum >= 100) ? 'x' : '0', mazeNum);
+	OutFile fMob(_vm, filename);
+	XeenSerializer sMob(nullptr, &fEvents);
+	_mobData.synchronize(sMob, _monsterData);
+	fEvents.finalize();
 }
 
 void Map::cellFlagLookup(const Common::Point &pt) {
diff --git a/engines/xeen/map.h b/engines/xeen/map.h
index c23b214..d26dfff 100644
--- a/engines/xeen/map.h
+++ b/engines/xeen/map.h
@@ -228,7 +228,7 @@ public:
 public:
 	MobStruct();
 
-	bool synchronize(Common::SeekableReadStream &s);
+	bool synchronize(XeenSerializer &s);
 };
 
 struct MazeObject {
@@ -295,8 +295,7 @@ public:
 public:
 	MonsterObjectData(XeenEngine *vm);
 
-	void synchronize(Common::SeekableReadStream &s, bool isOutdoors, 
-		MonsterData monsterData);
+	void synchronize(XeenSerializer &s, MonsterData monsterData);
 };
 
 class HeadData {


Commit: 4745bfe182fa0824aee2525ff196d93060c2cd0c
    https://github.com/scummvm/scummvm/commit/4745bfe182fa0824aee2525ff196d93060c2cd0c
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-01-11T17:09:48-05:00

Commit Message:
XEEN: Implemented setIndoorObjects

Changed paths:
    engines/xeen/interface.cpp
    engines/xeen/interface.h



diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp
index c2c907b..b003e9a 100644
--- a/engines/xeen/interface.cpp
+++ b/engines/xeen/interface.cpp
@@ -358,15 +358,16 @@ Interface::Interface(XeenEngine *vm) : ButtonContainer(), _vm(vm) {
 	_newDay = false;
 	_buttonsLoaded = false;
 	_hiliteChar = -1;
-	Common::fill(&_combatCharIds[0], &_combatCharIds[8], 0);
 	_intrIndex1 = 0;
 	_flipWtr = false;
 	_flag1 = false;
 	_flag2 = false;
 	_tillMove = 0;
 	_objNumber = 0;
-	_objectFlag2 = _objectFlag3 = _objectFlag4 = _objectFlag5 = false;
-	_objectFlag6 = _objectFlag7 = _objectFlag8 = false;
+
+	Common::fill(&_combatCharIds[0], &_combatCharIds[8], 0);
+	Common::fill(&_wp[0], &_wp[20], 0);
+	Common::fill(&_wo[0], &_wo[308], 0);
 
 	initDrawStructs();
 }
@@ -886,8 +887,6 @@ void Interface::setIndoorObjects() {
 	const int8 *posOffset = &SCREEN_POSITIONING[_vm->_party._mazeDirection * 48];
 	Common::Point pt;
 
-	// TODO: Fields loading
-
 	Common::Array<MazeObject> &objects = _vm->_map->_mobData._objects;
 	for (uint idx = 0; idx < objects.size(); ++idx) {
 		MazeObject &mazeObject = objects[idx];
@@ -896,7 +895,8 @@ void Interface::setIndoorObjects() {
 		int listOffset;
 		if (_vm->_files->_isDarkCc) {
 			listOffset = mazeObject._spriteId == 47 ? 1 : 0;
-		} else {
+		}
+		else {
 			listOffset = mazeObject._spriteId == 113 ? 1 : 0;
 		}
 
@@ -915,7 +915,7 @@ void Interface::setIndoorObjects() {
 
 		// Position 2
 		pt = Common::Point(mazePos.x + posOffset[7], mazePos.y + posOffset[199]);
-		if (pt == mazeObject._position && !_objectFlag2 && _indoorList._objects1._frame == -1) {
+		if (pt == mazeObject._position && !_wo[27] && _indoorList._objects1._frame == -1) {
 			_indoorList._objects1._x = INDOOR_OBJECT_X[listOffset][1];
 			_indoorList._objects1._y = INDOOR_OBJECT_Y[listOffset][1];
 			_indoorList._objects1._frame = mazeObject._frame;
@@ -923,24 +923,139 @@ void Interface::setIndoorObjects() {
 			_indoorList._objects1._flags &= ~SPRFLAG_HORIZ_FLIPPED;
 			if (mazeObject._flipped)
 				_indoorList._objects1._flags |= SPRFLAG_HORIZ_FLIPPED;
-			_objNumber = idx;
 		}
 
 		// Position 3
 		pt = Common::Point(mazePos.x + posOffset[5], mazePos.y + posOffset[197]);
-		if (pt == mazeObject._position && !_objectFlag2 && _indoorList._objects2._frame == -1) {
-			_indoorList._objects2._x = INDOOR_OBJECT_X[listOffset][1];
-			_indoorList._objects2._y = INDOOR_OBJECT_Y[listOffset][1];
+		if (pt == mazeObject._position && (!_wo[27] || !_wo[25]) && (!_wo[27] || !_wo[28]) &&
+				(!_wo[23] || !_wo[25]) && (!_wo[23] || !_wo[28]) && 
+				_indoorList._objects2._frame == -1) {
+			_indoorList._objects2._x = INDOOR_OBJECT_X[listOffset][2];
+			_indoorList._objects2._y = INDOOR_OBJECT_Y[listOffset][2];
 			_indoorList._objects2._frame = mazeObject._frame;
 			_indoorList._objects2._sprites = mazeObject._sprites;
 			_indoorList._objects2._flags &= ~SPRFLAG_HORIZ_FLIPPED;
 			if (mazeObject._flipped)
 				_indoorList._objects2._flags |= SPRFLAG_HORIZ_FLIPPED;
-			_objNumber = idx;
 		}
 
-		// Position 4 onwards
-		// TODO: Also resolve usage of _objectFlag* flags
+		// Position 4
+		pt = Common::Point(mazePos.x + posOffset[9], mazePos.y + posOffset[201]);
+		if (pt == mazeObject._position && (!_wo[27] || !_wo[26]) && (!_wo[27] || !_wo[29]) &&
+				(!_wo[24] || !_wo[26]) && (!_wo[24] || !_wo[29]) && _indoorList._objects3._frame == -1) {
+			_indoorList._objects3._x = INDOOR_OBJECT_X[listOffset][3];
+			_indoorList._objects3._y = INDOOR_OBJECT_Y[listOffset][3];
+			_indoorList._objects3._frame = mazeObject._frame;
+			_indoorList._objects3._sprites = mazeObject._sprites;
+			_indoorList._objects3._flags &= ~SPRFLAG_HORIZ_FLIPPED;
+			if (mazeObject._flipped)
+				_indoorList._objects3._flags |= SPRFLAG_HORIZ_FLIPPED;
+		}
+
+		// Position 5
+		pt = Common::Point(mazePos.x + posOffset[14], mazePos.y + posOffset[206]);
+		if (pt == mazeObject._position && !_wo[22] && !_wo[27] && _indoorList._objects4._frame == -1) {
+			_indoorList._objects4._x = INDOOR_OBJECT_X[listOffset][4];
+			_indoorList._objects4._y = INDOOR_OBJECT_Y[listOffset][4];
+			_indoorList._objects4._frame = mazeObject._frame;
+			_indoorList._objects4._sprites = mazeObject._sprites;
+			_indoorList._objects4._flags &= ~SPRFLAG_HORIZ_FLIPPED;
+			if (mazeObject._flipped)
+				_indoorList._objects4._flags |= SPRFLAG_HORIZ_FLIPPED;
+		}
+
+		// Position 6
+		pt = Common::Point(mazePos.x + posOffset[12], mazePos.y + posOffset[204]);
+		if (pt == mazeObject._position && !_wo[27] && (!_wo[22] || !_wo[23]) && (!_wo[22] || !_wo[20]) &&
+				(!_wo[23] || !_wo[17]) && (!_wo[20] || !_wo[17]) && _indoorList._objects5._frame == -1) {
+			_indoorList._objects5._x = INDOOR_OBJECT_X[listOffset][5];
+			_indoorList._objects5._y = INDOOR_OBJECT_Y[listOffset][5];
+			_indoorList._objects5._frame = mazeObject._frame;
+			_indoorList._objects5._sprites = mazeObject._sprites;
+			_indoorList._objects5._flags &= ~SPRFLAG_HORIZ_FLIPPED;
+			if (mazeObject._flipped)
+				_indoorList._objects5._flags |= SPRFLAG_HORIZ_FLIPPED;
+		}
+
+		// Position 7
+		pt = Common::Point(mazePos.x + posOffset[16], mazePos.y + posOffset[208]);
+		if (pt == mazeObject._position && !_wo[27] && (!_wo[22] || !_wo[24]) && (!_wo[22] || !_wo[21]) &&
+			(!_wo[24] || !_wo[19]) && (!_wo[21] || !_wo[19]) && _indoorList._objects6._frame == -1) {
+			_indoorList._objects6._x = INDOOR_OBJECT_X[listOffset][6];
+			_indoorList._objects6._y = INDOOR_OBJECT_Y[listOffset][6];
+			_indoorList._objects6._frame = mazeObject._frame;
+			_indoorList._objects6._sprites = mazeObject._sprites;
+			_indoorList._objects6._flags &= ~SPRFLAG_HORIZ_FLIPPED;
+			if (mazeObject._flipped)
+				_indoorList._objects6._flags |= SPRFLAG_HORIZ_FLIPPED;
+		}
+
+		// Position 8
+		pt = Common::Point(mazePos.x + posOffset[27], mazePos.y + posOffset[219]);
+		if (pt == mazeObject._position && !_wo[27] && !_wo[22] && !_wo[15] &&  _indoorList._objects7._frame == -1) {
+			_indoorList._objects7._x = INDOOR_OBJECT_X[listOffset][7];
+			_indoorList._objects7._y = INDOOR_OBJECT_Y[listOffset][7];
+			_indoorList._objects7._frame = mazeObject._frame;
+			_indoorList._objects7._sprites = mazeObject._sprites;
+			_indoorList._objects7._flags &= ~SPRFLAG_HORIZ_FLIPPED;
+			if (mazeObject._flipped)
+				_indoorList._objects7._flags |= SPRFLAG_HORIZ_FLIPPED;
+		}
+
+		// Position 9
+		pt = Common::Point(mazePos.x + posOffset[25], mazePos.y + posOffset[217]);
+		if (pt == mazeObject._position && !_wo[27] && (!_wo[15] || !_wo[17]) && (!_wo[15] || !_wo[12]) &&
+				(!_wo[12] || !_wo[7]) && (!_wo[17] || !_wo[7]) && _indoorList._objects5._frame == -1) {
+			_indoorList._objects8._x = INDOOR_OBJECT_X[listOffset][8];
+			_indoorList._objects8._y = INDOOR_OBJECT_Y[listOffset][8];
+			_indoorList._objects8._frame = mazeObject._frame;
+			_indoorList._objects8._sprites = mazeObject._sprites;
+			_indoorList._objects8._flags &= ~SPRFLAG_HORIZ_FLIPPED;
+			if (mazeObject._flipped)
+				_indoorList._objects8._flags |= SPRFLAG_HORIZ_FLIPPED;
+		}
+
+		// Position 10
+		pt = Common::Point(mazePos.x + posOffset[23], mazePos.y + posOffset[215]);
+		if (pt == mazeObject._position && !_wo[27] && (!_wo[22] || !_wo[20]) && (!_wo[22] || !_wo[23]) &&
+				(!_wo[20] || !_wo[17]) && (!_wo[23] || !_wo[17]) && !_wo[12] && !_wo[8] &&			
+				_indoorList._objects9._frame == -1) {
+			_indoorList._objects9._x = INDOOR_OBJECT_X[listOffset][9];
+			_indoorList._objects9._y = INDOOR_OBJECT_Y[listOffset][9];
+			_indoorList._objects9._frame = mazeObject._frame;
+			_indoorList._objects9._sprites = mazeObject._sprites;
+			_indoorList._objects9._flags &= ~SPRFLAG_HORIZ_FLIPPED;
+			if (mazeObject._flipped)
+				_indoorList._objects9._flags |= SPRFLAG_HORIZ_FLIPPED;
+		}
+
+		// Block 11
+		pt = Common::Point(mazePos.x + posOffset[29], mazePos.y + posOffset[221]);
+		if (pt == mazeObject._position && !_wo[27] && !_wo[22] && (!_wo[15] || !_wo[19]) && 
+				(!_wo[15] || !_wo[14]) && (!_wo[14] || !_wo[9]) && (!_wo[19] || !_wo[9]) && 
+				_indoorList._objects10._frame == -1) {
+			_indoorList._objects10._x = INDOOR_OBJECT_X[listOffset][10];
+			_indoorList._objects10._y = INDOOR_OBJECT_Y[listOffset][10];
+			_indoorList._objects10._frame = mazeObject._frame;
+			_indoorList._objects10._sprites = mazeObject._sprites;
+			_indoorList._objects10._flags &= ~SPRFLAG_HORIZ_FLIPPED;
+			if (mazeObject._flipped)
+				_indoorList._objects10._flags |= SPRFLAG_HORIZ_FLIPPED;
+		}
+
+		// Block 12
+		pt = Common::Point(mazePos.x + posOffset[31], mazePos.y + posOffset[223]);
+		if (pt == mazeObject._position && !_wo[27] && (!_wo[22] || !_wo[21]) && (!_wo[22] || !_wo[24]) && 
+				(!_wo[21] || !_wo[19]) && (!_wo[24] || !_wo[19]) && !_wo[14] && !_wo[10] &&
+				_indoorList._objects11._frame == -1) {
+			_indoorList._objects11._x = INDOOR_OBJECT_X[listOffset][11];
+			_indoorList._objects11._y = INDOOR_OBJECT_Y[listOffset][11];
+			_indoorList._objects11._frame = mazeObject._frame;
+			_indoorList._objects11._sprites = mazeObject._sprites;
+			_indoorList._objects11._flags &= ~SPRFLAG_HORIZ_FLIPPED;
+			if (mazeObject._flipped)
+				_indoorList._objects11._flags |= SPRFLAG_HORIZ_FLIPPED;
+		}
 	}
 }
 
diff --git a/engines/xeen/interface.h b/engines/xeen/interface.h
index 3bb0fa7..404beca 100644
--- a/engines/xeen/interface.h
+++ b/engines/xeen/interface.h
@@ -99,8 +99,8 @@ private:
 	bool _flag2;
 	byte _tillMove;
 	int _objNumber;
-	bool _objectFlag2, _objectFlag3, _objectFlag4, _objectFlag5;
-	bool _objectFlag6, _objectFlag7, _objectFlag8;
+	byte _wp[20];
+	byte _wo[308];
 
 	void loadSprites();
 


Commit: 892a504009e0d7d6d6304d485bf2fad9519781e9
    https://github.com/scummvm/scummvm/commit/892a504009e0d7d6d6304d485bf2fad9519781e9
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-01-11T18:29:36-05:00

Commit Message:
XEEN: Implemented loading of object animation data

Changed paths:
    engines/xeen/interface.cpp
    engines/xeen/map.cpp
    engines/xeen/map.h



diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp
index b003e9a..665ce67 100644
--- a/engines/xeen/interface.cpp
+++ b/engines/xeen/interface.cpp
@@ -868,6 +868,17 @@ void Interface::draw3d(bool flag) {
 			moveMonsters();
 	}
 
+	int e3 = 0xE302 + _objNumber * 8;
+	Direction dir = _vm->_party._mazeDirection;
+	bool flag2 = _flag2;
+	int objNum = _objNumber - 1;
+
+	for (uint i = 0; i < _vm->_map->_mobData._objects.size(); ++i) {
+		if (flag2) {
+
+		}
+	}
+
 	// TODO: more
 
 	warning("TODO");
diff --git a/engines/xeen/map.cpp b/engines/xeen/map.cpp
index c70b0cf..836680c 100644
--- a/engines/xeen/map.cpp
+++ b/engines/xeen/map.cpp
@@ -809,6 +809,49 @@ void HeadData::synchronize(Common::SeekableReadStream &s) {
 
 /*------------------------------------------------------------------------*/
 
+/**
+ * Synchronize data for an entry within an animation entry
+ */
+void AnimationFrame::synchronize(Common::SeekableReadStream &s) {
+	_left = s.readByte();
+	_back = s.readByte();
+	_right = s.readByte();
+	_front = s.readByte();
+}
+
+/**
+ * Synchronize data for an animation entry
+ */
+void AnimationEntry::synchronize(Common::SeekableReadStream &s) {
+	_frame1.synchronize(s);
+	_flipped.synchronize(s);
+	_frame2.synchronize(s);
+}
+
+/**
+ * Synchronize data for object animations within the game
+ */
+void AnimationInfo::synchronize(Common::SeekableReadStream &s) {
+	AnimationEntry entry;
+
+	clear();
+	while (s.pos() < s.size()) {
+		entry.synchronize(s);
+		push_back(entry);
+	}
+}
+
+/**
+ * Load the animation info objects in the game
+ */
+void AnimationInfo::load(const Common::String &name) {
+	File f(name);
+	synchronize(f);
+	f.close();
+}
+
+/*------------------------------------------------------------------------*/
+
 Map::Map(XeenEngine *vm) : _vm(vm), _mobData(vm) {
 	_townPortalSide = 0;
 	_sideObj = 0;
@@ -849,7 +892,7 @@ void Map::load(int mapId) {
 
 	if (_vm->getGameID() == GType_WorldOfXeen) {
 		if (_vm->_loadDarkSide) {
-			_objPicSprites.load("clouds.dat");
+			_animationInfo.load("clouds.dat");
 			_monsterData.load("xeen.mon");
 			_wallPicSprites.load("xeenpic.dat");
 		} else {
@@ -859,7 +902,7 @@ void Map::load(int mapId) {
 			case 115:
 			case 116:
 			case 128:
-				_objPicSprites.load("clouds.dat");
+				_animationInfo.load("clouds.dat");
 				_monsterData.load("dark.mon");
 				_wallPicSprites.load("darkpic.dat");
 				_sideObj = 0;
@@ -869,7 +912,7 @@ void Map::load(int mapId) {
 			case 119:
 			case 120:
 			case 124:
-				_objPicSprites.load("clouds.dat");
+				_animationInfo.load("clouds.dat");
 				_monsterData.load("xeen.mon");
 				_wallPicSprites.load("darkpic.dat");
 				_sideObj = 0;
@@ -878,12 +921,12 @@ void Map::load(int mapId) {
 			case 125:
 			case 126:
 			case 127:
-				_objPicSprites.load("clouds.dat");
+				_animationInfo.load("clouds.dat");
 				_monsterData.load("dark.mon");
 				_wallPicSprites.load("xeenpic.dat");
 				break;
 			default:
-				_objPicSprites.load("dark.dat");
+				_animationInfo.load("dark.dat");
 				_monsterData.load("ddark.mon");
 				_wallPicSprites.load("darkpic.dat");
 				break;
diff --git a/engines/xeen/map.h b/engines/xeen/map.h
index d26dfff..228dfb8 100644
--- a/engines/xeen/map.h
+++ b/engines/xeen/map.h
@@ -311,13 +311,36 @@ public:
 	void synchronize(Common::SeekableReadStream &s);
 };
 
+struct AnimationFrame {
+	int _front, _left, _back, _right;
+
+	AnimationFrame(): _front(0), _left(0), _back(0), _right(0) {}
+
+	void synchronize(Common::SeekableReadStream &s);
+};
+
+struct AnimationEntry {
+	AnimationFrame _frame1;
+	AnimationFrame _flipped;
+	AnimationFrame _frame2;
+
+	void synchronize(Common::SeekableReadStream &s);
+};
+
+class AnimationInfo : public Common::Array<AnimationEntry> {
+public:
+	void synchronize(Common::SeekableReadStream &s);
+
+	void load(const Common::String &name);
+};
+
 class Map {
 private:
 	XeenEngine *_vm;
 	MazeData _mazeData[9];
 	Common::String _mazeName;
 	HeadData _headData;
-	SpriteResource _objPicSprites;
+	AnimationInfo _animationInfo;
 	MonsterData _monsterData;
 	SpriteResource _wallPicSprites;
 	int _townPortalSide;


Commit: 1b3473d3431ae8fcac15526f1a59f1dfd0c9fc58
    https://github.com/scummvm/scummvm/commit/1b3473d3431ae8fcac15526f1a59f1dfd0c9fc58
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-01-11T19:30:02-05:00

Commit Message:
XEEN: Implement frame update loop of draw3d

Changed paths:
    engines/xeen/interface.cpp
    engines/xeen/interface.h
    engines/xeen/map.cpp
    engines/xeen/map.h
    engines/xeen/resources.cpp
    engines/xeen/resources.h



diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp
index 665ce67..9e02806 100644
--- a/engines/xeen/interface.cpp
+++ b/engines/xeen/interface.cpp
@@ -361,7 +361,8 @@ Interface::Interface(XeenEngine *vm) : ButtonContainer(), _vm(vm) {
 	_intrIndex1 = 0;
 	_flipWtr = false;
 	_flag1 = false;
-	_flag2 = false;
+	_animCounter = 0;
+	_isAnimReset = false;
 	_tillMove = 0;
 	_objNumber = 0;
 
@@ -868,15 +869,30 @@ void Interface::draw3d(bool flag) {
 			moveMonsters();
 	}
 
-	int e3 = 0xE302 + _objNumber * 8;
-	Direction dir = _vm->_party._mazeDirection;
-	bool flag2 = _flag2;
+	MazeObject &objObject = _vm->_map->_mobData._objects[_objNumber];
+	Direction partyDirection = _vm->_party._mazeDirection;
 	int objNum = _objNumber - 1;
 
 	for (uint i = 0; i < _vm->_map->_mobData._objects.size(); ++i) {
-		if (flag2) {
+		MazeObject &mazeObject = _vm->_map->_mobData._objects[i];
+		AnimationEntry &animEntry = _vm->_map->_animationInfo[mazeObject._spriteId];
+		int directionIndex = DIRECTION_ANIM_POSITIONS[mazeObject._direction][partyDirection];
 
+		if (_isAnimReset) {
+			mazeObject._frame = animEntry._frame1._frames[directionIndex];
+		} else {
+			++mazeObject._frame;
+			if (i == objNum && _animCounter > 0 && (
+					objObject._spriteId == (_vm->_files->_isDarkCc ? 15 : 16) ||
+					objObject._spriteId == 58 || objObject._spriteId == 73)) {
+				if (mazeObject._frame > 4 || mazeObject._spriteId == 58)
+					mazeObject._frame = 1;
+			} else if (mazeObject._frame == animEntry._frame2._frames[directionIndex]) {
+				mazeObject._frame = animEntry._frame2._frames[directionIndex];
+			}
 		}
+
+		mazeObject._flipped = animEntry._flipped._flags[directionIndex];
 	}
 
 	// TODO: more
diff --git a/engines/xeen/interface.h b/engines/xeen/interface.h
index 404beca..d161169 100644
--- a/engines/xeen/interface.h
+++ b/engines/xeen/interface.h
@@ -96,7 +96,8 @@ private:
 	int _intrIndex1;
 	bool _flipWtr;
 	bool _flag1;
-	bool _flag2;
+	int _animCounter;
+	bool _isAnimReset;
 	byte _tillMove;
 	int _objNumber;
 	byte _wp[20];
diff --git a/engines/xeen/map.cpp b/engines/xeen/map.cpp
index 836680c..b8ea36b 100644
--- a/engines/xeen/map.cpp
+++ b/engines/xeen/map.cpp
@@ -810,22 +810,15 @@ void HeadData::synchronize(Common::SeekableReadStream &s) {
 /*------------------------------------------------------------------------*/
 
 /**
- * Synchronize data for an entry within an animation entry
- */
-void AnimationFrame::synchronize(Common::SeekableReadStream &s) {
-	_left = s.readByte();
-	_back = s.readByte();
-	_right = s.readByte();
-	_front = s.readByte();
-}
-
-/**
  * Synchronize data for an animation entry
  */
 void AnimationEntry::synchronize(Common::SeekableReadStream &s) {
-	_frame1.synchronize(s);
-	_flipped.synchronize(s);
-	_frame2.synchronize(s);
+	for (int i = 0; i < 4; ++i)
+		_frame1._frames[i] = s.readByte();
+	for (int i = 0; i < 4; ++i)
+		_flipped._flags[i] = s.readByte() != 0;
+	for (int i = 0; i < 4; ++i)
+		_frame2._frames[i] = s.readByte();
 }
 
 /**
diff --git a/engines/xeen/map.h b/engines/xeen/map.h
index 228dfb8..7255552 100644
--- a/engines/xeen/map.h
+++ b/engines/xeen/map.h
@@ -311,18 +311,21 @@ public:
 	void synchronize(Common::SeekableReadStream &s);
 };
 
-struct AnimationFrame {
-	int _front, _left, _back, _right;
-
-	AnimationFrame(): _front(0), _left(0), _back(0), _right(0) {}
-
-	void synchronize(Common::SeekableReadStream &s);
-};
-
+struct AnimationFrame { int _front, _left, _back, _right; };
+struct AnimationFlipped { bool _front, _left, _back, _right; };
 struct AnimationEntry {
-	AnimationFrame _frame1;
-	AnimationFrame _flipped;
-	AnimationFrame _frame2;
+	union {
+		AnimationFrame _positions;
+		int _frames[4];
+	} _frame1;
+	union {
+		AnimationFlipped _positions;
+		bool _flags[4];
+	} _flipped;
+	union {
+		AnimationFrame _positions;
+		int _frames[4];
+	} _frame2;
 
 	void synchronize(Common::SeekableReadStream &s);
 };
@@ -339,8 +342,6 @@ private:
 	XeenEngine *_vm;
 	MazeData _mazeData[9];
 	Common::String _mazeName;
-	HeadData _headData;
-	AnimationInfo _animationInfo;
 	MonsterData _monsterData;
 	SpriteResource _wallPicSprites;
 	int _townPortalSide;
@@ -358,6 +359,8 @@ public:
 	bool _isOutdoors;
 	MonsterObjectData _mobData;
 	MazeEvents _events;
+	HeadData _headData;
+	AnimationInfo _animationInfo;
 	bool _currentIsGrate;
 	bool _currentCantRest;
 	bool _currentIsDrain;
diff --git a/engines/xeen/resources.cpp b/engines/xeen/resources.cpp
index 35fa2cb..e660014 100644
--- a/engines/xeen/resources.cpp
+++ b/engines/xeen/resources.cpp
@@ -350,4 +350,8 @@ const int OUTDOOR_OBJECT_Y[2][12] = {
 	{ 70, 71, 72, 73, 74, 75, 90, 91, 92, 93, 94, 112 }
 };
 
+const int DIRECTION_ANIM_POSITIONS[4][4] = {
+	{ 0, 1, 2, 3 }, { 3, 0, 1, 2 }, { 2, 3, 0, 1 }, { 1, 2, 3, 0 }
+};
+
 } // End of namespace Xeen
diff --git a/engines/xeen/resources.h b/engines/xeen/resources.h
index d8cc93b..35b8256 100644
--- a/engines/xeen/resources.h
+++ b/engines/xeen/resources.h
@@ -78,6 +78,8 @@ extern const int OUTDOOR_OBJECT_X[2][12];
 
 extern const int OUTDOOR_OBJECT_Y[2][12];
 
+extern const int DIRECTION_ANIM_POSITIONS[4][4];
+
 } // End of namespace Xeen
 
 #endif	/* XEEN_RESOURCES_H */


Commit: d8e23aa558ffda15e36d087dee6e3f3d1db659ff
    https://github.com/scummvm/scummvm/commit/d8e23aa558ffda15e36d087dee6e3f3d1db659ff
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-01-11T20:35:32-05:00

Commit Message:
XEEN: Split up SCREEN_POSITIONING array and fix data

Changed paths:
    engines/xeen/interface.cpp
    engines/xeen/interface.h
    engines/xeen/resources.cpp
    engines/xeen/resources.h



diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp
index 9e02806..0ae64ca 100644
--- a/engines/xeen/interface.cpp
+++ b/engines/xeen/interface.cpp
@@ -363,6 +363,7 @@ Interface::Interface(XeenEngine *vm) : ButtonContainer(), _vm(vm) {
 	_flag1 = false;
 	_animCounter = 0;
 	_isAnimReset = false;
+	_charsShooting = false;
 	_tillMove = 0;
 	_objNumber = 0;
 
@@ -873,6 +874,8 @@ void Interface::draw3d(bool flag) {
 	Direction partyDirection = _vm->_party._mazeDirection;
 	int objNum = _objNumber - 1;
 
+	// Loop to update the frame numbers for each maze object, applying the animation frame
+	// limits as specified by the map's _animationInfo listing
 	for (uint i = 0; i < _vm->_map->_mobData._objects.size(); ++i) {
 		MazeObject &mazeObject = _vm->_map->_mobData._objects[i];
 		AnimationEntry &animEntry = _vm->_map->_animationInfo[mazeObject._spriteId];
@@ -895,6 +898,40 @@ void Interface::draw3d(bool flag) {
 		mazeObject._flipped = animEntry._flipped._flags[directionIndex];
 	}
 
+	if (_vm->_map->_isOutdoors) {
+		error("TODO: draw3d outdoors handling");
+	} else {
+		// Default all the parts of draw struct not to be drawn by default
+		for (int idx = 3; idx < _indoorList.size(); ++idx)
+			_indoorList[idx]._frame = -1;
+
+		if (_flag1) {
+			for (int idx = 0; idx < 96; ++idx) {
+				if (_indoorList[79 + idx]._sprites != nullptr) {
+					_indoorList[79 + idx]._frame = 0;
+				} else if (_indoorList[111 + idx]._sprites != nullptr) {
+					_indoorList[111 + idx]._frame = 1;
+				} else if (_indoorList[135 + idx]._sprites != nullptr) {
+					_indoorList[135 + idx]._frame = 2;
+				} else if (_indoorList[162 + idx]._sprites != nullptr) {
+					_indoorList[162 + idx]._frame = 0;
+				}
+			}
+		} else if (_charsShooting) {
+			for (int idx = 0; idx < 96; ++idx) {
+				if (_indoorList[162 + idx]._sprites != nullptr) {
+					_indoorList[162 + idx]._frame = 0;
+				} else if (_indoorList[135 + idx]._sprites != nullptr) {
+					_indoorList[135 + idx]._frame = 1;
+				} else if (_indoorList[111 + idx]._sprites != nullptr) {
+					_indoorList[111 + idx]._frame = 2;
+				} else if (_indoorList[79 + idx]._sprites != nullptr) {
+					_indoorList[79 + idx]._frame = 0;
+				}
+			}
+		}
+	}
+
 	// TODO: more
 
 	warning("TODO");
@@ -911,7 +948,7 @@ void Interface::setIndoorsMonsters() {
 void Interface::setIndoorObjects() {
 	Common::Point mazePos = _vm->_party._mazePosition;
 	_objNumber = 0;
-	const int8 *posOffset = &SCREEN_POSITIONING[_vm->_party._mazeDirection * 48];
+	const int8 *posOffset = &SCREEN_POSITIONING_X[_vm->_party._mazeDirection][0];
 	Common::Point pt;
 
 	Common::Array<MazeObject> &objects = _vm->_map->_mobData._objects;
@@ -1158,4 +1195,12 @@ void Interface::setMainButtons() {
 	addButton(Common::Rect(239,  47, 312,  57),  51, &_iconSprites, false);
 }
 
+void Interface::setMazeBits() {
+
+}
+
+void Interface::getCell() {
+}
+
+
 } // End of namespace Xeen
diff --git a/engines/xeen/interface.h b/engines/xeen/interface.h
index d161169..1c11035 100644
--- a/engines/xeen/interface.h
+++ b/engines/xeen/interface.h
@@ -40,7 +40,12 @@ public:
 public:
 	OutdoorDrawList();
 
-	DrawStruct &operator[](int idx) { return _data[idx]; }
+	DrawStruct &operator[](int idx) { 
+		assert(idx < size());
+		return _data[idx]; 
+	}
+
+	int size() const { return 132; }
 };
 
 class IndoorDrawList {
@@ -54,7 +59,12 @@ public:
 public:
 	IndoorDrawList();
 
-	DrawStruct &operator[](int idx) { return _data[idx]; }
+	DrawStruct &operator[](int idx) { 
+		assert(idx < size());
+		return _data[idx]; 
+	}
+
+	int size() const { return 170; }
 };
 
 
@@ -98,6 +108,7 @@ private:
 	bool _flag1;
 	int _animCounter;
 	bool _isAnimReset;
+	bool _charsShooting;
 	byte _tillMove;
 	int _objNumber;
 	byte _wp[20];
@@ -132,6 +143,10 @@ private:
 	void moveMonsters();
 
 	void setMainButtons();
+
+	void setMazeBits();
+
+	void getCell();
 public:
 	Interface(XeenEngine *vm);
 
diff --git a/engines/xeen/resources.cpp b/engines/xeen/resources.cpp
index e660014..0737e14 100644
--- a/engines/xeen/resources.cpp
+++ b/engines/xeen/resources.cpp
@@ -303,31 +303,52 @@ const char *const PLEASE_WAIT = "\014""d\003""c\011""000"
 
 const char *const OOPS = "\003""c\011""000\013""002Oops...";
 
-const int8 SCREEN_POSITIONING[384] = {
-	-1,  0,  0,  0,  1, -1,  0,  0,  0,  1, -2, -1, -1,  0,  0,  0,
-	 1,  1,  2, -4, -3, -3, -2, -2, -1, -1,  0,  0,  0,  1,  1,  2,
-	 2,  3,  3,  4, -3, -2, -1,  0,  0,  1,  2,  3, -4,  4,  0,  0,
-	 0,  0,  0,  0,  0,  1,  1,  1,  1,  1,  2,  2,  2,  2,  2,  2,
-	 2,  2,  2,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,
-	 3,  3,  3,  3,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  0,  1,
-	 1,  0,  0,  0, -1,  1,  0,  0,  0, -1,  2,  1,  1,  0,  0,  0,
-	-1, -1, -2,  4,  3,  3,  2,  2,  1,  1,  0,  0,  0, -1, -1, -2,
-	-2, -3, -3, -4,  3,  2,  1,  0,  0, -1, -2, -3,  4, -4,  0,  0,
-	 0,  0,  0,  0,  0, -1, -1, -1, -1, -1, -2, -2, -2, -2, -2, -2,
-	-2, -2, -2, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3,
-	-3, -3, -3, -3, -4, -4, -4, -4, -4, -4, -4, -4, -4, -4,  0, -1,
-	 0,  0,  0,  0,  0,  1,  1,  1,  1,  1,  2,  2,  2,  2,  2,  2,
-	 2,  2,  2,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,
-	 3,  3,  3,  3,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  0,  1,
-	 1,  0,  0,  0, -1,  1,  0,  0,  0, -1,  2,  1,  1,  0,  0,  0,
-	-1, -1, -2,  4,  3,  3,  2,  2,  1,  1,  0,  0,  0, -1, -1, -2,
-	-2, -3, -3, -4,  3,  2,  1,  0,  0, -1, -2, -3,  4, -4,  0,  0,
-	 0,  0,  0,  0,  0, -1, -1, -1, -1, -1, -2, -2, -2, -2, -2, -2,
-	-2, -2, -2, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3,
-	-3, -3, -3, -3, -4, -4, -4, -4, -4, -4, -4, -4, -4, -4,  0, -1,
-	-1,  0,  0,  0,  1, -1,  0,  0,  0,  1, -2, -1, -1,  0,  0,  0,
-	 1,  1,  2, -4, -3, -3, -2, -2, -1, -1,  0,  0,  0,  1,  1,  2,
-	 2,  3,  3,  4, -3, -2, -1,  0,  0,  1,  2,  3, -4,  4,  0,  0,
+const int8 SCREEN_POSITIONING_X[4][48] = {
+	{
+	-1,  0,  0,  0,  1, -1,  0,  0,  0,  1, -2, -1,
+	-1,  0,  0,  0,  1,  1,  2, -4, -3, -3, -2, -2,
+	-1, -1,  0,  0,  0,  1,  1,  2,  2,  3,  3,  4, 
+	-3, -2, -1,  0,  0,  1,  2,  3, -4,  4,  0,  0
+	}, {
+	 0,  0,  0,  0,  0,  1,  1,  1,  1,  1,  2,  2,
+	 2,  2,  2,  2,  2,  2,  2,  3,  3,  3,  3,  3,
+	 3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,
+	 4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  0,  1
+	}, {
+	 1,  0,  0,  0, -1,  1,  0,  0,  0, -1,  2,  1,
+	 1,  0,  0,  0, -1, -1, -2,  4,  3,  3,  2,  2,
+	 1,  1,  0,  0,  0, -1, -1, -2, -2, -3, -3, -4,
+	 3,  2,  1,  0,  0, -1, -2, -3,  4, -4,  0,  0
+	}, {
+	 0,  0,  0,  0,  0, -1, -1, -1, -1, -1, -2, -2, 
+	-2, -2, -2, -2, -2, -2, -2, -3, -3, -3, -3, -3,
+	-3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3,
+	-4, -4, -4, -4, -4, -4, -4, -4, -4, -4,  0, -1
+	}
+};
+
+const int8 SCREEN_POSITIONING_Y[4][48] = {
+	{
+	 0,  0,  0,  0,  0,  1,  1,  1,  1,  1,  2,  2,
+	 2,  2,  2,  2,  2,  2,  2,  3,  3,  3,  3,  3,
+	 3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,
+	 4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  0,  1
+	}, {
+	 1,  0,  0,  0, -1,  1,  0,  0,  0, -1,  2,  1,
+	 1,  0,  0,  0, -1, -1, -2,  4,  3,  3,  2,  2,
+	 1,  1,  0,  0,  0, -1, -1, -2, -2, -3, -3, -4,
+	 3,  2,  1,  0,  0, -1, -2, -3,  4, -4,  0,  0
+	}, {
+	 0,  0,  0,  0,  0, -1, -1, -1, -1, -1, -2, -2,
+	-2, -2, -2, -2, -2, -2, -2, -3, -3, -3, -3, -3,
+	-3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3,
+	-4, -4, -4, -4, -4, -4, -4, -4, -4, -4,  0, -1
+	}, {
+	-1,  0,  0,  0,  1, -1,  0,  0,  0,  1, -2, -1,
+	-1,  0,  0,  0,  1,  1,  2, -4, -3, -3, -2, -2,
+	-1, -1,  0,  0,  0,  1,  1,  2,  2,  3,  3,  4,
+	-3, -2, -1,  0,  0,  1,  2,  3, -4,  4,  0,  0
+	}
 };
 
 const int INDOOR_OBJECT_X[2][12] = {
diff --git a/engines/xeen/resources.h b/engines/xeen/resources.h
index 35b8256..36c2cb0 100644
--- a/engines/xeen/resources.h
+++ b/engines/xeen/resources.h
@@ -68,7 +68,9 @@ extern const char *const PLEASE_WAIT;
 
 extern const char *const OOPS;
 
-extern const int8 SCREEN_POSITIONING[384];
+extern const int8 SCREEN_POSITIONING_X[4][48];
+
+extern const int8 SCREEN_POSITIONING_Y[4][48];
 
 extern const int INDOOR_OBJECT_X[2][12];
 


Commit: 230c4f52ea8f5c95ea28a5f25bcf5c6f89acbd60
    https://github.com/scummvm/scummvm/commit/230c4f52ea8f5c95ea28a5f25bcf5c6f89acbd60
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-01-11T23:55:46-05:00

Commit Message:
XEEN: Implemented map getCell method

Changed paths:
    engines/xeen/interface.cpp
    engines/xeen/interface.h
    engines/xeen/map.cpp
    engines/xeen/map.h
    engines/xeen/resources.cpp
    engines/xeen/resources.h



diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp
index 0ae64ca..4fb943f 100644
--- a/engines/xeen/interface.cpp
+++ b/engines/xeen/interface.cpp
@@ -885,7 +885,7 @@ void Interface::draw3d(bool flag) {
 			mazeObject._frame = animEntry._frame1._frames[directionIndex];
 		} else {
 			++mazeObject._frame;
-			if (i == objNum && _animCounter > 0 && (
+			if ((int)i == objNum && _animCounter > 0 && (
 					objObject._spriteId == (_vm->_files->_isDarkCc ? 15 : 16) ||
 					objObject._spriteId == 58 || objObject._spriteId == 73)) {
 				if (mazeObject._frame > 4 || mazeObject._spriteId == 58)
@@ -1199,8 +1199,4 @@ void Interface::setMazeBits() {
 
 }
 
-void Interface::getCell() {
-}
-
-
 } // End of namespace Xeen
diff --git a/engines/xeen/interface.h b/engines/xeen/interface.h
index 1c11035..d50cdd0 100644
--- a/engines/xeen/interface.h
+++ b/engines/xeen/interface.h
@@ -145,8 +145,6 @@ private:
 	void setMainButtons();
 
 	void setMazeBits();
-
-	void getCell();
 public:
 	Interface(XeenEngine *vm);
 
diff --git a/engines/xeen/map.cpp b/engines/xeen/map.cpp
index b8ea36b..b6bf91d 100644
--- a/engines/xeen/map.cpp
+++ b/engines/xeen/map.cpp
@@ -854,6 +854,8 @@ Map::Map(XeenEngine *vm) : _vm(vm), _mobData(vm) {
 	_mazeDataIndex = 0;
 	_currentSteppedOn = false;
 	_currentSurfaceId = 0;
+	_currentWall = 0;
+	_currentTile = 0;
 	_currentIsGrate = false;
 	_currentCantRest = false;
 	_currentIsDrain = false;
@@ -1217,4 +1219,132 @@ void Map::setCellSurfaceFlags(const Common::Point &pt, int bits) {
 	_mazeData[0]._cells[pt.y][pt.x]._surfaceId |= bits;
 }
 
+
+int Map::getCell(int idx) {
+	int mapId = _vm->_party._mazeId;
+	Direction dir = _vm->_party._mazeDirection;
+	Common::Point pt(
+		_vm->_party._mazePosition.x + SCREEN_POSITIONING_X[_vm->_party._mazeDirection][idx],
+		_vm->_party._mazePosition.y + SCREEN_POSITIONING_Y[_vm->_party._mazeDirection][idx]
+	);
+
+	if (pt.x > 31 || pt.y > 31) {
+		if (_vm->_files->_isDarkCc) {
+			if ((mapId >= 53 && mapId <= 88 && mapId != 73) || (mapId >= 74 && mapId <= 120) ||
+					mapId == 125 || mapId == 126 || mapId == 128 || mapId == 129) {
+				_currentSurfaceId = SURFTYPE_DESERT;
+			} else {
+				_currentSurfaceId = 0;
+			}
+		} else {
+			_currentSurfaceId = (mapId >= 25 && mapId <= 27) ? 7 : 0;
+		}
+		_currentWall = 0x8888;
+		return _currentWall;
+	} 
+
+	_mazeDataIndex = 0;
+	while (_mazeData[_mazeDataIndex]._mazeId != mapId)
+		++_mazeDataIndex;
+
+	if (pt.y & 16) {
+		if (pt.y >= 0) {
+			pt.y -= 16;
+			mapId = _mazeData[_mazeDataIndex]._surroundingMazes._north;
+		} else {
+			pt.y += 16;
+			mapId = _mazeData[_mazeDataIndex]._surroundingMazes._south;
+		}
+
+		if (!mapId) {
+			if (_isOutdoors) {
+				_currentSurfaceId = SURFTYPE_SPACE;
+				_currentWall = 0;
+				return 0;
+			} else {
+				if (_vm->_files->_isDarkCc) {
+					if ((mapId >= 53 && mapId <= 88 && mapId != 73) || (mapId >= 74 && mapId <= 120) ||
+						mapId == 125 || mapId == 126 || mapId == 128 || mapId == 129) {
+						_currentSurfaceId = SURFTYPE_DESERT;
+					} else {
+						_currentSurfaceId = 0;
+					}
+				} else {
+					_currentSurfaceId = (mapId >= 25 && mapId <= 27) ? SURFTYPE_ROAD : SURFTYPE_DEFAULT;
+				}
+
+				_currentWall = 0x8888;
+				return _currentWall;
+			}
+		
+			_mazeDataIndex = 0;
+			while (_mazeData[_mazeDataIndex]._mazeId != mapId)
+				++_mazeDataIndex;
+		}
+	}
+
+	if (pt.x & 16) {
+		if (pt.x >= 0) {
+			pt.x -= 16;
+			mapId = _mazeData[_mazeDataIndex]._surroundingMazes._east;
+		} else {
+			pt.x += 16;
+			mapId = _mazeData[_mazeDataIndex]._surroundingMazes._east;
+		}
+
+		if (!mapId) {
+			if (_isOutdoors) {
+				_currentSurfaceId = SURFTYPE_SPACE;
+				_currentWall = 0;
+				return _currentWall;
+			} else {
+				if (_vm->_files->_isDarkCc) {
+					if ((mapId >= 53 && mapId <= 88 && mapId != 73) || (mapId >= 74 && mapId <= 120) ||
+						mapId == 125 || mapId == 126 || mapId == 128 || mapId == 129) {
+						_currentSurfaceId = SURFTYPE_DESERT;
+					} else {
+						_currentSurfaceId = 0;
+					}
+				} else {
+					_currentSurfaceId = (mapId >= 25 && mapId <= 27) ? SURFTYPE_ROAD : SURFTYPE_DEFAULT;
+				}
+
+				_currentWall = 0x8888;
+				return _currentWall;
+			}
+
+			_mazeDataIndex = 0;
+			while (_mazeData[_mazeDataIndex]._mazeId != mapId)
+				++_mazeDataIndex;
+		}
+	}
+
+	MazeWallLayers &wallLayers = _mazeData[_mazeDataIndex]._wallData[pt.y][pt.x];
+	if (_isOutdoors) {
+		if (mapId) {
+			// TODO: tile is set to word of (wallLayers >> 8) && 0xff? Makes no sense
+			_currentTile = wallLayers._outdoors._surfaceId;
+			_currentWall = wallLayers._outdoors._iMiddle;
+			_currentSurfaceId = wallLayers._outdoors._surfaceId;
+		} else {
+			_currentSurfaceId = SURFTYPE_DEFAULT;
+			_currentWall = 0;
+			_currentTile = 0;
+		}
+	} else {
+		if (!mapId)
+			return 0;
+
+		if (pt.x > 31 || pt.y > 31)
+			_currentSurfaceId = SURFTYPE_ROAD;
+		else
+			_currentSurfaceId = _mazeData[_mazeDataIndex]._cells[pt.y][pt.x]._surfaceId;
+
+		_currentWall = wallLayers._data;
+		return (_currentWall >> (WALL_NUMBERS[dir][idx * 2] * 4)) & 0xF;
+	}
+
+	return _currentWall;
+}
+
 } // End of namespace Xeen
diff --git a/engines/xeen/map.h b/engines/xeen/map.h
index 7255552..17c3fc6 100644
--- a/engines/xeen/map.h
+++ b/engines/xeen/map.h
@@ -351,6 +351,8 @@ private:
 	int _mazeDataIndex;
 	bool _currentSteppedOn;
 	int _currentSurfaceId;
+	int _currentWall;
+	int _currentTile;
 
 	void loadEvents(int mapId);
 
@@ -377,6 +379,8 @@ public:
 	void setCellSurfaceFlags(const Common::Point &pt, int bits);
 
 	void saveMaze();
+
+	int getCell(int idx);
 };
 
 } // End of namespace Xeen
diff --git a/engines/xeen/resources.cpp b/engines/xeen/resources.cpp
index 0737e14..352e596 100644
--- a/engines/xeen/resources.cpp
+++ b/engines/xeen/resources.cpp
@@ -375,4 +375,44 @@ const int DIRECTION_ANIM_POSITIONS[4][4] = {
 	{ 0, 1, 2, 3 }, { 3, 0, 1, 2 }, { 2, 3, 0, 1 }, { 1, 2, 3, 0 }
 };
 
+const byte WALL_NUMBERS[4][96] = {
+	{
+	3, 0, 0, 0, 3, 0, 2, 0, 3, 0, 3, 0,
+	0, 0, 3, 0, 2, 0, 3, 0, 3, 0, 0, 0,
+	3, 0, 0, 0, 3, 0, 2, 0, 3, 0, 2, 0,
+	3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0,
+	0, 0, 3, 0, 0, 0, 3, 0, 2, 0, 3, 0,
+	2, 0, 3, 0, 2, 0, 3, 0, 2, 0, 3, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 0,
+	2, 0, 2, 0, 0, 0, 0, 0, 1, 0, 1, 0
+	}, {
+	2, 0, 3, 0, 2, 0, 1, 0, 2, 0, 2, 0,
+	3, 0, 2, 0, 1, 0, 2, 0, 2, 0, 3, 0,
+	2, 0, 3, 0, 2, 0, 1, 0, 2, 0, 1, 0,
+	2, 0, 2, 0, 3, 0, 2, 0, 3, 0, 2, 0,
+	3, 0, 2, 0, 3, 0, 2, 0, 1, 0, 2, 0,
+	1, 0, 2, 0, 1, 0, 2, 0, 1, 0, 2, 0,
+	3, 0, 3, 0, 3, 0, 3, 0, 1, 0, 1, 0,
+	1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0
+	}, {
+	1, 0, 2, 0, 1, 0, 0, 0, 1, 0, 1, 0,
+	2, 0, 1, 0, 0, 0, 1, 0, 1, 0, 2, 0,
+	1, 0, 2, 0, 1, 0, 0, 0, 1, 0, 0, 0,
+	1, 0, 1, 0, 2, 0, 1, 0, 2, 0, 1, 0,
+	2, 0, 1, 0, 2, 0, 1, 0, 0, 0, 1, 0,
+	0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0,
+	2, 0, 2, 0, 2, 0, 2, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 3, 0
+	}, {
+	0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 0, 0,
+	1, 0, 0, 0, 3, 0, 0, 0, 0, 0, 1, 0,
+	0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 3, 0,
+	0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0,
+	1, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0,
+	3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0,
+	1, 0, 1, 0, 1, 0, 1, 0, 3, 0, 3, 0,
+	3, 0, 3, 0, 0, 0, 0, 0, 2, 0, 2, 0
+	}
+};
+
 } // End of namespace Xeen
diff --git a/engines/xeen/resources.h b/engines/xeen/resources.h
index 36c2cb0..2c537fd 100644
--- a/engines/xeen/resources.h
+++ b/engines/xeen/resources.h
@@ -82,6 +82,8 @@ extern const int OUTDOOR_OBJECT_Y[2][12];
 
 extern const int DIRECTION_ANIM_POSITIONS[4][4];
 
+extern const byte WALL_NUMBERS[4][96];
+
 } // End of namespace Xeen
 
 #endif	/* XEEN_RESOURCES_H */


Commit: 488847006c5ddd29a6ab8de0145d80e26daab48c
    https://github.com/scummvm/scummvm/commit/488847006c5ddd29a6ab8de0145d80e26daab48c
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-01-12T20:25:12-05:00

Commit Message:
XEEN: Implemented setMazeBits

Changed paths:
    engines/xeen/interface.cpp
    engines/xeen/interface.h
    engines/xeen/map.h
    engines/xeen/xeen.cpp
    engines/xeen/xeen.h



diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp
index 4fb943f..46b7bc4 100644
--- a/engines/xeen/interface.cpp
+++ b/engines/xeen/interface.cpp
@@ -366,6 +366,7 @@ Interface::Interface(XeenEngine *vm) : ButtonContainer(), _vm(vm) {
 	_charsShooting = false;
 	_tillMove = 0;
 	_objNumber = 0;
+	_thinWall = false;
 
 	Common::fill(&_combatCharIds[0], &_combatCharIds[8], 0);
 	Common::fill(&_wp[0], &_wp[20], 0);
@@ -639,7 +640,7 @@ void Interface::assembleBorder() {
 
 	// Draw UI element to indicate whether can spot hidden doors
 	_borderSprites.draw(screen,
-		(_vm->_thinWall && _vm->_party.checkSkill(SPOT_DOORS)) ? _spotDoorsUIFrame + 28 : 28,
+		(_thinWall && _vm->_party.checkSkill(SPOT_DOORS)) ? _spotDoorsUIFrame + 28 : 28,
 		Common::Point(194, 91));
 	_spotDoorsUIFrame = (_spotDoorsUIFrame + 1) % 12;
 
@@ -1196,7 +1197,1498 @@ void Interface::setMainButtons() {
 }
 
 void Interface::setMazeBits() {
+	Common::fill(&_wo[0], &_wo[308], 0);
+
+	switch (_vm->_map->getCell(0)) {
+	case 0:
+		++_wo[125];
+		break;
+	case 1:
+		++_wo[69];
+		break;
+	case 2:
+		++_wo[185];
+		break;
+	case 3:
+	case 12:
+		++_wo[105];
+		break;
+	case 4:
+	case 7:
+		++_wo[25];
+		break;
+	case 5:
+		++_wo[225];
+		break;
+	case 6:
+		++_wo[205];
+		break;
+	case 8:
+		++_wo[145];
+		break;
+	case 9:
+		++_wo[305];
+		break;
+	case 10:
+		++_wo[245];
+		break;
+	case 11:
+		++_wo[165];
+		break;
+	case 13:
+		++_wo[265];
+		break;
+	case 14:
+		++_wo[285];
+		break;
+	default:
+		break;
+	}
+
+	switch (_vm->_map->getCell(1)) {
+	case 1:
+		++_wo[72];
+		break;
+	case 0:
+	case 2:
+	case 3:
+	case 4:
+	case 5:
+	case 6:
+	case 7:
+	case 8:
+	case 9:
+	case 10:
+	case 11:
+	case 12:
+	case 13:
+	case 14:
+		++_wo[28];
+		break;
+	default:
+		break;
+	}
+
+	switch (_vm->_map->getCell(2)) {
+	case 0:
+		++_wo[127];
+		break;
+	case 1:
+		++_wo[71];
+		break;
+	case 2:
+		++_wo[187];
+		break;
+	case 3:
+	case 12:
+		++_wo[107];
+		break;
+	case 4:
+	case 7:
+		_wo[27];
+		break;
+	case 5:
+		++_wo[227];
+		break;
+	case 6:
+		++_wo[207];
+		break;
+	case 8:
+		++_wo[147];
+		break;
+	case 9:
+		++_wo[307];
+		break;
+	case 10:
+		++_wo[247];
+		break;
+	case 11:
+		++_wo[167];
+		break;
+	case 13:
+		++_wo[267];
+		break;
+	case 14:
+		++_wo[287];
+		break;
+	defualt:
+		break;
+	}
+
+	switch (_vm->_map->getCell(3)) {
+	case 1:
+		++_wo[73];
+		break;
+	case 0:
+	case 2:
+	case 3:
+	case 4:
+	case 5:
+	case 6:
+	case 7:
+	case 8:
+	case 9:
+	case 10:
+	case 11:
+	case 12:
+	case 13:
+	case 14:
+		++_wo[29];
+		break;
+	default:
+		break;
+	}
+
+	switch (_vm->_map->getCell(4)) {
+	case 0:
+		++_wo[126];
+		break;
+	case 1:
+		++_wo[70];
+		break;
+	case 2:
+		++_wo[186];
+		break;
+	case 3:
+	case 12:
+		++_wo[106];
+		break;
+	case 4:
+	case 7:
+		++_wo[26];
+		break;
+	case 5:
+		++_wo[226];
+		break;
+	case 6:
+		++_wo[206];
+	case 8:
+		++_wo[146];
+		break;
+	case 9:
+		++_wo[306];
+		break;
+	case 10:
+		++_wo[246];
+		break;
+		break;
+	case 11:
+		++_wo[166];
+		break;
+	case 13:
+		++_wo[266];
+		break;
+	case 14:
+		++_wo[286];
+		break;
+	default:
+		break;
+	}
+
+	switch (_vm->_map->getCell(5)) {
+	case 0:
+		++_wo[122];
+		break;
+	case 1:
+		++_wo[64];
+		break;
+	case 2:
+		++_wo[182];
+		break;
+	case 3:
+	case 12:
+		++_wo[102];
+		break;
+	case 5:
+		++_wo[222];
+		break;
+	case 6:
+		++_wo[202];
+		break;
+	case 8:
+		++_wo[142];
+		break;
+	case 9:
+		++_wo[302];
+		break;
+	case 10:
+		++_wo[242];
+		break;
+	case 11:
+		++_wo[162];
+		break;
+	case 13:
+		++_wo[262];
+		break;
+	case 14:
+		++_wo[282];
+		break;
+	default:
+		break;
+	}
+
+	switch (_vm->_map->getCell(6)) {
+	case 1:
+		++_wo[67];
+		break;
+	case 0:
+	case 2:
+	case 3:
+	case 4:
+	case 5:
+	case 6:
+	case 7:
+	case 8:
+	case 9:
+	case 10:
+	case 11:
+	case 12:
+	case 13:
+	case 14:
+		++_wo[23];
+		break;
+	default:
+		break;
+	}
+
+	switch (_vm->_map->getCell(7)) {
+	case 0:
+		++_wo[124];
+		break;
+	case 1:
+		++_wo[66];
+		break;
+	case 2:
+		++_wo[184];
+		break;
+	case 3:
+	case 12:
+		++_wo[104];
+		break;
+	case 4:
+	case 7:
+		++_wo[22];
+		break;
+	case 5:
+		++_wo[224];
+		break;
+	case 6:
+		++_wo[204];
+		break;
+	case 8:
+		++_wo[144];
+		break;
+	case 9:
+		++_wo[304];
+		break;
+	case 10:
+		++_wo[244];
+		break;
+	case 11:
+		++_wo[164];
+		break;
+	case 13:
+		++_wo[264];
+		break;
+	case 14:
+		++_wo[284];
+		break;
+	default:
+		break;
+	}
+
+	_thinWall = (_vm->_map->_currentWall != 0x8888 && _wo[27]);
+
+	switch (_vm->_map->getCell(8)) {
+	case 1:
+		++_wo[68];
+		break;
+	case 0:
+	case 2:
+	case 3:
+	case 4:
+	case 5:
+	case 6:
+	case 7:
+	case 8:
+	case 9:
+	case 10:
+	case 11:
+	case 12:
+	case 13:
+	case 14:
+		++_wo[24];
+		break;
+	default:
+		break;
+	}
+
+	switch (_vm->_map->getCell(9)) {
+	case 0:
+		++_wo[123];
+		break;
+	case 1:
+		++_wo[65];
+		break;
+	case 2:
+		++_wo[183];
+		break;
+	case 3:
+	case 12:
+		++_wo[103];
+		break;
+	case 4:
+	case 7:
+		++_wo[21];
+		break;
+	case 5:
+		++_wo[223];
+		break;
+	case 6:
+		++_wo[203];
+		break;
+	case 8:
+		++_wo[143];
+		break;
+	case 9:
+		++_wo[3033];
+		break;
+	case 10:
+		++_wo[243];
+		break;
+	case 11:
+		++_wo[163];
+		break;
+	case 13:
+		++_wo[263];
+		break;
+	case 14:
+		++_wo[283];
+		break;
+	default:
+		break;
+	}
+
+	switch (_vm->_map->getCell(10)) {
+	case 0:
+		+_wo[117];
+		break;
+	case 1:
+		++_wo[55];
+		break;
+	case 2:
+		++_wo[177];
+		break;
+	case 3:
+	case 12:
+		++_wo[97];
+		break;
+	case 4:
+	case 7:
+		++_wo[11];
+		break;
+	case 5:
+		++_wo[217];
+		break;
+	case 6:
+		++_wo[197];
+		break;
+	case 8:
+		++_wo[137];
+		break;
+	case 9:
+		++_wo[297];
+		break;
+	case 10:
+		++_wo[237];
+	case 11:
+		++_wo[157];
+		break;
+	case 13:
+		++_wo[257];
+		break;
+	case 14:
+		++_wo[277];
+		break;
+	default:
+		break;
+	}
+
+	switch (_vm->_map->getCell(11)) {
+	case 1:
+		++_wo[60];
+		break;
+	case 0:
+	case 2:
+	case 3:
+	case 4:
+	case 5:
+	case 6:
+	case 7:
+	case 8:
+	case 9:
+	case 10:
+	case 11:
+	case 12:
+	case 13:
+	case 14:
+		++_wo[16];
+		break;
+	default:
+		break;
+	}
+
+	switch (_vm->_map->getCell(12)) {
+	case 0:
+		++_wo[118];
+		break;
+	case 1:
+		++_wo[56];
+		break;
+	case 2:
+		++_wo[178];
+		break;
+	case 3:
+	case 12:
+		++_wo[98];
+		break;
+	case 4:
+	case 7:
+		++_wo[12];
+		break;
+	case 5:
+		++_wo[218];
+		break;
+	case 6:
+		++_wo[198];
+		break;
+	case 8:
+		++_wo[138];
+		break;
+	case 9:
+		++_wo[298];
+		break;
+	case 10:
+		++_wo[238];
+		break;
+	case 11:
+		++_wo[158];
+		break;
+	case 13:
+		++_wo[258];
+		break;
+	case 14:
+		++_wo[278];
+		break;
+	default:
+		break;
+	}
+
+	switch (_vm->_map->getCell(13)) {
+	case 1:
+		++_wo[61];
+		break;
+	case 0:
+	case 2:
+	case 3:
+	case 4:
+	case 5:
+	case 6:
+	case 7:
+	case 8:
+	case 9:
+	case 10:
+	case 11:
+	case 12:
+	case 13:
+	case 14:
+		++_wo[17];
+		break;
+	default:
+		break;
+	}
+
+	switch (_vm->_map->getCell(14)) {
+	case 0:
+		++_wo[121];
+		break;
+	case 1:
+		++_wo[59];
+		break;
+	case 2:
+		++_wo[181];
+		break;
+	case 3:
+	case 12:
+		++_wo[101];
+		break;
+	case 4:
+	case 7:
+		++_wo[15];
+		break;
+	case 5:
+		++_wo[221];
+		break;
+	case 6:
+		++_wo[201];
+		break;
+	case 8:
+		++_wo[141];
+		break;
+	case 9:
+		++_wo[301];
+		break;
+	case 10:
+		++_wo[241];
+		break;
+	case 11:
+		++_wo[161];
+		break;
+	case 13:
+		++_wo[261];
+		break;
+	case 14:
+		++_wo[281];
+		break;
+	default:
+		break;
+	}
+
+	switch (_vm->_map->getCell(15)) {
+	case 1:
+		++_wo[63];
+		break;
+	case 0:
+	case 2:
+	case 3:
+	case 4:
+	case 5:
+	case 6:
+	case 7:
+	case 8:
+	case 9:
+	case 10:
+	case 11:
+	case 12:
+	case 13:
+	case 14:
+		++_wo[19];
+		break;
+	default:
+		break;
+	}
+
+	switch (_vm->_map->getCell(16)) {
+	case 0:
+		++_wo[120];
+		break;
+	case 1:
+		++_wo[58];
+		break;
+	case 2:
+		++_wo[180];
+		break;
+	case 3:
+	case 12:
+		++_wo[100];
+		break;
+	case 4:
+	case 7:
+		++_wo[14];
+		break;
+	case 5:
+		++_wo[220];
+		break;
+	case 6:
+		++_wo[200];
+		break;
+	case 8:
+		++_wo[140];
+		break;
+	case 9:
+		++_wo[300];
+		break;
+	case 10:
+		++_wo[240];
+		break;
+	case 11:
+		++_wo[160];
+		break;
+	case 13:
+		++_wo[260];
+		break;
+	case 14:
+		++_wo[280];
+		break;
+	default:
+		break;
+	}
+
+	switch (_vm->_map->getCell(17)) {
+	case 1:
+		++_wo[62];
+		break;
+	case 0:
+	case 2:
+	case 3:
+	case 4:
+	case 5:
+	case 6:
+	case 7:
+	case 8:
+	case 9:
+	case 10:
+	case 11:
+	case 12:
+	case 13:
+	case 14:
+		++_wo[18];
+		break;
+	default:
+		break;
+	}
+
+	switch (_vm->_map->getCell(18)) {
+	case 0:
+		++_wo[119];
+		break;
+	case 1:
+		++_wo[57];
+		break;
+	case 2:
+		++_wo[179];
+		break;
+	case 3:
+	case 12:
+		++_wo[99];
+		break;
+	case 4:
+	case 7:
+		++_wo[13];
+		break;
+	case 5:
+		++_wo[219];
+		break;
+	case 6:
+		++_wo[199];
+		break;
+	case 8:
+		++_wo[139];
+		break;
+	case 9:
+		++_wo[299];
+		break;
+	case 10:
+		++_wo[239];
+		break;
+	case 11:
+		++_wo[159];
+		break;
+	case 13:
+		++_wo[259];
+		break;
+	case 14:
+		++_wo[279];
+		break;
+	default:
+		break;
+	}
+
+	switch (_vm->_map->getCell(19)) {
+	case 0:
+		++_wo[108];
+		break;
+	case 1:
+		++_wo[78];
+		break;
+	case 2:
+		++_wo[168];
+	case 3:
+	case 12:
+		++_wo[88];
+		break;
+	case 4:
+	case 7:
+		++_wo[34];
+		break;
+	case 5:
+		++_wo[208];
+		break;
+	case 6:
+		++_wo[188];
+		break;
+	case 8:
+		++_wo[128];
+		break;
+	case 9:
+		++_wo[288];
+		break;
+	case 10:
+		++_wo[228];
+		break;
+	case 11:
+		++_wo[148];
+		break;
+	case 13:
+		++_wo[248];
+		break;
+	case 14:
+		++_wo[268];
+		break;
+	default:
+		break;
+	}
+
+	switch (_vm->_map->getCell(20)) {
+	case 1:
+		++_wo[76];
+		break;
+	case 0:
+	case 2:
+	case 3:
+	case 4:
+	case 5:
+	case 6:
+	case 7:
+	case 8:
+	case 9:
+	case 10:
+	case 11:
+	case 12:
+	case 13:
+	case 14:
+		++_wo[32];
+		break;
+	default:
+		break;
+	}
+
+	switch (_vm->_map->getCell(21)) {
+	case 0:
+		++_wo[109];
+		break;
+	case 1:
+		++_wo[44];
+		break;
+	case 2:
+		++_wo[169];
+		break;
+	case 3:
+	case 12:
+		++_wo[89];
+		break;
+	case 4:
+	case 7:
+		++_wo[0];
+		break;
+	case 5:
+		++_wo[209];
+		break;
+	case 6:
+		++_wo[189];
+		break;
+	case 8:
+		++_wo[129];
+		break;
+	case 9:
+		++_wo[289];
+		break;
+	case 10:
+		++_wo[229];
+		break;
+	case 11:
+		++_wo[149];
+		break;
+	case 13:
+		++_wo[249];
+		break;
+	case 14:
+		++_wo[269];
+		break;
+	default:
+		break;
+	}
+
+	switch (_vm->_map->getCell(22)) {
+	case 1:
+		++_wo[74];
+		break;
+	case 0:
+	case 2:
+	case 3:
+	case 4:
+	case 5:
+	case 6:
+	case 7:
+	case 8:
+	case 9:
+	case 10:
+	case 11:
+	case 12:
+	case 13:
+	case 14:
+		++_wo[30];
+		break;
+	default:
+		break;
+	}
+
+	switch (_vm->_map->getCell(23)) {
+	case 0:
+		++_wo[110];
+		break;
+	case 1:
+		++_wo[45];
+		break;
+	case 2:
+		++_wo[170];
+		break;
+	case 3:
+	case 12:
+		++_wo[90];
+		break;
+	case 4:
+	case 7:
+		++_wo[1];
+		break;
+	case 5:
+		++_wo[210];
+		break;
+	case 6:
+		++_wo[190];
+		break;
+	case 8:
+		++_wo[130];
+		break;
+	case 9:
+		++_wo[290];
+		break;
+	case 10:
+		++_wo[230];
+		break;
+	case 11:
+		++_wo[150];
+		break;
+	case 13:
+		++_wo[250];
+		break;
+	case 14:
+		++_wo[270];
+		break;
+	default:
+		break;
+	}
+
+	switch (_vm->_map->getCell(24)) {
+	case 1:
+		++_wo[52];
+		break;
+	case 0:
+	case 2:
+	case 3:
+	case 4:
+	case 5:
+	case 6:
+	case 7:
+	case 8:
+	case 9:
+	case 10:
+	case 11:
+	case 12:
+	case 13:
+	case 14:
+		++_wo[8];
+		break;
+	default:
+		break;
+	}
+
+	switch (_vm->_map->getCell(25)) {
+	case 0:
+		++_wo[111];
+		break;
+	case 1:
+		++_wo[46];
+		break;
+	case 2:
+		++_wo[171];
+		break;
+	case 3:
+	case 12:
+		++_wo[91];
+		break;
+	case 4:
+	case 7:
+		++_wo[2];
+		break;
+	case 5:
+		++_wo[211];
+		break;
+	case 6:
+		++_wo[191];
+		break;
+	case 8:
+		++_wo[131];
+		break;
+	case 9:
+		++_wo[291];
+		break;
+	case 10:
+		++_wo[231];
+		break;
+	case 11:
+		++_wo[151];
+		break;
+	case 13:
+		++_wo[251];
+		break;
+	case 14:
+		++_wo[271];
+		break;
+	default:
+		break;
+	}
+
+	switch (_vm->_map->getCell(26)) {
+	case 1:
+		++_wo[51];
+		break;
+	case 0:
+	case 2:
+	case 3:
+	case 4:
+	case 5:
+	case 6:
+	case 7:
+	case 8:
+	case 9:
+	case 10:
+	case 11:
+	case 12:
+	case 13:
+	case 14:
+		++_wo[7];
+		break;
+	default:
+		break;
+	}
+
+	switch (_vm->_map->getCell(27)) {
+	case 0:
+		++_wo[116];
+		break;
+	case 1:
+		++_wo[50];
+		break;
+	case 2:
+		++_wo[176];
+		break;
+	case 3:
+	case 12:
+		++_wo[96];
+		break;
+	case 4:
+	case 7:
+		++_wo[6];
+		break;
+	case 5:
+		++_wo[216];
+		break;
+	case 6:
+		++_wo[196];
+		break;
+	case 8:
+		++_wo[136];
+		break;
+	case 9:
+		++_wo[296];
+		break;
+	case 10:
+		++_wo[236];
+		break;
+	case 11:
+		++_wo[156];
+		break;
+	case 13:
+		++_wo[256];
+		break;
+	case 14:
+		++_wo[276];
+		break;
+	default:
+		break;
+	}
+
+	switch (_vm->_map->getCell(28)) {
+	case 1:
+		++_wo[53];
+		break;
+	case 0:
+	case 2:
+	case 3:
+	case 4:
+	case 5:
+	case 6:
+	case 7:
+	case 8:
+	case 9:
+	case 10:
+	case 11:
+	case 12:
+	case 13:
+	case 14:
+		++_wo[9];
+		break;
+	default:
+		break;
+	}
+
+	switch (_vm->_map->getCell(29)) {
+	case 0:
+		++_wo[115];
+		break;
+	case 1:
+		++_wo[49];
+		break;
+	case 2:
+		++_wo[175];
+		break;
+	case 3:
+	case 12:
+		++_wo[95];
+		break;
+	case 4:
+	case 7:
+		++_wo[5];
+		break;
+	case 5:
+		++_wo[215];
+		break;
+	case 6:
+		++_wo[195];
+		break;
+	case 8:
+		++_wo[135];
+		break;
+	case 9:
+		++_wo[295];
+		break;
+	case 10:
+		++_wo[235];
+		break;
+	case 11:
+		++_wo[155];
+		break;
+	case 13:
+		++_wo[255];
+		break;
+	case 14:
+		++_wo[275];
+		break;
+	default:
+		break;
+	}
+
+	switch (_vm->_map->getCell(30)) {
+	case 1:
+		++_wo[54];
+		break;
+	case 0:
+	case 2:
+	case 3:
+	case 4:
+	case 5:
+	case 6:
+	case 7:
+	case 8:
+	case 9:
+	case 10:
+	case 11:
+	case 12:
+	case 13:
+	case 14:
+		++_wo[10];
+		break;
+	default:
+		break;
+	}
+
+	switch (_vm->_map->getCell(31)) {
+	case 0:
+		++_wo[114];
+		break;
+	case 1:
+		++_wo[48];
+		break;
+	case 2:
+		++_wo[174];
+		break;
+	case 3:
+	case 12:
+		++_wo[94];
+		break;
+	case 4:
+		++_wo[4];
+		break;
+	case 5:
+		++_wo[214];
+		break;
+	case 6:
+		++_wo[194];
+		break;
+	case 8:
+		++_wo[134];
+		break;
+	case 9:
+		++_wo[294];
+		break;
+	case 10:
+		++_wo[234];
+		break;
+	case 11:
+		++_wo[154];
+		break;
+	case 13:
+		++_wo[254];
+		break;
+	case 14:
+		++_wo[274];
+		break;
+	default:
+		break;
+	}
+
+	switch (_vm->_map->getCell(32)) {
+	case 1:
+		++_wo[75];
+		break;
+	case 0:
+	case 2:
+	case 3:
+	case 4:
+	case 5:
+	case 6:
+	case 7:
+	case 8:
+	case 9:
+	case 10:
+	case 11:
+	case 12:
+	case 13:
+	case 14:
+		++_wo[31];
+		break;
+	default:
+		break;
+	}
+
+	switch (_vm->_map->getCell(33)) {
+	case 0:
+		++_wo[112];
+		break;
+	case 1:
+		++_wo[47];
+		break;
+	case 2:
+		++_wo[172];
+		break;
+	case 3:
+	case 12:
+		++_wo[92];
+		break;
+	case 4:
+	case 7:
+		++_wo[3];
+		break;
+	case 5:
+		++_wo[212];
+		break;
+	case 6:
+		++_wo[192];
+		break;
+	case 8:
+		++_wo[132];
+		break;
+	case 9:
+		++_wo[292];
+		break;
+	case 10:
+		++_wo[232];
+		break;
+	case 11:
+		++_wo[152];
+		break;
+	case 13:
+		++_wo[252];
+		break;
+	case 14:
+		++_wo[272];
+		break;
+	default:
+		break;
+	}
+
+	switch (_vm->_map->getCell(34)) {
+	case 1:
+		++_wo[77];
+		break;
+	case 0:
+	case 2:
+	case 3:
+	case 4:
+	case 5:
+	case 6:
+	case 7:
+	case 8:
+	case 9:
+	case 10:
+	case 11:
+	case 12:
+	case 13:
+	case 14:
+		++_wo[33];
+		break;
+	default:
+		break;
+	}
+
+	switch (_vm->_map->getCell(35)) {
+	case 0:
+		++_wo[113];
+		break;
+	case 1:
+		++_wo[79];
+		break;
+	case 2:
+		++_wo[173];
+		break;
+	case 3:
+	case 12:
+		++_wo[93];
+		break;
+	case 4:
+	case 7:
+		++_wo[35];
+		break;
+	case 5:
+		++_wo[213];
+		break;
+	case 6:
+		++_wo[193];
+		break;
+	case 8:
+		++_wo[133];
+		break;
+	case 9:
+		++_wo[293];
+		break;
+	case 10:
+		++_wo[233];
+		break;
+	case 11:
+		++_wo[153];
+		break;
+	case 13:
+		++_wo[253];
+		break;
+	case 14:
+		++_wo[273];
+		break;
+	default:
+		break;
+	}
+
+	switch (_vm->_map->getCell(36)) {
+	case 1:
+		++_wo[83];
+		break;
+	case 0:
+	case 2:
+	case 3:
+	case 4:
+	case 5:
+	case 6:
+	case 7:
+	case 8:
+	case 9:
+	case 10:
+	case 11:
+	case 12:
+	case 13:
+	case 14:
+		++_wo[39];
+		break;
+	default:
+		break;
+	}
+
+	switch (_vm->_map->getCell(37)) {
+	case 1:
+		++_wo[82];
+		break;
+	case 0:
+	case 2:
+	case 3:
+	case 4:
+	case 5:
+	case 6:
+	case 7:
+	case 8:
+	case 9:
+	case 10:
+	case 11:
+	case 12:
+	case 13:
+	case 14:
+		++_wo[38];
+		break;
+	default:
+		break;
+	}
 
+	switch (_vm->_map->getCell(38)) {
+	case 1:
+		++_wo[81];
+		break;
+	case 0:
+	case 2:
+	case 3:
+	case 4:
+	case 5:
+	case 6:
+	case 7:
+	case 8:
+	case 9:
+	case 10:
+	case 11:
+	case 12:
+	case 13:
+	case 14:
+		++_wo[37];
+		break;
+	default:
+		break;
+	}
+
+	switch (_vm->_map->getCell(34)) {
+	case 1:
+		++_wo[80];
+		break;
+	case 0:
+	case 2:
+	case 3:
+	case 4:
+	case 5:
+	case 6:
+	case 7:
+	case 8:
+	case 9:
+	case 10:
+	case 11:
+	case 12:
+	case 13:
+	case 14:
+		++_wo[36];
+		break;
+	default:
+		break;
+	}
+
+	switch (_vm->_map->getCell(40)) {
+	case 1:
+		++_wo[84];
+		break;
+	case 0:
+	case 2:
+	case 3:
+	case 4:
+	case 5:
+	case 6:
+	case 7:
+	case 8:
+	case 9:
+	case 10:
+	case 11:
+	case 12:
+	case 13:
+	case 14:
+		++_wo[40];
+		break;
+	default:
+		break;
+	}
+
+	switch (_vm->_map->getCell(41)) {
+	case 1:
+		++_wo[85];
+		break;
+	case 0:
+	case 2:
+	case 3:
+	case 4:
+	case 5:
+	case 6:
+	case 7:
+	case 8:
+	case 9:
+	case 10:
+	case 11:
+	case 12:
+	case 13:
+	case 14:
+		++_wo[41];
+		break;
+	default:
+		break;
+	}
+
+	switch (_vm->_map->getCell(42)) {
+	case 1:
+		++_wo[86];
+		break;
+	case 0:
+	case 2:
+	case 3:
+	case 4:
+	case 5:
+	case 6:
+	case 7:
+	case 8:
+	case 9:
+	case 10:
+	case 11:
+	case 12:
+	case 13:
+	case 14:
+		++_wo[42];
+		break;
+	default:
+		break;
+	}
+
+	switch (_vm->_map->getCell(43)) {
+	case 1:
+		++_wo[87];
+		break;
+	case 0:
+	case 2:
+	case 3:
+	case 4:
+	case 5:
+	case 6:
+	case 7:
+	case 8:
+	case 9:
+	case 10:
+	case 11:
+	case 12:
+	case 13:
+	case 14:
+		++_wo[43];
+		break;
+	default:
+		break;
+	}
 }
 
 } // End of namespace Xeen
diff --git a/engines/xeen/interface.h b/engines/xeen/interface.h
index d50cdd0..bd2f2af 100644
--- a/engines/xeen/interface.h
+++ b/engines/xeen/interface.h
@@ -113,6 +113,7 @@ private:
 	int _objNumber;
 	byte _wp[20];
 	byte _wo[308];
+	bool _thinWall;
 
 	void loadSprites();
 
diff --git a/engines/xeen/map.h b/engines/xeen/map.h
index 17c3fc6..6a06178 100644
--- a/engines/xeen/map.h
+++ b/engines/xeen/map.h
@@ -351,8 +351,6 @@ private:
 	int _mazeDataIndex;
 	bool _currentSteppedOn;
 	int _currentSurfaceId;
-	int _currentWall;
-	int _currentTile;
 
 	void loadEvents(int mapId);
 
@@ -369,6 +367,8 @@ public:
 	bool _currentIsEvent;
 	bool _currentIsObject;
 	int _currentMonsterFlags;
+	int _currentWall;
+	int _currentTile;
 public:
 	Map(XeenEngine *vm);
 
diff --git a/engines/xeen/xeen.cpp b/engines/xeen/xeen.cpp
index 9cc51e1..583a1dd 100644
--- a/engines/xeen/xeen.cpp
+++ b/engines/xeen/xeen.cpp
@@ -46,7 +46,6 @@ XeenEngine::XeenEngine(OSystem *syst, const XeenGameDescription *gameDesc)
 	_sound = nullptr;
 	_eventData = nullptr;
 	_loadDarkSide = 1;
-	_thinWall = false;
 	_dangerSenseAllowed = false;
 	_face1State = 0;
 	_face2State = 0;
diff --git a/engines/xeen/xeen.h b/engines/xeen/xeen.h
index efeacf0..a9b102a 100644
--- a/engines/xeen/xeen.h
+++ b/engines/xeen/xeen.h
@@ -138,7 +138,6 @@ public:
 	Roster _roster;
 	Party _party;
 	int _loadDarkSide;
-	bool _thinWall;
 	bool _dangerSenseAllowed;
 	int _face1State;
 	int _face2State;


Commit: 07f37cedf54d956d9f736012f5b334e26cdbac5d
    https://github.com/scummvm/scummvm/commit/07f37cedf54d956d9f736012f5b334e26cdbac5d
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-01-12T20:56:15-05:00

Commit Message:
XEEN: Change _currentWall to be MazeWallLayers union

Changed paths:
    engines/xeen/interface.cpp
    engines/xeen/map.cpp
    engines/xeen/map.h



diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp
index 46b7bc4..2dec248 100644
--- a/engines/xeen/interface.cpp
+++ b/engines/xeen/interface.cpp
@@ -1311,7 +1311,7 @@ void Interface::setMazeBits() {
 	case 14:
 		++_wo[287];
 		break;
-	defualt:
+	default:
 		break;
 	}
 
@@ -1497,7 +1497,7 @@ void Interface::setMazeBits() {
 		break;
 	}
 
-	_thinWall = (_vm->_map->_currentWall != 0x8888 && _wo[27]);
+	_thinWall = (_vm->_map->_currentWall._data != 0x8888) && _wo[27];
 
 	switch (_vm->_map->getCell(8)) {
 	case 1:
@@ -1571,7 +1571,7 @@ void Interface::setMazeBits() {
 
 	switch (_vm->_map->getCell(10)) {
 	case 0:
-		+_wo[117];
+		++_wo[117];
 		break;
 	case 1:
 		++_wo[55];
diff --git a/engines/xeen/map.cpp b/engines/xeen/map.cpp
index b6bf91d..f9a687b 100644
--- a/engines/xeen/map.cpp
+++ b/engines/xeen/map.cpp
@@ -854,7 +854,7 @@ Map::Map(XeenEngine *vm) : _vm(vm), _mobData(vm) {
 	_mazeDataIndex = 0;
 	_currentSteppedOn = false;
 	_currentSurfaceId = 0;
-	_currentWall = 0;
+	_currentWall._data = 0;
 	_currentTile = 0;
 	_currentIsGrate = false;
 	_currentCantRest = false;
@@ -1239,8 +1239,8 @@ int Map::getCell(int idx) {
 		} else {
 			_currentSurfaceId = (mapId >= 25 && mapId <= 27) ? 7 : 0;
 		}
-		_currentWall = 0x8888;
-		return _currentWall;
+		_currentWall._data = 0x8888;
+		return 0x8888;
 	} 
 
 	_mazeDataIndex = 0;
@@ -1259,7 +1259,7 @@ int Map::getCell(int idx) {
 		if (!mapId) {
 			if (_isOutdoors) {
 				_currentSurfaceId = SURFTYPE_SPACE;
-				_currentWall = 0;
+				_currentWall._data = 0;
 				return 0;
 			} else {
 				if (_vm->_files->_isDarkCc) {
@@ -1273,8 +1273,8 @@ int Map::getCell(int idx) {
 					_currentSurfaceId = (mapId >= 25 && mapId <= 27) ? SURFTYPE_ROAD : SURFTYPE_DEFAULT;
 				}
 
-				_currentWall = 0x8888;
-				return _currentWall;
+				_currentWall._data = 0x8888;
+				return 0x8888;
 			}
 		
 			_mazeDataIndex = 0;
@@ -1295,8 +1295,8 @@ int Map::getCell(int idx) {
 		if (!mapId) {
 			if (_isOutdoors) {
 				_currentSurfaceId = SURFTYPE_SPACE;
-				_currentWall = 0;
-				return _currentWall;
+				_currentWall._data = 0;
+				return 0;
 			} else {
 				if (_vm->_files->_isDarkCc) {
 					if ((mapId >= 53 && mapId <= 88 && mapId != 73) || (mapId >= 74 && mapId <= 120) ||
@@ -1309,8 +1309,8 @@ int Map::getCell(int idx) {
 					_currentSurfaceId = (mapId >= 25 && mapId <= 27) ? SURFTYPE_ROAD : SURFTYPE_DEFAULT;
 				}
 
-				_currentWall = 0x8888;
-				return _currentWall;
+				_currentWall._data = 0x8888;
+				return 0x8888;
 			}
 
 			_mazeDataIndex = 0;
@@ -1324,15 +1324,15 @@ int Map::getCell(int idx) {
 		if (mapId) {
 			// TODO: tile is set to word of (wallLayers >> 8) && 0xff? Makes no sense
 			_currentTile = wallLayers._outdoors._surfaceId;
-			_currentWall = wallLayers._outdoors._iMiddle;
+			_currentWall = wallLayers;
 			_currentSurfaceId = wallLayers._outdoors._surfaceId;
 		} else {
 			_currentSurfaceId = SURFTYPE_DEFAULT;
-			_currentWall = 0;
+			_currentWall._data = 0;
 			_currentTile = 0;
 		}
 	} else {
-		if (!mapId)
+		if (!mapId) 
 			return 0;
 
 		if (pt.x > 31 || pt.y > 31)
@@ -1340,11 +1340,11 @@ int Map::getCell(int idx) {
 		else
 			_currentSurfaceId = _mazeData[_mazeDataIndex]._cells[pt.y][pt.x]._surfaceId;
 
-		_currentWall = wallLayers._data;
-		return (_currentWall >> (WALL_NUMBERS[dir][idx * 2] * 4)) & 0xF;
+		_currentWall = wallLayers;
+		return (_currentWall._data >> (WALL_NUMBERS[dir][idx * 2] * 4)) & 0xF;
 	}
 
-	return _currentWall;
+	return _currentWall._data;
 }
 
 } // End of namespace Xeen
diff --git a/engines/xeen/map.h b/engines/xeen/map.h
index 6a06178..090619f 100644
--- a/engines/xeen/map.h
+++ b/engines/xeen/map.h
@@ -367,7 +367,7 @@ public:
 	bool _currentIsEvent;
 	bool _currentIsObject;
 	int _currentMonsterFlags;
-	int _currentWall;
+	MazeWallLayers _currentWall;
 	int _currentTile;
 public:
 	Map(XeenEngine *vm);


Commit: 747ca9eb2ff87b1205d41fcd0cf65a016ade8e0d
    https://github.com/scummvm/scummvm/commit/747ca9eb2ff87b1205d41fcd0cf65a016ade8e0d
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-01-13T00:16:26-05:00

Commit Message:
XEEN: Implemented indoor drawing code in draw3d

Changed paths:
    engines/xeen/interface.cpp
    engines/xeen/interface.h
    engines/xeen/module.mk
    engines/xeen/xeen.cpp
    engines/xeen/xeen.h



diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp
index 2dec248..7bbe08e 100644
--- a/engines/xeen/interface.cpp
+++ b/engines/xeen/interface.cpp
@@ -371,6 +371,7 @@ Interface::Interface(XeenEngine *vm) : ButtonContainer(), _vm(vm) {
 	Common::fill(&_combatCharIds[0], &_combatCharIds[8], 0);
 	Common::fill(&_wp[0], &_wp[20], 0);
 	Common::fill(&_wo[0], &_wo[308], 0);
+	Common::fill(&_charsArray1[0], &_charsArray1[12], 0);
 
 	initDrawStructs();
 }
@@ -408,6 +409,7 @@ void Interface::setup() {
 	_restoreSprites.load("restorex.icn");
 	_hpSprites.load("hpbars.icn");
 	_uiSprites.load("inn.icn");
+	_charPowSprites.load("charpow.icn");
 
 	// Get mappings to the active characters in the party
 	_vm->_party._activeParty.resize(_vm->_party._partyCount);
@@ -855,9 +857,11 @@ void Interface::moveCharacterToRoster() {
 	error("TODO");
 }
 
-void Interface::draw3d(bool flag) {
+void Interface::draw3d(bool updateFlag) {
+	Combat &combat = *_vm->_combat;
+	EventsManager &events = *_vm->_events;
+	Map &map = *_vm->_map;
 	Screen &screen = *_vm->_screen;
-//	EventsManager &events = *_vm->_events;
 
 	if (!screen._windows[11]._enabled)
 		return;
@@ -871,15 +875,15 @@ void Interface::draw3d(bool flag) {
 			moveMonsters();
 	}
 
-	MazeObject &objObject = _vm->_map->_mobData._objects[_objNumber];
+	MazeObject &objObject = map._mobData._objects[_objNumber];
 	Direction partyDirection = _vm->_party._mazeDirection;
 	int objNum = _objNumber - 1;
 
 	// Loop to update the frame numbers for each maze object, applying the animation frame
 	// limits as specified by the map's _animationInfo listing
-	for (uint i = 0; i < _vm->_map->_mobData._objects.size(); ++i) {
-		MazeObject &mazeObject = _vm->_map->_mobData._objects[i];
-		AnimationEntry &animEntry = _vm->_map->_animationInfo[mazeObject._spriteId];
+	for (uint i = 0; i < map._mobData._objects.size(); ++i) {
+		MazeObject &mazeObject = map._mobData._objects[i];
+		AnimationEntry &animEntry = map._animationInfo[mazeObject._spriteId];
 		int directionIndex = DIRECTION_ANIM_POSITIONS[mazeObject._direction][partyDirection];
 
 		if (_isAnimReset) {
@@ -899,7 +903,7 @@ void Interface::draw3d(bool flag) {
 		mazeObject._flipped = animEntry._flipped._flags[directionIndex];
 	}
 
-	if (_vm->_map->_isOutdoors) {
+	if (map._isOutdoors) {
 		error("TODO: draw3d outdoors handling");
 	} else {
 		// Default all the parts of draw struct not to be drawn by default
@@ -931,11 +935,134 @@ void Interface::draw3d(bool flag) {
 				}
 			}
 		}
+
+		setMazeBits();
+		_isAnimReset = false;
+		const int INDOOR_INDEXES[3] = { 157, 151, 154 };
+		const int INDOOR_COMBAT_POS[3][2] = { { 102, 134 }, { 36, 67 }, { 161, 161 } };
+		const int INDOOR_COMBAT_POS2[4] = { 8, 6, 4, 2 };
+
+		MazeObject &objObject = map._mobData._objects[_objNumber - 1];
+
+		for (int idx = 0; idx < 3; ++idx) {
+			DrawStruct &ds1 = _indoorList[INDOOR_INDEXES[idx]];
+			DrawStruct &ds2 = _indoorList[INDOOR_INDEXES[idx] + 1];
+			ds1._sprites = nullptr;
+			ds2._sprites = nullptr;
+
+			if (_charsArray1[idx]) {
+				int posIndex= combat._attackMon2 && !combat._attackMon3 ? 1 : 0;
+				--combat._charsArray1[idx];
+
+				if (combat._monPow[idx]) {
+					ds1._x = INDOOR_COMBAT_POS[idx][0];
+					ds1._frame = 0;
+					ds1._scale = combat._monsterScale[idx];
+					if (ds1._scale == 0x8000) {
+						ds1._x /= 3;
+						ds1._y = 60;
+					} else {
+						ds1._y = 73;
+					}
+
+					ds1._flags = SPRFLAG_4000 | SPRFLAG_2000;
+					ds1._sprites = &_charPowSprites;
+				}
+
+				if (combat._elemPow[idx]) {
+					ds2._x = INDOOR_COMBAT_POS[idx][posIndex] + INDOOR_COMBAT_POS2[idx];
+					ds2._frame = combat._elemPow[idx];
+					ds2._scale = combat._elemScale[idx];
+					if (ds2._scale == 0x8000)
+						ds2._x /= 3;
+					ds2._flags = SPRFLAG_4000 | SPRFLAG_2000;
+					ds2._sprites = &_charPowSprites;
+				}
+			}
+		}
+
+		setIndoorsMonsters();
+		setIndoorObjects();
+		setIndoorWallPics();
+
+		_indoorList[161]._sprites = nullptr;
+		_indoorList[160]._sprites = nullptr;
+		_indoorList[159]._sprites = nullptr;
+
+		// Handle attacking monsters
+		int monsterIndex = 0;
+		if (combat._attackMon1 != -1 && map._mobData._monsters[combat._attackMon1]._frame >= 0) {
+			_indoorList[159] = _indoorList[156];
+			_indoorList[160] = _indoorList[157];
+			_indoorList[161] = _indoorList[158];
+			_indoorList[158]._sprites = nullptr;
+			_indoorList[156]._sprites = nullptr;
+			_indoorList[157]._sprites = nullptr;
+			monsterIndex = 1;
+		} else if (combat._attackMon2 != -1 && map._mobData._monsters[combat._attackMon2]._frame >= 0) {
+			_indoorList[159] = _indoorList[150];
+			_indoorList[160] = _indoorList[151];
+			_indoorList[161] = _indoorList[152];
+			_indoorList[152]._sprites = nullptr;
+			_indoorList[151]._sprites = nullptr;
+			_indoorList[150]._sprites = nullptr;
+			monsterIndex = 2;
+		} else if (combat._attackMon3 != -1 &&  map._mobData._monsters[combat._attackMon3]._frame >= 0) {
+			_indoorList[159] = _indoorList[153];
+			_indoorList[160] = _indoorList[154];
+			_indoorList[161] = _indoorList[155];
+			_indoorList[153]._sprites = nullptr;
+			_indoorList[154]._sprites = nullptr;
+			_indoorList[155]._sprites = nullptr;
+			monsterIndex = 3;
+		}
+
+		drawIndoors();
+
+		switch (monsterIndex) {
+		case 1:
+			_indoorList[156] = _indoorList[159];
+			_indoorList[157] = _indoorList[160];
+			_indoorList[158] = _indoorList[161];
+			break;
+		case 2:
+			_indoorList[150] = _indoorList[159];
+			_indoorList[151] = _indoorList[160];
+			_indoorList[152] = _indoorList[161];
+			break;
+		case 3:
+			_indoorList[153] = _indoorList[159];
+			_indoorList[154] = _indoorList[160];
+			_indoorList[155] = _indoorList[161];
+			break;
+		default:
+			break;
+		}
+	}
+
+	animate3d();
+	updateAutoMap();
+
+	if (_vm->_falling == 1) {
+		error("TODO: Indoor falling");
 	}
 
-	// TODO: more
+	if (_vm->_falling == 2) {
+		screen.saveBackground(1);
+	}
+
+	assembleBorder();
 
-	warning("TODO");
+	// TODO: write strings
+
+	if (updateFlag) {
+		screen._windows[1].update();
+		screen._windows[3].update();
+	}
+
+	// TODO: more stuff
+
+	events.wait(2);
 }
 
 void Interface::animate3d() {
@@ -1124,6 +1251,11 @@ void Interface::setIndoorObjects() {
 	}
 }
 
+void Interface::setIndoorWallPics() {
+	// TODO
+}
+
+
 void Interface::setOutdoorsMonsters() {
 
 }
@@ -2691,4 +2823,12 @@ void Interface::setMazeBits() {
 	}
 }
 
+void Interface::drawIndoors() {
+	// TODO
+}
+
+void Interface::updateAutoMap() {
+	// TODO
+}
+
 } // End of namespace Xeen
diff --git a/engines/xeen/interface.h b/engines/xeen/interface.h
index bd2f2af..ec8a384 100644
--- a/engines/xeen/interface.h
+++ b/engines/xeen/interface.h
@@ -81,6 +81,7 @@ private:
 	SpriteResource _hpSprites;
 	SpriteResource _uiSprites;
 	SpriteResource _iconSprites;
+	SpriteResource _charPowSprites;
 	SpriteResource _charFaces[TOTAL_CHARACTERS];
 	SpriteResource *_partyFaces[MAX_ACTIVE_PARTY];
 	DrawStruct _faceDrawStructs[4];
@@ -114,6 +115,7 @@ private:
 	byte _wp[20];
 	byte _wo[308];
 	bool _thinWall;
+	int _charsArray1[12];
 
 	void loadSprites();
 
@@ -137,6 +139,10 @@ private:
 
 	void setIndoorObjects();
 
+	void setIndoorWallPics();
+
+	void drawIndoors();
+
 	void setOutdoorsMonsters();
 
 	void setOutdoorsObjects();
@@ -146,6 +152,8 @@ private:
 	void setMainButtons();
 
 	void setMazeBits();
+
+	void updateAutoMap();
 public:
 	Interface(XeenEngine *vm);
 
@@ -157,7 +165,7 @@ public:
 
 	void loadPartyIcons();
 
-	void draw3d(bool flag);
+	void draw3d(bool updateFlag);
 
 	void startup();
 
diff --git a/engines/xeen/module.mk b/engines/xeen/module.mk
index 076a31a..2c22322 100644
--- a/engines/xeen/module.mk
+++ b/engines/xeen/module.mk
@@ -4,6 +4,7 @@ MODULE_OBJS := \
 	clouds\clouds_game.o \
 	darkside\darkside_game.o \
 	worldofxeen\worldofxeen_game.o \
+	combat.o \
 	debugger.o \
 	detection.o \
 	dialogs.o \
diff --git a/engines/xeen/xeen.cpp b/engines/xeen/xeen.cpp
index 583a1dd..c749129 100644
--- a/engines/xeen/xeen.cpp
+++ b/engines/xeen/xeen.cpp
@@ -36,6 +36,7 @@ namespace Xeen {
 
 XeenEngine::XeenEngine(OSystem *syst, const XeenGameDescription *gameDesc)
 		: Engine(syst), _gameDescription(gameDesc), _randomSource("Xeen") {
+	_combat = nullptr;
 	_debugger = nullptr;
 	_events = nullptr;
 	_files = nullptr;
@@ -50,12 +51,13 @@ XeenEngine::XeenEngine(OSystem *syst, const XeenGameDescription *gameDesc)
 	_face1State = 0;
 	_face2State = 0;
 	_noDirectionSense = false;
-	_falling = false;
+	_falling = 0;
 	_moveMonsters = false;
 	_mode = MODE_0;
 }
 
 XeenEngine::~XeenEngine() {
+	delete _combat;
 	delete _debugger;
 	delete _events;
 	delete _interface;
@@ -76,6 +78,7 @@ void XeenEngine::initialize() {
 
 	// Create sub-objects of the engine
 	_files = new FileManager(this);
+	_combat = new Combat(this);
 	_debugger = new Debugger(this);
 	_events = new EventsManager(this);
 	_interface = new Interface(this);
diff --git a/engines/xeen/xeen.h b/engines/xeen/xeen.h
index a9b102a..5927977 100644
--- a/engines/xeen/xeen.h
+++ b/engines/xeen/xeen.h
@@ -31,6 +31,7 @@
 #include "common/serializer.h"
 #include "common/util.h"
 #include "engines/engine.h"
+#include "xeen/combat.h"
 #include "xeen/debugger.h"
 #include "xeen/dialogs.h"
 #include "xeen/events.h"
@@ -124,6 +125,7 @@ private:
 	virtual Common::Error run();
 	virtual bool hasFeature(EngineFeature f) const;
 public:
+	Combat *_combat;
 	Debugger *_debugger;
 	EventsManager *_events;
 	FileManager *_files;
@@ -142,7 +144,7 @@ public:
 	int _face1State;
 	int _face2State;
 	bool _noDirectionSense;
-	bool _falling;
+	int _falling;
 	bool _moveMonsters;
 public:
 	XeenEngine(OSystem *syst, const XeenGameDescription *gameDesc);


Commit: 1a0a597ff8c02d103d56968bfd18de1908e219d6
    https://github.com/scummvm/scummvm/commit/1a0a597ff8c02d103d56968bfd18de1908e219d6
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-01-13T08:51:04-05:00

Commit Message:
XEEN: Add indoor terrain loading and indoor list sprite setting to Map::load

Changed paths:
    engines/xeen/interface.cpp
    engines/xeen/interface.h
    engines/xeen/map.cpp
    engines/xeen/map.h
    engines/xeen/resources.cpp
    engines/xeen/resources.h



diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp
index 7bbe08e..4bf9b1a 100644
--- a/engines/xeen/interface.cpp
+++ b/engines/xeen/interface.cpp
@@ -164,11 +164,28 @@ OutdoorDrawList::OutdoorDrawList() : _skySprite(_data[1]), _groundSprite(_data[2
 
 /*------------------------------------------------------------------------*/
 
-IndoorDrawList::IndoorDrawList() : _skySprite(_data[1]), _groundSprite(_data[2]),
+IndoorDrawList::IndoorDrawList() : 
+	_sky(_data[1]), _ground(_data[2]), _horizon(_data[28]),
+	_swl_0F1R(_data[ 46]), _swl_0F1L(_data[44]),  _swl_1F1R(_data[134]), 
+	_swl_1F1L(_data[133]), _swl_2F2R(_data[110]), _swl_2F1R(_data[109]), 
+	_swl_2F1L(_data[108]), _swl_2F2L(_data[107]), _swl_3F1R(_data[ 78]), 
+	_swl_3F2R(_data[ 77]), _swl_3F3R(_data[ 76]), _swl_3F4R(_data[ 75]),
+	_swl_3F1L(_data[ 74]), _swl_3F2L(_data[ 73]), _swl_3F3L(_data[ 72]), 
+	_swl_3F4L(_data[ 71]), _swl_4F4R(_data[ 33]), _swl_4F3R(_data[ 34]), 
+	_swl_4F2R(_data[ 35]), _swl_4F1R(_data[ 36]), _swl_4F1L(_data[ 32]),
+	_swl_4F2L(_data[ 31]), _swl_4F3L(_data[ 30]), _swl_4F4L(_data[ 29]),
+	_fwl_4F4R(_data[ 45]), _fwl_4F3R(_data[ 44]), _fwl_4F2R(_data[ 43]), 
+	_fwl_4F1R(_data[ 42]), _fwl_4F(  _data[ 41]), _fwl_4F1L(_data[ 40]), 
+	_fwl_4F2L(_data[ 39]), _fwl_4F3L(_data[ 38]), _fwl_4F4L(_data[ 37]),
+	_fwl_2F1R(_data[121]), _fwl_2F(  _data[120]), _fwl_2F1L(_data[119]), 
+	_fwl_3F2R(_data[ 91]), _fwl_3F1R(_data[ 90]), _fwl_3F(  _data[ 89]), 
+	_fwl_3F1L(_data[ 88]), _fwl_3F2L(_data[ 87]), _fwl_1F(  _data[147]),
+	_fwl_1F1R(_data[145]), _fwl_1F1L(_data[143]),
 	_objects0(_data[149]), _objects1(_data[125]), _objects2(_data[126]),
 	_objects3(_data[127]), _objects4(_data[97]), _objects5(_data[98]),
 	_objects6(_data[99]), _objects7(_data[55]), _objects8(_data[56]),
 	_objects9(_data[58]), _objects10(_data[57]), _objects11(_data[59]) {
+	// Setup draw structure positions
 	_data[0] = DrawStruct(0, 8, 8);
 	_data[1] = DrawStruct(1, 8, 25);
 	_data[2] = DrawStruct(0, 8, 67);
@@ -2824,6 +2841,10 @@ void Interface::setMazeBits() {
 }
 
 void Interface::drawIndoors() {
+	Map &map = *_vm->_map;
+
+	map.getCell(36);
+
 	// TODO
 }
 
diff --git a/engines/xeen/interface.h b/engines/xeen/interface.h
index ec8a384..0c014f6 100644
--- a/engines/xeen/interface.h
+++ b/engines/xeen/interface.h
@@ -51,8 +51,20 @@ public:
 class IndoorDrawList {
 public:
 	DrawStruct _data[170];
-	DrawStruct &_skySprite;
-	DrawStruct &_groundSprite;
+	DrawStruct &_sky;
+	DrawStruct &_ground;
+	DrawStruct &_horizon;
+	DrawStruct &_swl_0F1R, _swl_0F1L, _swl_1F1R, _swl_1F1L,
+		_swl_2F2R, _swl_2F1R, _swl_2F1L, _swl_2F2L,
+		_swl_3F1R, _swl_3F2R, _swl_3F3R, _swl_3F4R,
+		_swl_3F1L, _swl_3F2L, _swl_3F3L, _swl_3F4L,
+		_swl_4F4R, _swl_4F3R, _swl_4F2R, _swl_4F1R,
+		_swl_4F1L, _swl_4F2L, _swl_4F3L, _swl_4F4L;
+	DrawStruct &_fwl_4F4R, _fwl_4F3R, _fwl_4F2R, _fwl_4F1R,
+		_fwl_4F, _fwl_4F1L, _fwl_4F2L, _fwl_4F3L, _fwl_4F4L;
+	DrawStruct &_fwl_2F1R, _fwl_2F, _fwl_2F1L, _fwl_3F2R,
+		_fwl_3F1R, _fwl_3F, _fwl_3F1L, _fwl_3F2L;
+	DrawStruct &_fwl_1F, _fwl_1F1R, _fwl_1F1L;
 	DrawStruct &_objects0, _objects1, _objects2, _objects3;
 	DrawStruct &_objects4, _objects5, _objects6, _objects7;
 	DrawStruct &_objects8, _objects9, _objects10, _objects11;
diff --git a/engines/xeen/map.cpp b/engines/xeen/map.cpp
index f9a687b..07cb0d6 100644
--- a/engines/xeen/map.cpp
+++ b/engines/xeen/map.cpp
@@ -1050,6 +1050,40 @@ void Map::load(int mapId) {
 		filename = Common::String::format("%03d.pic", _mobData._wallItems[i]._spriteId);
 		_mobData._wallItemSprites[i]._sprites.load(filename);
 	}
+
+	// Handle loading miscellaneous sprites for the map
+	if (_isOutdoors) {
+		warning("TODO");
+	} else {
+		warning("TODO");	// Sound loading
+
+		_skySprites.load(isDarkCc ? "sky.sky" : "night.sky");
+		_mazeSkySprites.load(Common::String::format("%s.sky",
+			TERRAIN_TYPES[_mazeData[0]._wallKind]));
+		_groundSprites.load(Common::String::format("%s.gnd",
+			TERRAIN_TYPES[_mazeData[0]._wallKind]));
+		_tileSprites.load(Common::String::format("%s.til",
+			TERRAIN_TYPES[_mazeData[0]._wallKind]));
+
+		for (int i = 0; i < TOTAL_SURFACES; ++i) {
+			_surfaceSprites[i].clear();
+
+			if (_mazeData[0]._surfaceTypes[i] != 0 || i == 4)
+				_surfaceSprites[i].load(OUTDOOR_SURFACES[i]);
+		}
+
+		_wallSprites._wal.clear();
+		Common::String fwlName = Common::String::format("%s.til",
+			TERRAIN_TYPES[_mazeData[0]._wallKind]);
+		_wallSprites._fwl1.load(fwlName);
+		_wallSprites._fwl2.load(fwlName);
+		_wallSprites._fwl3.load(fwlName);
+		_wallSprites._fwl4.load(fwlName);
+		_wallSprites._swl.load(Common::String::format("s%s.swl",
+			TERRAIN_TYPES[_mazeData[0]._wallKind]));
+
+
+	}
 }
 
 int Map::mazeLookup(const Common::Point &pt, int directionLayerIndex) {
diff --git a/engines/xeen/map.h b/engines/xeen/map.h
index 090619f..d697243 100644
--- a/engines/xeen/map.h
+++ b/engines/xeen/map.h
@@ -34,6 +34,7 @@ namespace Xeen {
 
 #define MAP_WIDTH 16
 #define MAP_HEIGHT 16
+#define TOTAL_SURFACES 16
 
 class XeenEngine;
 
@@ -269,6 +270,15 @@ public:
 	MazeWallItem();
 };
 
+struct WallSprites {
+	SpriteResource _wal;
+	SpriteResource _fwl1;
+	SpriteResource _fwl2;
+	SpriteResource _fwl3;
+	SpriteResource _fwl4;
+	SpriteResource _swl;
+};
+
 class Map;
 
 class MonsterObjectData {
@@ -361,6 +371,12 @@ public:
 	MazeEvents _events;
 	HeadData _headData;
 	AnimationInfo _animationInfo;
+	SpriteResource _skySprites;
+	SpriteResource _mazeSkySprites;
+	SpriteResource _groundSprites;
+	SpriteResource _tileSprites;
+	SpriteResource _surfaceSprites[TOTAL_SURFACES];
+	WallSprites _wallSprites;
 	bool _currentIsGrate;
 	bool _currentCantRest;
 	bool _currentIsDrain;
diff --git a/engines/xeen/resources.cpp b/engines/xeen/resources.cpp
index 352e596..d0f5d6a 100644
--- a/engines/xeen/resources.cpp
+++ b/engines/xeen/resources.cpp
@@ -66,6 +66,23 @@ const char *const OPTIONS_TITLE =
 	"\v117Copyright (c) 1993 NWC, Inc.\n"
 	"All Rights Reserved\x01";
 
+const char *const TERRAIN_TYPES[6] = {
+	"town", "cave", "towr", "cstl", "dung", "scfi"
+};
+
+const char *const OUTDOOR_WALLS[15] = {
+	nullptr, "mount", "ltree", "dtree", "grass", "snotree", "snomnt",
+	"dedltree", "mount", "lavamnt", "palm", "dmount", "dedltree",
+	"dedltree", "dedltree"
+};
+
+const char *const OUTDOOR_SURFACES[16] = {
+	"water.srf", "dirt.srf", "grass.srf", "snow.srf", "swamp.srf",
+	"lava.srf", "desert.srf", "road.srf", "dwater.srf", "tflr.srf",
+	"sky.srf", "croad.srf", "sewer.srf", "cloud.srf", "scortch.srf",
+	"space.srf"
+};
+
 const byte SYMBOLS[20][64] = {
 	{ // 0
 		0x00, 0x00, 0xA8, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0x00, 0xA8, 0x9E, 0x9C, 0x9C, 0x9E, 0x9E, 0x9E,
diff --git a/engines/xeen/resources.h b/engines/xeen/resources.h
index 2c537fd..dbb0003 100644
--- a/engines/xeen/resources.h
+++ b/engines/xeen/resources.h
@@ -32,6 +32,12 @@ extern const char *const CREDITS;
 
 extern const char *const OPTIONS_TITLE;
 
+extern const char *const TERRAIN_TYPES[6];
+
+extern const char *const OUTDOOR_WALLS[15];
+
+extern const char *const OUTDOOR_SURFACES[16];
+
 extern const byte SYMBOLS[20][64];
 
 extern const byte TEXT_COLORS[40][4];


Commit: a856e58ee41505db36e208389d5931952540ca84
    https://github.com/scummvm/scummvm/commit/a856e58ee41505db36e208389d5931952540ca84
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-01-13T19:30:03-05:00

Commit Message:
XEEN: Added Combat class and further map loading sprite setting

Changed paths:
  A engines/xeen/combat.cpp
  A engines/xeen/combat.h
    engines/xeen/interface.h
    engines/xeen/map.cpp
    engines/xeen/map.h
    engines/xeen/resources.cpp
    engines/xeen/resources.h



diff --git a/engines/xeen/combat.cpp b/engines/xeen/combat.cpp
new file mode 100644
index 0000000..f870083
--- /dev/null
+++ b/engines/xeen/combat.cpp
@@ -0,0 +1,37 @@
+/* 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 "xeen/combat.h"
+#include "common/algorithm.h"
+
+namespace Xeen {
+
+Combat::Combat(XeenEngine *vm): _vm(vm) {
+	_attackMon1 = _attackMon2 = _attackMon3 = 0;
+	Common::fill(&_charsArray1[0], &_charsArray1[12], 0);
+	Common::fill(&_monPow[0], &_monPow[12], 0);
+	Common::fill(&_monsterScale[0], &_monsterScale[12], 0);
+	Common::fill(&_elemPow[0], &_elemPow[12], 0);
+	Common::fill(&_elemScale[0], &_elemScale[12], 0);
+}
+
+} // End of namespace Xeen
diff --git a/engines/xeen/combat.h b/engines/xeen/combat.h
new file mode 100644
index 0000000..3360bbd
--- /dev/null
+++ b/engines/xeen/combat.h
@@ -0,0 +1,48 @@
+/* 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_COMBAT_H
+#define XEEN_COMBAT_H
+
+#include "common/scummsys.h"
+
+namespace Xeen {
+
+class XeenEngine;
+
+class Combat {
+private:
+	XeenEngine *_vm;
+public:
+	int _charsArray1[12];
+	bool _monPow[12];
+	int _monsterScale[12];
+	int _elemPow[12];
+	int _elemScale[12];
+	int _attackMon1, _attackMon2, _attackMon3;
+public:
+	Combat(XeenEngine *vm);
+};
+
+} // End of namespace Xeen
+
+#endif	/* XEEN_COMBAT_H */
diff --git a/engines/xeen/interface.h b/engines/xeen/interface.h
index 0c014f6..498de3c 100644
--- a/engines/xeen/interface.h
+++ b/engines/xeen/interface.h
@@ -98,8 +98,6 @@ private:
 	SpriteResource *_partyFaces[MAX_ACTIVE_PARTY];
 	DrawStruct _faceDrawStructs[4];
 	DrawStruct _mainList[16];
-	OutdoorDrawList _outdoorList;
-	IndoorDrawList _indoorList;
 	int _combatCharIds[8];
 
 	int _batUIFrame;
@@ -167,6 +165,9 @@ private:
 
 	void updateAutoMap();
 public:
+	OutdoorDrawList _outdoorList;
+	IndoorDrawList _indoorList;
+public:
 	Interface(XeenEngine *vm);
 
 	void setup();
diff --git a/engines/xeen/map.cpp b/engines/xeen/map.cpp
index 07cb0d6..1a01b44 100644
--- a/engines/xeen/map.cpp
+++ b/engines/xeen/map.cpp
@@ -22,6 +22,7 @@
 
 #include "common/serializer.h"
 #include "xeen/map.h"
+#include "xeen/interface.h"
 #include "xeen/resources.h"
 #include "xeen/saves.h"
 #include "xeen/screen.h"
@@ -866,6 +867,9 @@ Map::Map(XeenEngine *vm) : _vm(vm), _mobData(vm) {
 
 void Map::load(int mapId) {
 	Screen &screen = *_vm->_screen;
+	IndoorDrawList &indoorList = _vm->_interface->_indoorList;
+	OutdoorDrawList &outdoorList = _vm->_interface->_outdoorList;
+
 	if (_vm->_falling) {
 		Window &w = screen._windows[9];
 		w.open();
@@ -1010,8 +1014,9 @@ void Map::load(int mapId) {
 	// TODO: Switch setting flags that don't seem to ever be used
  
 	// Reload the monster data for the main maze that we're loading
+	mapId = _vm->_party._mazeId;
 	Common::String filename = Common::String::format("maze%c%03d.mob",
-		(_vm->_party._mazeId >= 100) ? 'x' : '0', _vm->_party._mazeId);
+		(mapId >= 100) ? 'x' : '0', mapId);
 	File mobFile(filename, *_vm->_saves);
 	XeenSerializer sMob(&mobFile, nullptr);
 	_mobData.synchronize(sMob, _monsterData);
@@ -1020,9 +1025,9 @@ void Map::load(int mapId) {
 	// Load sprites for the objects
 	for (uint i = 0; i < _mobData._objectSprites.size(); ++i) {
 		if (_vm->_party._cloudsEnd && _mobData._objectSprites[i]._spriteId == 85 &&
-				_vm->_party._mazeId == 27 && isDarkCc) {
+				mapId == 27 && isDarkCc) {
 			// TODO: Flags set that don't seem to be used
-		} else if (_vm->_party._mazeId == 12 && _vm->_party._gameFlags[43] &&
+		} else if (mapId == 12 && _vm->_party._gameFlags[43] &&
 			_mobData._objectSprites[i]._spriteId == 118 && !isDarkCc) {
 			filename = "085.obj";
 			_mobData._objectSprites[0]._spriteId = 85;
@@ -1053,7 +1058,25 @@ void Map::load(int mapId) {
 
 	// Handle loading miscellaneous sprites for the map
 	if (_isOutdoors) {
-		warning("TODO");
+		warning("TODO");	// Sound loading
+
+		_skySprites.load(isDarkCc ? "sky.sky" : "night.sky");
+		_groundSprites.load("water.out");
+		_tileSprites.load("outdoor.til");
+		outdoorList._skySprite._sprites = &_skySprites;
+		outdoorList._groundSprite._sprites = &_groundSprites;
+		
+		for (int i = 0; i < TOTAL_SURFACES; ++i) {
+			_wallSprites._surfaces[i].clear();
+			if (_mazeData[0]._wallTypes[i] != 0) {
+				_wallSprites._surfaces[i].load(Common::String::format("%s.wal",
+					SURFACE_TYPE_NAMES[i]));
+			}
+
+			_surfaceSprites[i].clear();
+			if (i != 0 && _mazeData[0]._wallTypes[i] != 0)
+				_surfaceSprites[i].load(OUTDOOR_SURFACES[_mazeData[0]._surfaceTypes[i]]);
+		}
 	} else {
 		warning("TODO");	// Sound loading
 
@@ -1072,7 +1095,7 @@ void Map::load(int mapId) {
 				_surfaceSprites[i].load(OUTDOOR_SURFACES[i]);
 		}
 
-		_wallSprites._wal.clear();
+		_wallSprites._surfaces[0].clear();
 		Common::String fwlName = Common::String::format("%s.til",
 			TERRAIN_TYPES[_mazeData[0]._wallKind]);
 		_wallSprites._fwl1.load(fwlName);
@@ -1082,7 +1105,68 @@ void Map::load(int mapId) {
 		_wallSprites._swl.load(Common::String::format("s%s.swl",
 			TERRAIN_TYPES[_mazeData[0]._wallKind]));
 
+		// Set entries in the indoor draw list to the correct sprites
+		// for drawing various parts of the background
+		indoorList._swl_0F1R._sprites = &_wallSprites._swl;
+		indoorList._swl_0F1L._sprites = &_wallSprites._swl;
+		indoorList._swl_1F1R._sprites = &_wallSprites._swl;
+		indoorList._swl_1F1L._sprites = &_wallSprites._swl;
+		indoorList._swl_2F2R._sprites = &_wallSprites._swl;
+		indoorList._swl_2F1R._sprites = &_wallSprites._swl;
+		indoorList._swl_2F1L._sprites = &_wallSprites._swl;
+		indoorList._swl_2F2L._sprites = &_wallSprites._swl;
+
+		indoorList._swl_3F1R._sprites = &_wallSprites._swl;
+		indoorList._swl_3F2R._sprites = &_wallSprites._swl;
+		indoorList._swl_3F3R._sprites = &_wallSprites._swl;
+		indoorList._swl_3F4R._sprites = &_wallSprites._swl;
+		indoorList._swl_3F1L._sprites = &_wallSprites._swl;
+		indoorList._swl_3F2L._sprites = &_wallSprites._swl;
+		indoorList._swl_3F3L._sprites = &_wallSprites._swl;
+		indoorList._swl_3F4L._sprites = &_wallSprites._swl;
+
+		indoorList._swl_4F4R._sprites = &_wallSprites._swl;
+		indoorList._swl_4F3R._sprites = &_wallSprites._swl;
+		indoorList._swl_4F2R._sprites = &_wallSprites._swl;
+		indoorList._swl_4F1R._sprites = &_wallSprites._swl;
+		indoorList._swl_4F1L._sprites = &_wallSprites._swl;
+		indoorList._swl_4F2L._sprites = &_wallSprites._swl;
+		indoorList._swl_4F3L._sprites = &_wallSprites._swl;
+		indoorList._swl_4F4L._sprites = &_wallSprites._swl;
+
+		indoorList._fwl_4F4R._sprites = &_wallSprites._fwl4;
+		indoorList._fwl_4F3R._sprites = &_wallSprites._fwl4;
+		indoorList._fwl_4F2R._sprites = &_wallSprites._fwl4;
+		indoorList._fwl_4F1R._sprites = &_wallSprites._fwl4;
+		indoorList._fwl_4F._sprites = &_wallSprites._fwl4;
+		indoorList._fwl_4F1L._sprites = &_wallSprites._fwl4;
+		indoorList._fwl_4F2L._sprites = &_wallSprites._fwl4;
+		indoorList._fwl_4F3L._sprites = &_wallSprites._fwl4;
+		indoorList._fwl_4F4L._sprites = &_wallSprites._fwl4;
+
+		indoorList._fwl_2F1R._sprites = &_wallSprites._fwl3;
+		indoorList._fwl_2F._sprites = &_wallSprites._fwl3;
+		indoorList._fwl_2F1L._sprites = &_wallSprites._fwl3;
+		indoorList._fwl_3F2R._sprites = &_wallSprites._fwl3;
+		indoorList._fwl_3F1R._sprites = &_wallSprites._fwl3;
+		indoorList._fwl_3F._sprites = &_wallSprites._fwl3;
+		indoorList._fwl_3F1L._sprites = &_wallSprites._fwl3;
+		indoorList._fwl_3F2L._sprites = &_wallSprites._fwl3;
+
+		indoorList._fwl_1F._sprites = &_wallSprites._fwl1;
+		indoorList._fwl_1F1R._sprites = &_wallSprites._fwl1;
+		indoorList._fwl_1F1L._sprites = &_wallSprites._fwl1;
+		
+		indoorList._horizon._sprites = &_groundSprites;
 
+		// Down show horizon for certain maps
+		if (_vm->_files->_isDarkCc) {
+			if ((mapId >= 89 && mapId <= 112) || mapId == 128 || mapId == 129)
+				indoorList._horizon._sprites = nullptr;
+		} else {
+			if (mapId >= 25 && mapId <= 27)
+				indoorList._horizon._sprites = nullptr;
+		}
 	}
 }
 
diff --git a/engines/xeen/map.h b/engines/xeen/map.h
index d697243..37eba70 100644
--- a/engines/xeen/map.h
+++ b/engines/xeen/map.h
@@ -271,7 +271,7 @@ public:
 };
 
 struct WallSprites {
-	SpriteResource _wal;
+	SpriteResource _surfaces[TOTAL_SURFACES];
 	SpriteResource _fwl1;
 	SpriteResource _fwl2;
 	SpriteResource _fwl3;
diff --git a/engines/xeen/resources.cpp b/engines/xeen/resources.cpp
index d0f5d6a..5740a41 100644
--- a/engines/xeen/resources.cpp
+++ b/engines/xeen/resources.cpp
@@ -70,7 +70,7 @@ const char *const TERRAIN_TYPES[6] = {
 	"town", "cave", "towr", "cstl", "dung", "scfi"
 };
 
-const char *const OUTDOOR_WALLS[15] = {
+const char *const SURFACE_TYPE_NAMES[15] = {
 	nullptr, "mount", "ltree", "dtree", "grass", "snotree", "snomnt",
 	"dedltree", "mount", "lavamnt", "palm", "dmount", "dedltree",
 	"dedltree", "dedltree"
diff --git a/engines/xeen/resources.h b/engines/xeen/resources.h
index dbb0003..71ac91f 100644
--- a/engines/xeen/resources.h
+++ b/engines/xeen/resources.h
@@ -34,7 +34,7 @@ extern const char *const OPTIONS_TITLE;
 
 extern const char *const TERRAIN_TYPES[6];
 
-extern const char *const OUTDOOR_WALLS[15];
+extern const char *const SURFACE_TYPE_NAMES[15];
 
 extern const char *const OUTDOOR_SURFACES[16];
 


Commit: 2b78d5190b6b734fbf24ab533cef0c8f427cbe0f
    https://github.com/scummvm/scummvm/commit/2b78d5190b6b734fbf24ab533cef0c8f427cbe0f
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-01-14T00:20:45-05:00

Commit Message:
XEEN: Implementing drawIndoors

Changed paths:
    engines/xeen/interface.cpp
    engines/xeen/interface.h
    engines/xeen/map.cpp
    engines/xeen/map.h
    engines/xeen/resources.cpp
    engines/xeen/resources.h



diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp
index 4bf9b1a..12317da 100644
--- a/engines/xeen/interface.cpp
+++ b/engines/xeen/interface.cpp
@@ -377,6 +377,7 @@ Interface::Interface(XeenEngine *vm) : ButtonContainer(), _vm(vm) {
 	_hiliteChar = -1;
 	_intrIndex1 = 0;
 	_flipWtr = false;
+	_flipWall = false;
 	_flag1 = false;
 	_animCounter = 0;
 	_isAnimReset = false;
@@ -384,11 +385,11 @@ Interface::Interface(XeenEngine *vm) : ButtonContainer(), _vm(vm) {
 	_tillMove = 0;
 	_objNumber = 0;
 	_thinWall = false;
+	_overallFrame = 0;
 
 	Common::fill(&_combatCharIds[0], &_combatCharIds[8], 0);
 	Common::fill(&_wp[0], &_wp[20], 0);
 	Common::fill(&_wo[0], &_wo[308], 0);
-	Common::fill(&_charsArray1[0], &_charsArray1[12], 0);
 
 	initDrawStructs();
 }
@@ -967,7 +968,7 @@ void Interface::draw3d(bool updateFlag) {
 			ds1._sprites = nullptr;
 			ds2._sprites = nullptr;
 
-			if (_charsArray1[idx]) {
+			if (combat._charsArray1[idx]) {
 				int posIndex= combat._attackMon2 && !combat._attackMon3 ? 1 : 0;
 				--combat._charsArray1[idx];
 
@@ -2842,8 +2843,897 @@ void Interface::setMazeBits() {
 
 void Interface::drawIndoors() {
 	Map &map = *_vm->_map;
+	int surfaceId;
+	int idx;
 
-	map.getCell(36);
+	for (int cellIndex = 0; cellIndex < 25; ++cellIndex) {
+		map.getCell(DRAW_NUMBERS[cellIndex]);
+
+		DrawStruct &drawStruct = _indoorList[3 + cellIndex];
+		drawStruct._sprites = &map._surfaceSprites[map._currentSurfaceId];
+
+		surfaceId = map.mazeData()._surfaceTypes[map._currentSurfaceId];
+		if (surfaceId == 5 || surfaceId == 12) {
+			drawStruct._flags = _flipWtr;
+			drawStruct._frame = DRAW_FRAMES[cellIndex][_flipWtr ? 1 : 0];
+		}
+		else {
+			drawStruct._frame = DRAW_FRAMES[cellIndex][_flipWall ? 1 : 0];
+			drawStruct._flags = _flipWall ? 0 : SPRFLAG_HORIZ_FLIPPED;
+		}
+	}
+
+	if (!_wo[27] && !_wo[20] && !_wo[23] && !_wo[12] && !_wo[8] && !_wo[30]) {
+		if (_wo[39])
+			_indoorList._swl_4F4L._frame = 22;
+		else if (_wo[83])
+			_indoorList._swl_4F4L._frame = 46;
+	}
+
+	if (!_wo[27] && !_wo[22] && !_wo[17] && !_wo[12] && !_wo[8]) {
+		if (_wo[38])
+			_indoorList._swl_4F3L._frame = 20;
+		else if (_wo[82])
+			_indoorList._swl_4F3L._frame = 44;
+	}
+
+	if (!_wo[27] && !_wo[22] && !_wo[15] && !_wo[2] && !_wo[7]) {
+		if (_wo[37])
+			_indoorList._swl_4F2L._frame = 18;
+		else if (_wo[81])
+			_indoorList._swl_4F2L._frame = 42;
+	}
+
+	if (!_wo[27] && !_wo[22] && !_wo[15] && !_wo[6]) {
+		if (_wo[36])
+			_indoorList._swl_4F1L._frame = 16;
+		else if (_wo[80])
+			_indoorList._swl_4F1L._frame = 40;
+	}
+
+	if (!_wo[27] && !_wo[21] && !_wo[24] && !_wo[14] && !_wo[10] && !_wo[31]) {
+		if (_wo[43])
+			_indoorList._swl_4F4R._frame = 23;
+		else if (_wo[87])
+			_indoorList._swl_4F4R._frame = 47;
+	}
+
+	if (!_wo[27] && !_wo[22] && !_wo[19] && !_wo[14] && !_wo[10]) {
+		if (_wo[42])
+			_indoorList._swl_4F3R._frame = 21;
+		else if (_wo[86])
+			_indoorList._swl_4F3R._frame = 45;
+	}
+
+	if (!_wo[27] && !_wo[22] && !_wo[15] && !_wo[5] && !_wo[9]) {
+		if (_wo[41])
+			_indoorList._swl_4F2R._frame = 19;
+		else if (_wo[85])
+			_indoorList._swl_4F2R._frame = 43;
+	}
+
+	if (!_wo[27] && !_wo[22] && !_wo[15] && !_wo[6]) {
+		if (_wo[40])
+			_indoorList._swl_4F1R._frame = 17;
+		else if (_wo[84])
+			_indoorList._swl_4F1R._frame = 41;
+	}
+
+	if (!_wo[25] && !_wo[28] && !_wo[20] && !_wo[11] &&
+		!_wo[16] && !_wo[30] && !_wo[32]) {
+		if (_wo[88])
+			_indoorList._fwl_4F4L._frame = 7;
+		else if (_wo[78])
+			_indoorList._fwl_4F4L._frame = 16;
+		else if (_wo[148])
+			_indoorList._fwl_4F4L._frame = _overallFrame + 1;
+		else if (_wo[108])
+			_indoorList._fwl_4F4L._frame = 8;
+		else if (_wo[168])
+			_indoorList._fwl_4F4L._frame = 10;
+		else if (_wo[128])
+			_indoorList._fwl_4F4L._frame = 9;
+		else if (_wo[34])
+			_indoorList._fwl_4F4L._frame = 0;
+		else if (_wo[188])
+			_indoorList._fwl_4F4L._frame = 15;
+		else if (_wo[208])
+			_indoorList._fwl_4F4L._frame = 14;
+		else if (_wo[228])
+			_indoorList._fwl_4F4L._frame = 6;
+		else if (_wo[248])
+			_indoorList._fwl_4F4L._frame = 11;
+		else if (_wo[268])
+			_indoorList._fwl_4F4L._frame = 12;
+		else if (_wo[288])
+			_indoorList._fwl_4F4L._frame = 13;
+	}
+
+	if (!_wo[26] && !_wo[29] && !_wo[21] && !_wo[13] && !_wo[18] && !_wo[31] && !_wo[33]) {
+		if (_wo[93])
+			_indoorList._fwl_4F4R._frame = 7;
+		else if (_wo[79])
+			_indoorList._fwl_4F4R._frame = 16;
+		else if (_wo[153])
+			_indoorList._fwl_4F4R._frame = _overallFrame + 1;
+		else if (_wo[113])
+			_indoorList._fwl_4F4R._frame = 8;
+		else if (_wo[173])
+			_indoorList._fwl_4F4R._frame = 10;
+		else if (_wo[133])
+			_indoorList._fwl_4F4R._frame = 9;
+		else if (_wo[35])
+			_indoorList._fwl_4F4R._frame = 0;
+		else if (_wo[79])
+			_indoorList._fwl_4F4R._frame = 15;
+		else if (_wo[213])
+			_indoorList._fwl_4F4R._frame = 14;
+		else if (_wo[233])
+			_indoorList._fwl_4F4R._frame = 6;
+		else if (_wo[253])
+			_indoorList._fwl_4F4R._frame = 11;
+		else if (_wo[273])
+			_indoorList._fwl_4F4R._frame = 12;
+		else if (_wo[293])
+			_indoorList._fwl_4F4R._frame = 13;
+	}
+
+	if (!_wo[25] && !_wo[28] && !_wo[20] && !_wo[11] && !_wo[16] && !_wo[30]) {
+		if (_wo[32])
+			_indoorList._swl_3F4L._frame = 14;
+		else if (_wo[76])
+			_indoorList._swl_3F4L._frame = 38;
+	}
+
+	if (!_wo[26] && !_wo[29] && !_wo[21] && !_wo[13] && !_wo[18] && !_wo[31]) {
+		if (_wo[33])
+			_indoorList._fwl_3F1R._frame = 15;
+		else if (_wo[77])
+			_indoorList._swl_3F1R._frame = 39;
+	}
+
+	if (_wo[28] && _wo[27]) {
+	}
+	else if (_wo[28] && _wo[12]) {
+	}
+	else if (_wo[28] && _wo[23]) {
+	}
+	else if (_wo[28] && _wo[8]) {
+	}
+	else if (_wo[25] && _wo[27]) {
+	}
+	else if (_wo[25] && _wo[12]) {
+	}
+	else if (_wo[25] && _wo[23]) {
+	}
+	else if (_wo[25] && _wo[8]) {
+	}
+	else if (_wo[11] && _wo[27]) {
+	}
+	else if (_wo[11] && _wo[12]) {
+	}
+	else if (_wo[11] && _wo[23]) {
+	}
+	else if (_wo[11] && _wo[8]) {
+	}
+	else if (_wo[17] && _wo[27]) {
+	}
+	else if (_wo[17] && _wo[12]) {
+	}
+	else if (_wo[17] && _wo[23]) {
+	}
+	else if (_wo[17] && _wo[8]) {
+	}
+	else if (_wo[20]) {
+	}
+	else if (_wo[30]) {
+		_indoorList._swl_3F3L._frame = 12;
+	}
+	else if (_wo[74]) {
+		_indoorList._swl_3F3L._frame = 36;
+	}
+
+	if (_wo[29] && _wo[27]) {
+	}
+	else if (_wo[29] && _wo[14]) {
+	}
+	else if (_wo[29] && _wo[24]) {
+	}
+	else if (_wo[29] && _wo[10]) {
+	}
+	else if (_wo[26] && _wo[27]) {
+	}
+	else if (_wo[26] && _wo[14]) {
+	}
+	else if (_wo[26] && _wo[24]) {
+	}
+	else if (_wo[26] && _wo[10]) {
+	}
+	else if (_wo[13] && _wo[27]) {
+	}
+	else if (_wo[13] && _wo[14]) {
+	}
+	else if (_wo[13] && _wo[24]) {
+	}
+	else if (_wo[13] && _wo[10]) {
+	}
+	else if (_wo[19] && _wo[27]) {
+	}
+	else if (_wo[19] && _wo[24]) {
+	}
+	else if (_wo[19] && _wo[10]) {
+	}
+	else if (_wo[21]) {
+	}
+	else if (_wo[31]) {
+		_indoorList._swl_3F2R._frame = 13;
+	}
+	else if (_wo[75]) {
+		_indoorList._swl_3F2R._frame = 37;
+	}
+
+	if (!_wo[27] && !_wo[20] && !_wo[12] && !_wo[23] && !_wo[8] && !_wo[30]) {
+		if (_wo[89])
+			_indoorList._fwl_4F3L._frame = 7;
+		else if (_wo[44])
+			_indoorList._fwl_4F3L._frame = 16;
+		else if (_wo[149])
+			_indoorList._fwl_4F3L._frame = _overallFrame + 1;
+		else if (_wo[109])
+			_indoorList._fwl_4F3L._frame = 8;
+		else if (_wo[169])
+			_indoorList._fwl_4F3L._frame = 10;
+		else if (_wo[129])
+			_indoorList._fwl_4F3L._frame = 9;
+		else if (_wo[0])
+			_indoorList._fwl_4F3L._frame = 0;
+		else if (_wo[189])
+			_indoorList._fwl_4F3L._frame = 15;
+		else if (_wo[209])
+			_indoorList._fwl_4F3L._frame = 14;
+		else if (_wo[229])
+			_indoorList._fwl_4F3L._frame = 6;
+		else if (_wo[249])
+			_indoorList._fwl_4F3L._frame = 11;
+		else if (_wo[269])
+			_indoorList._fwl_4F3L._frame = 12;
+		else if (_wo[289])
+			_indoorList._fwl_4F3L._frame = 13;
+	}
+
+	if (_wo[22] && _wo[20]) {
+	}
+	else if (_wo[22] && _wo[23]) {
+	}
+	else if (_wo[20] && _wo[17]) {
+	}
+	else if (_wo[23] && _wo[17]) {
+	}
+	else if (_wo[12]) {
+	}
+	else if (_wo[8]) {
+	}
+	else if (_wo[90]) {
+		_indoorList._fwl_4F2L._frame = 7;
+	}
+	else if (_wo[45])  {
+		_indoorList._fwl_4F2L._frame = 16;
+	}
+	else if (_wo[150]) {
+		_indoorList._fwl_4F2L._frame = _overallFrame + 1;
+	}
+	else if (_wo[110]) {
+		_indoorList._fwl_4F2L._frame = 8;
+	}
+	else if (_wo[170]) {
+		_indoorList._fwl_4F2L._frame = 10;
+	}
+	else if (_wo[130]) {
+		_indoorList._fwl_4F2L._frame = 9;
+	}
+	else if (_wo[1]) {
+		_indoorList._fwl_4F2L._frame = 0;
+	}
+	else if (_wo[190]) {
+		_indoorList._fwl_4F2L._frame = 15;
+	}
+	else if (_wo[210]) {
+		_indoorList._fwl_4F2L._frame = 14;
+	}
+	else if (_wo[230]) {
+		_indoorList._fwl_4F2L._frame = 6;
+	}
+	else if (_wo[250]) {
+		_indoorList._fwl_4F2L._frame = 11;
+	}
+	else if (_wo[270]) {
+		_indoorList._fwl_4F2L._frame = 12;
+	}
+	else if (_wo[290]) {
+		_indoorList._fwl_4F2L._frame = 13;
+	}
+
+	if (_wo[15] && _wo[17]) {
+	}
+	else if (_wo[15] && _wo[12]) {
+	}
+	else if (_wo[12] && _wo[7]) {
+	}
+	else if (_wo[17] && _wo[7]) {
+	}
+	else if (_wo[91]) {
+		_indoorList._fwl_4F1L._frame = 7;
+	}
+	else if (_wo[46]) {
+		_indoorList._fwl_4F1L._frame = 16;
+	}
+	else if (_wo[151]) {
+		_indoorList._fwl_4F1L._frame = _overallFrame + 1;
+	}
+	else if (_wo[111]) {
+		_indoorList._fwl_4F1L._frame = 8;
+	}
+	else if (_wo[171]) {
+		_indoorList._fwl_4F1L._frame = 10;
+	}
+	else if (_wo[131]) {
+		_indoorList._fwl_4F1L._frame = 9;
+	}
+	else if (_wo[2]) {
+		_indoorList._fwl_4F1L._frame = 0;
+	}
+	else if (_wo[191]) {
+		_indoorList._fwl_4F1L._frame = 15;
+	}
+	else if (_wo[211]) {
+		_indoorList._fwl_4F1L._frame = 14;
+	}
+	else if (_wo[231]) {
+		_indoorList._fwl_4F1L._frame = 6;
+	}
+	else if (_wo[251]) {
+		_indoorList._fwl_4F1L._frame = 11;
+	}
+	else if (_wo[271]) {
+		_indoorList._fwl_4F1L._frame = 12;
+	}
+	else if (_wo[291]) {
+		_indoorList._fwl_4F1L._frame = 13;
+	}
+
+	if (!_wo[27] && !_wo[21] && !_wo[14] && !_wo[24] && !_wo[10] && !_wo[31]) {
+		if (_wo[92]) {
+			_indoorList._fwl_4F3R._frame = 7;
+		}
+		else if (_wo[47]) {
+			_indoorList._fwl_4F3R._frame = 16;
+		}
+		else if (_wo[152]) {
+			_indoorList._fwl_4F3R._frame = _overallFrame + 1;
+		}
+		else if (_wo[112]) {
+			_indoorList._fwl_4F3R._frame = 8;
+		}
+		else if (_wo[172]) {
+			_indoorList._fwl_4F3R._frame = 10;
+		}
+		else if (_wo[132]) {
+			_indoorList._fwl_4F3R._frame = 9;
+		}
+		else if (_wo[3]) {
+			_indoorList._fwl_4F3R._frame = 0;
+		}
+		else if (_wo[192]) {
+			_indoorList._fwl_4F3R._frame = 15;
+		}
+		else if (_wo[212]) {
+			_indoorList._fwl_4F3R._frame = 14;
+		}
+		else if (_wo[232]) {
+			_indoorList._fwl_4F3R._frame = 6;
+		}
+		else if (_wo[252]) {
+			_indoorList._fwl_4F3R._frame = 11;
+		}
+		else if (_wo[272]) {
+			_indoorList._fwl_4F3R._frame = 12;
+		}
+		else if (_wo[292]) {
+			_indoorList._fwl_4F3R._frame = 13;
+		}
+	}
+
+	if (_wo[22] && _wo[21]) {
+	}
+	else if (_wo[22] && _wo[24]) {
+	}
+	else if (_wo[21] && _wo[19]) {
+	}
+	else if (_wo[24] && _wo[19]) {
+	}
+	else if (_wo[14] || _wo[10]) {
+	}
+	else if (_wo[94]) {
+		_indoorList._fwl_4F2R._frame = 7;
+	}
+	else if (_wo[48]) {
+		_indoorList._fwl_4F2R._frame = 16;
+	}
+	else if (_wo[154]) {
+		_indoorList._fwl_4F2R._frame = _overallFrame + 1;
+	}
+	else if (_wo[114]) {
+		_indoorList._fwl_4F2R._frame = 8;
+	}
+	else if (_wo[174]) {
+		_indoorList._fwl_4F2R._frame = 10;
+	}
+	else if (_wo[134]) {
+		_indoorList._fwl_4F2R._frame = 9;
+	}
+	else if (_wo[4]) {
+		_indoorList._fwl_4F2R._frame = 0;
+	}
+	else if (_wo[194]) {
+		_indoorList._fwl_4F2R._frame = 15;
+	}
+	else if (_wo[214]) {
+		_indoorList._fwl_4F2R._frame = 14;
+	}
+	else if (_wo[234]) {
+		_indoorList._fwl_4F2R._frame = 6;
+	}
+	else if (_wo[254]) {
+		_indoorList._fwl_4F2R._frame = 11;
+	}
+	else if (_wo[274]) {
+		_indoorList._fwl_4F2R._frame = 12;
+	}
+	else if (_wo[294]) {
+		_indoorList._fwl_4F2R._frame = 13;
+	}
+
+	if (_wo[15] && _wo[19]) {
+	}
+	else if (_wo[15] && _wo[14]) {
+	}
+	else if (_wo[14] && _wo[9]) {
+	}
+	else if (_wo[19] && _wo[9]) {
+	}
+	else if (_wo[95]) {
+		_indoorList._fwl_4F1R._frame = 7;
+	}
+	else if (_wo[49]) {
+		_indoorList._fwl_4F1R._frame = 16;
+	}
+	else if (_wo[155]) {
+		_indoorList._fwl_4F1R._frame = _overallFrame + 1;
+	}
+	else if (_wo[115]) {
+		_indoorList._fwl_4F1R._frame = 8;
+	}
+	else if (_wo[175]) {
+		_indoorList._fwl_4F1R._frame = 10;
+	}
+	else if (_wo[135]) {
+		_indoorList._fwl_4F1R._frame = 9;
+	}
+	else if (_wo[5]) {
+		_indoorList._fwl_4F1R._frame = 0;
+	}
+	else if (_wo[195]) {
+		_indoorList._fwl_4F1R._frame = 15;
+	}
+	else if (_wo[215]) {
+		_indoorList._fwl_4F1R._frame = 14;
+	}
+	else if (_wo[235]) {
+		_indoorList._fwl_4F1R._frame = 6;
+	}
+	else if (_wo[255]) {
+		_indoorList._fwl_4F1R._frame = 11;
+	}
+	else if (_wo[275]) {
+		_indoorList._fwl_4F1R._frame = 12;
+	}
+	else if (_wo[295]) {
+		_indoorList._fwl_4F1R._frame = 13;
+	}
+
+	if (_wo[27] || _wo[22] || _wo[15] || _wo[96]) {
+	}
+	else if (_wo[50]) {
+		_indoorList._fwl_4F._frame = 16;
+	}
+	else if (_wo[156]) {
+		_indoorList._fwl_4F._frame = _overallFrame + 1;
+	}
+	else if (_wo[116]) {
+		_indoorList._fwl_4F._frame = 8;
+	}
+	else if (_wo[176]) {
+		_indoorList._fwl_4F._frame = 10;
+	}
+	else if (_wo[136]) {
+		_indoorList._fwl_4F._frame = 9;
+	}
+	else if (_wo[6]) {
+		_indoorList._fwl_4F._frame = 0;
+	}
+	else if (_wo[196]) {
+		_indoorList._fwl_4F._frame = 15;
+	}
+	else if (_wo[216]) {
+		_indoorList._fwl_4F._frame = 14;
+	}
+	else if (_wo[236]) {
+		_indoorList._fwl_4F._frame = 6;
+	}
+	else if (_wo[256]) {
+		_indoorList._fwl_4F._frame = 11;
+	}
+	else if (_wo[276]) {
+		_indoorList._fwl_4F._frame = 12;
+	}
+	else if (_wo[296]) {
+		_indoorList._fwl_4F._frame = 13;
+	}
+
+	if (!_wo[27] && !_wo[22] && !_wo[15]) {
+		if (_wo[7])
+			_indoorList._swl_3F1L._frame = 8;
+		else if (_wo[51])
+			_indoorList._swl_3F1L._frame = 32;
+	}
+
+	if (_wo[22] && _wo[23]) {
+	}
+	else if (_wo[22] && _wo[20]) {
+	}
+	else if (_wo[17] && _wo[23]) {
+	}
+	else if (_wo[17] && _wo[20]) {
+	}
+	else if (_wo[8]) {
+		_indoorList._swl_3F2L._frame = 10;
+	}
+	else if (_wo[52]) {
+		_indoorList._swl_3F2L._frame = 34;
+	}
+
+	if (_wo[27] || _wo[22] || _wo[15]) {
+	}
+	else if (_wo[9]) {
+		_indoorList._swl_3F4R._frame = 9;
+	}
+	else if (_wo[53]) {
+		_indoorList._swl_3F4R._frame = 33;
+	}
+
+	if (_wo[22] && _wo[24]) {
+	}
+	else if (_wo[22] && _wo[21]) {
+	}
+	else if (_wo[19] && _wo[24]) {
+	}
+	else if (_wo[19] && _wo[21]) {
+	}
+	else if (_wo[14]) {
+	}
+	else if (_wo[10]) {
+		_indoorList._swl_3F3R._frame = 11;
+	}
+	else if (_wo[54]) {
+		_indoorList._swl_3F3R._frame = 35;
+	}
+
+	if (_wo[25] || _wo[28] || _wo[20] || _wo[16]) {
+	}
+	else if (_wo[97]) {
+		_indoorList._fwl_3F2L._frame = 24;
+	}
+	else if (_wo[55]) {
+		_indoorList._fwl_3F2L._frame = 33;
+	}
+	else if (_wo[137]) {
+		_indoorList._fwl_3F2L._frame = 26;
+	}
+	else if (_wo[157]) {
+		_indoorList._fwl_3F2L._frame = _overallFrame + 18;
+	}
+	else if (_wo[117]) {
+		_indoorList._fwl_3F2L._frame = 25;
+	}
+	else if (_wo[177]) {
+		_indoorList._fwl_3F2L._frame = 27;
+	}
+	else if (_wo[11]) {
+		_indoorList._fwl_3F2L._frame = 17;
+	}
+	else if (_wo[197]) {
+		_indoorList._fwl_3F2L._frame = 32;
+	}
+	else if (_wo[217]) {
+		_indoorList._fwl_3F2L._frame = 31;
+	}
+	else if (_wo[237]) {
+		_indoorList._fwl_3F2L._frame = 23;
+	}
+	else if (_wo[257]) {
+		_indoorList._fwl_3F2L._frame = 28;
+	}
+	else if (_wo[277]) {
+		_indoorList._fwl_3F2L._frame = 29;
+	}
+	else if (_wo[297]) {
+		_indoorList._fwl_3F2L._frame = 30;
+	}
+
+	if (_wo[22] && _wo[23]) {
+	}
+	else if (_wo[22] && _wo[20]) {
+	}
+	else if (_wo[23] && _wo[17]) {
+	}
+	else if (_wo[20] && _wo[17]) {
+	}
+	else if (_wo[98]) {
+		_indoorList._fwl_3F1L._frame = 24;
+	}
+	else if (_wo[56]) {
+		_indoorList._fwl_3F1L._frame = 33;
+	}
+	else if (_wo[178]) {
+		_indoorList._fwl_3F1L._frame = 27;
+	}
+	else if (_wo[118]) {
+		_indoorList._fwl_3F1L._frame = 25;
+	}
+	else if (_wo[158]) {
+		_indoorList._fwl_3F1L._frame = _overallFrame + 18;
+	}
+	else if (_wo[138]) {
+		_indoorList._fwl_3F1L._frame = 26;
+	}
+	else if (_wo[12]) {
+		_indoorList._fwl_3F1L._frame = 17;
+	}
+	else if (_wo[198]) {
+		_indoorList._fwl_3F1L._frame = 32;
+	}
+	else if (_wo[218]) {
+		_indoorList._fwl_3F1L._frame = 31;
+	}
+	else if (_wo[238]) {
+		_indoorList._fwl_3F1L._frame = 23;
+	}
+	else if (_wo[258]) {
+		_indoorList._fwl_3F1L._frame = 28;
+	}
+	else if (_wo[278]) {
+		_indoorList._fwl_3F1L._frame = 29;
+	}
+	else if (_wo[298]) {
+		_indoorList._fwl_3F1L._frame = 30;
+	}
+
+	if (_wo[26] || _wo[29] || _wo[21] || _wo[18]) {
+	}
+	else if (_wo[99]) {
+		_indoorList._fwl_3F2R._frame = 24;
+	}
+	else if (_wo[57]) {
+		_indoorList._fwl_3F2R._frame = 33;
+	}
+	else if (_wo[139]) {
+		_indoorList._fwl_3F2R._frame = 26;
+	}
+	else if (_wo[159]) {
+		_indoorList._fwl_3F2R._frame = _overallFrame + 18;
+	}
+	else if (_wo[119]) {
+		_indoorList._fwl_3F2R._frame = 25;
+	}
+	else if (_wo[179]) {
+		_indoorList._fwl_3F2R._frame = 27;
+	}
+	else if (_wo[13]) {
+		_indoorList._fwl_3F2R._frame = 17;
+	}
+	else if (_wo[199]) {
+		_indoorList._fwl_3F2R._frame = 32;
+	}
+	else if (_wo[219]) {
+		_indoorList._fwl_3F2R._frame = 31;
+	}
+	else if (_wo[239]) {
+		_indoorList._fwl_3F2R._frame = 23;
+	}
+	else if (_wo[259]) {
+		_indoorList._fwl_3F2R._frame = 28;
+	}
+	else if (_wo[279]) {
+		_indoorList._fwl_3F2R._frame = 29;
+	}
+	else if (_wo[299]) {
+		_indoorList._fwl_3F2R._frame = 30;
+	}
+
+	if (_wo[22] && _wo[24]) {
+	}
+	else if (_wo[22] && _wo[21]) {
+	}
+	else if (_wo[24] && _wo[19]) {
+	}
+	else if (_wo[21] && _wo[19]) {
+	}
+	else if (_wo[100]) {
+		_indoorList._fwl_3F1R._frame = 24;
+	}
+	else if (_wo[58]) {
+		_indoorList._fwl_3F1R._frame = 33;
+	}
+	else if (_wo[140]) {
+		_indoorList._fwl_3F1R._frame = 26;
+	}
+	else if (_wo[160]) {
+		_indoorList._fwl_3F1R._frame = _overallFrame + 18;
+	}
+	else if (_wo[120]) {
+		_indoorList._fwl_3F1R._frame = 25;
+	}
+	else if (_wo[180]) {
+		_indoorList._fwl_3F1R._frame = 27;
+	}
+	else if (_wo[14]) {
+		_indoorList._fwl_3F1R._frame = 17;
+	}
+	else if (_wo[200]) {
+		_indoorList._fwl_3F1R._frame = 32;
+	}
+	else if (_wo[220]) {
+		_indoorList._fwl_3F1R._frame = 31;
+	}
+	else if (_wo[240]) {
+		_indoorList._fwl_3F1R._frame = 23;
+	}
+	else if (_wo[260]) {
+		_indoorList._fwl_3F1R._frame = 28;
+	}
+	else if (_wo[280]) {
+		_indoorList._fwl_3F1R._frame = 29;
+	}
+	else if (_wo[300]) {
+		_indoorList._fwl_3F1R._frame = 30;
+	}
+
+	if (_wo[22] || _wo[27]) {
+	}
+	else if (_wo[101]) {
+		_indoorList._fwl_3F._frame = 24;
+	}
+	else if (_wo[59]) {
+		_indoorList._fwl_3F._frame = 33;
+	}
+	else if (_wo[141]) {
+		_indoorList._fwl_3F._frame = 26;
+	}
+	else if (_wo[161]) {
+		_indoorList._fwl_3F._frame = _overallFrame + 18;
+	}
+	else if (_wo[121]) {
+		_indoorList._fwl_3F._frame = 25;
+	}
+	else if (_wo[181]) {
+		_indoorList._fwl_3F._frame = 27;
+	}
+	else if (_wo[15]) {
+		_indoorList._fwl_3F._frame = 17;
+	}
+	else if (_wo[201]) {
+		_indoorList._fwl_3F._frame = 32;
+	}
+	else if (_wo[221]) {
+		_indoorList._fwl_3F._frame = 31;
+	}
+	else if (_wo[241]) {
+		_indoorList._fwl_3F._frame = 23;
+	}
+	else if (_wo[261]) {
+		_indoorList._fwl_3F._frame = 28;
+	}
+	else if (_wo[281]) {
+		_indoorList._fwl_3F._frame = 29;
+	}
+	else if (_wo[301]) {
+		_indoorList._fwl_3F._frame = 30;
+	}
+
+	if (_wo[25] || _wo[28] || _wo[20]) {
+	}
+	else if (_wo[16]) {
+		_indoorList._swl_2F2L._frame = 6;
+	}
+	else if (_wo[60]) {
+		_indoorList._swl_2F2L._frame = 30;
+	}
+
+	if (_wo[27] || _wo[22]) {
+	}
+	else if (_wo[17]) {
+		_indoorList._swl_2F1L._frame = 4;
+	}
+	else if (_wo[61]) {
+		_indoorList._swl_2F1L._frame = 28;
+	}
+
+	if (_wo[26] || _wo[29] || _wo[21]) {
+	}
+	else if (_wo[18]) {
+		_indoorList._swl_2F2R._frame = 7;
+	}
+	else if (_wo[62]) {
+		_indoorList._swl_2F2R._frame = 31;
+	}
+
+	if (_wo[27] || _wo[22]) {
+	}
+	else if (_wo[19]) {
+		_indoorList._swl_2F1R._frame = 5;
+	}
+	else if (_wo[63]) {
+		_indoorList._swl_2F1R._frame = 29;
+	}
+
+	if (_wo[27] && _wo[25]) {
+	}
+	else if (_wo[27] && _wo[28]) {
+	}
+	else if (_wo[23] & _wo[25]) {
+	}
+	else if (_wo[23] && _wo[28]) {
+	}
+	else if (_wo[102]) {
+		_indoorList._fwl_2F1L._frame = 7;
+	}
+	else if (_wo[64]) {
+		_indoorList._fwl_2F1L._frame = 16;
+	}
+	else if (_wo[182]) {
+		_indoorList._fwl_2F1L._frame = 10;
+	}
+	else if (_wo[122]) {
+		_indoorList._fwl_2F1L._frame = 8;
+	} 
+	else if (_wo[142]) {
+		_indoorList._fwl_2F1L._frame = 9;
+	}
+	else if (_wo[162]) {
+		_indoorList._fwl_2F1L._frame = _overallFrame + 1;
+	}
+	else if (_wo[20]) {
+		_indoorList._fwl_2F1L._frame = 0;
+	}
+	else if (_wo[202]) {
+		_indoorList._fwl_2F1L._frame = 15;
+	}
+	else if (_wo[222]) {
+		_indoorList._fwl_2F1L._frame = 14;
+	}
+	else if (_wo[242]) {
+		_indoorList._fwl_2F1L._frame = 6;
+	}
+	else if (_wo[262]) {
+		_indoorList._fwl_2F1L._frame = 11;
+	}
+	else if (_wo[282]) {
+		_indoorList._fwl_2F1L._frame = 12;
+	}
+	else if (_wo[302]) {
+		_indoorList._fwl_2F1L._frame = 13;
+	}
+	
 
 	// TODO
 }
diff --git a/engines/xeen/interface.h b/engines/xeen/interface.h
index 498de3c..43b1f31 100644
--- a/engines/xeen/interface.h
+++ b/engines/xeen/interface.h
@@ -116,6 +116,7 @@ private:
 	int _hiliteChar;
 	int _intrIndex1;
 	bool _flipWtr;
+	bool _flipWall;
 	bool _flag1;
 	int _animCounter;
 	bool _isAnimReset;
@@ -125,7 +126,7 @@ private:
 	byte _wp[20];
 	byte _wo[308];
 	bool _thinWall;
-	int _charsArray1[12];
+	int _overallFrame;
 
 	void loadSprites();
 
diff --git a/engines/xeen/map.cpp b/engines/xeen/map.cpp
index 1a01b44..3650c9d 100644
--- a/engines/xeen/map.cpp
+++ b/engines/xeen/map.cpp
@@ -1095,7 +1095,9 @@ void Map::load(int mapId) {
 				_surfaceSprites[i].load(OUTDOOR_SURFACES[i]);
 		}
 
-		_wallSprites._surfaces[0].clear();
+		for (int i = 0; i < TOTAL_SURFACES; ++i)
+			_wallSprites._surfaces[i].clear();
+
 		Common::String fwlName = Common::String::format("%s.til",
 			TERRAIN_TYPES[_mazeData[0]._wallKind]);
 		_wallSprites._fwl1.load(fwlName);
diff --git a/engines/xeen/map.h b/engines/xeen/map.h
index 37eba70..d68bc2b 100644
--- a/engines/xeen/map.h
+++ b/engines/xeen/map.h
@@ -360,7 +360,6 @@ private:
 	bool _stepped;
 	int _mazeDataIndex;
 	bool _currentSteppedOn;
-	int _currentSurfaceId;
 
 	void loadEvents(int mapId);
 
@@ -385,6 +384,7 @@ public:
 	int _currentMonsterFlags;
 	MazeWallLayers _currentWall;
 	int _currentTile;
+	int _currentSurfaceId;
 public:
 	Map(XeenEngine *vm);
 
@@ -397,6 +397,9 @@ public:
 	void saveMaze();
 
 	int getCell(int idx);
+
+	MazeData mazeData() { return _mazeData[0]; }
+
 };
 
 } // End of namespace Xeen
diff --git a/engines/xeen/resources.cpp b/engines/xeen/resources.cpp
index 5740a41..e56ad16 100644
--- a/engines/xeen/resources.cpp
+++ b/engines/xeen/resources.cpp
@@ -432,4 +432,18 @@ const byte WALL_NUMBERS[4][96] = {
 	}
 };
 
+const int DRAW_NUMBERS[25] = {
+	36, 37, 38, 43, 42, 41, 39, 20, 22, 24, 33, 31, 29, 26, 10, 11,
+	18, 16, 13, 5, 9, 6, 0, 4, 1
+};
+
+const int DRAW_FRAMES[25][2] = {
+	{ 18, 24 }, { 19, 23 }, { 20, 22 }, { 10, 24 }, { 19, 23 }, { 20, 22 },
+	{ 21, 21 }, { 11, 17 }, { 12, 16 }, { 13, 15 }, { 11, 17 }, { 12, 16 },
+	{ 13, 15 }, { 14, 14 }, { 6, 10 }, { 7, 9 }, { 6, 10 }, { 7, 9 },
+	{ 8, 8 }, { 3, 5 }, { 3, 5 }, { 4, 4 }, { 0, 2 }, { 0, 2 },
+	{ 1, 1 }
+};
+
+
 } // End of namespace Xeen
diff --git a/engines/xeen/resources.h b/engines/xeen/resources.h
index 71ac91f..bed9569 100644
--- a/engines/xeen/resources.h
+++ b/engines/xeen/resources.h
@@ -90,6 +90,10 @@ extern const int DIRECTION_ANIM_POSITIONS[4][4];
 
 extern const byte WALL_NUMBERS[4][96];
 
+extern const int DRAW_NUMBERS[25];
+
+extern const int DRAW_FRAMES[25][2];
+
 } // End of namespace Xeen
 
 #endif	/* XEEN_RESOURCES_H */


Commit: 5f2e145580ae4c10fd384933ae65b66215779fd9
    https://github.com/scummvm/scummvm/commit/5f2e145580ae4c10fd384933ae65b66215779fd9
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-01-14T08:48:16-05:00

Commit Message:
XEEN: Remainder of drawIndoors implemented

Changed paths:
    engines/xeen/combat.cpp
    engines/xeen/combat.h
    engines/xeen/interface.cpp
    engines/xeen/interface.h
    engines/xeen/map.cpp
    engines/xeen/map.h
    engines/xeen/screen.cpp
    engines/xeen/xeen.cpp
    engines/xeen/xeen.h



diff --git a/engines/xeen/combat.cpp b/engines/xeen/combat.cpp
index f870083..b3ef4fd 100644
--- a/engines/xeen/combat.cpp
+++ b/engines/xeen/combat.cpp
@@ -32,6 +32,7 @@ Combat::Combat(XeenEngine *vm): _vm(vm) {
 	Common::fill(&_monsterScale[0], &_monsterScale[12], 0);
 	Common::fill(&_elemPow[0], &_elemPow[12], 0);
 	Common::fill(&_elemScale[0], &_elemScale[12], 0);
+	Common::fill(&_shooting[0], &_shooting[6], 0);
 }
 
 } // End of namespace Xeen
diff --git a/engines/xeen/combat.h b/engines/xeen/combat.h
index 3360bbd..24a3587 100644
--- a/engines/xeen/combat.h
+++ b/engines/xeen/combat.h
@@ -38,6 +38,7 @@ public:
 	int _monsterScale[12];
 	int _elemPow[12];
 	int _elemScale[12];
+	bool _shooting[6];
 	int _attackMon1, _attackMon2, _attackMon3;
 public:
 	Combat(XeenEngine *vm);
diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp
index 12317da..ec66434 100644
--- a/engines/xeen/interface.cpp
+++ b/engines/xeen/interface.cpp
@@ -378,6 +378,8 @@ Interface::Interface(XeenEngine *vm) : ButtonContainer(), _vm(vm) {
 	_intrIndex1 = 0;
 	_flipWtr = false;
 	_flipWall = false;
+	_flipSky = false;
+	_flipGround = false;
 	_flag1 = false;
 	_animCounter = 0;
 	_isAnimReset = false;
@@ -386,6 +388,7 @@ Interface::Interface(XeenEngine *vm) : ButtonContainer(), _vm(vm) {
 	_objNumber = 0;
 	_thinWall = false;
 	_overallFrame = 0;
+	_isShooting = false;
 
 	Common::fill(&_combatCharIds[0], &_combatCharIds[8], 0);
 	Common::fill(&_wp[0], &_wp[20], 0);
@@ -960,6 +963,7 @@ void Interface::draw3d(bool updateFlag) {
 		const int INDOOR_COMBAT_POS[3][2] = { { 102, 134 }, { 36, 67 }, { 161, 161 } };
 		const int INDOOR_COMBAT_POS2[4] = { 8, 6, 4, 2 };
 
+		// TODO: Double check this, since it's not being used?
 		MazeObject &objObject = map._mobData._objects[_objNumber - 1];
 
 		for (int idx = 0; idx < 3; ++idx) {
@@ -3705,7 +3709,7 @@ void Interface::drawIndoors() {
 	}
 	else if (_wo[122]) {
 		_indoorList._fwl_2F1L._frame = 8;
-	} 
+	}
 	else if (_wo[142]) {
 		_indoorList._fwl_2F1L._frame = 9;
 	}
@@ -3733,7 +3737,244 @@ void Interface::drawIndoors() {
 	else if (_wo[302]) {
 		_indoorList._fwl_2F1L._frame = 13;
 	}
+
+	if (_wo[27] && _wo[26]) {
+	}
+	else if (_wo[27] && _wo[29]) {
+	}
+	else if (_wo[24] && _wo[26]) {
+	}
+	else if (_wo[24] && _wo[29]) {
+	}
+	else if (_wo[103]) {
+		_indoorList._fwl_2F1R._frame = 7;
+	}
+	else if (_wo[65]) {
+		_indoorList._fwl_2F1R._frame = 16;
+	}
+	else if (_wo[183]) {
+		_indoorList._fwl_2F1R._frame = 10;
+	}
+	else if (_wo[123]) {
+		_indoorList._fwl_2F1R._frame = 8;
+	}
+	else if (_wo[143]) {
+		_indoorList._fwl_2F1R._frame = 9;
+	}
+	else if (_wo[163]) {
+		_indoorList._fwl_2F1R._frame = _overallFrame + 1;
+	}
+	else if (_wo[21]) {
+		_indoorList._fwl_2F1R._frame = 0;
+	}
+	else if (_wo[203]) {
+		_indoorList._fwl_2F1R._frame = 15;
+	}
+	else if (_wo[223]) {
+		_indoorList._fwl_2F1R._frame = 14;
+	}
+	else if (_wo[243]) {
+		_indoorList._fwl_2F1R._frame = 6;
+	}
+	else if (_wo[263]) {
+		_indoorList._fwl_2F1R._frame = 11;
+	}
+	else if (_wo[283]) {
+		_indoorList._fwl_2F1R._frame = 12;
+	}
+	else if (_wo[303]) {
+		_indoorList._fwl_2F1R._frame = 13;
+	}
+
+	if (_wo[27]) {
+
+	}
+	else if (_wo[104]) {
+		_indoorList._fwl_2F._frame = 7;
+	}
+	else if (_wo[66]) {
+		_indoorList._fwl_2F._frame = 16;
+	}
+	else if (_wo[184]) {
+		_indoorList._fwl_2F._frame = 10;
+	}
+	else if (_wo[124]) {
+		_indoorList._fwl_2F._frame = 8;
+	}
+	else if (_wo[144]) {
+		_indoorList._fwl_2F._frame = 9;
+	}
+	else if (_wo[164]) {
+		_indoorList._fwl_2F._frame = _overallFrame + 1;
+	}
+	else if (_wo[22]) {
+		_indoorList._fwl_2F._frame = 0;
+	}
+	else if (_wo[204]) {
+		_indoorList._fwl_2F._frame = 15;
+	}
+	else if (_wo[224]) {
+		_indoorList._fwl_2F._frame = 14;
+	}
+	else if (_wo[244]) {
+		_indoorList._fwl_2F._frame = 6;
+	}
+	else if (_wo[264]) {
+		_indoorList._fwl_2F._frame = 11;
+	}
+	else if (_wo[284]) {
+		_indoorList._fwl_2F._frame = 12;
+	}
+	else if (_wo[304]) {
+		_indoorList._fwl_2F._frame = 13;
+	}
+
+	if (_wo[27]) {
+	}
+	else if (_wo[23]) {
+		_indoorList._swl_1F1L._frame = 2;
+	}
+	else if (_wo[67]) {
+		_indoorList._swl_1F1L._frame = 26;
+	}
+
+	if (_wo[27]) {
+	}
+	else if (_wo[24]) {
+		_indoorList._swl_1F1R._frame = 3;
+	}
+	else if (_wo[68]) {
+		_indoorList._swl_1F1R._frame = 27;
+	}
+
+	if (_wo[28]) {
+	}
+	else if (_wo[105] || _wo[25] || _wo[165] || _wo[125] || _wo[185] || _wo[145]) {
+		_indoorList._fwl_1F1L._frame = 0;
+		_indoorList._fwl_1F1L._sprites = &map._wallSprites._fwl1;
+	}
+	else if (_wo[69]) {
+		_indoorList._fwl_1F1L._frame = 9;
+		_indoorList._fwl_1F1L._sprites = &map._wallSprites._fwl2;
+	}
+
+	if (_wo[29]) {
+	}
+	else if (_wo[106] || _wo[26] || _wo[166] || _wo[126] || _wo[186] || _wo[146]) {
+		_indoorList._fwl_1F._frame = 0;
+		_indoorList._fwl_1F._sprites = &map._wallSprites._fwl1;
+	}
+	else if (_wo[70]) {
+		_indoorList._fwl_1F._frame = 9;
+		_indoorList._fwl_1F._sprites = &map._wallSprites._fwl2;
+	}
+
+	if (_wo[107]) {
+		_indoorList._fwl_1F1R._sprites = &map._wallSprites._fwl2;
+		if (_vm->_openDoor)
+			_indoorList._fwl_1F1R._frame = 0;
+		else
+			_indoorList._fwl_1F1R._frame = map.mazeData()._wallKind ? 1 : 10;
+	}
+	else if (_wo[71]) {
+		_indoorList._fwl_1F1R._frame = 9;
+		_indoorList._fwl_1F1R._sprites = &map._wallSprites._fwl2;
+	}
+	else if (_wo[167]) {
+		_indoorList._fwl_1F1R._frame = _overallFrame + 1;
+		_indoorList._fwl_1F1R._sprites = &map._wallSprites._fwl2;
+	}
+	else if (_wo[127]) {
+		_indoorList._fwl_1F1R._frame = 1;
+		_indoorList._fwl_1F1R._sprites = &map._wallSprites._fwl2;
+	}
+	else if (_wo[147]) {
+		_indoorList._fwl_1F1R._frame = 2;
+		_indoorList._fwl_1F1R._sprites = &map._wallSprites._fwl2;
+	}
+	else if (_wo[187]) {
+		_indoorList._fwl_1F1R._frame = 3;
+		_indoorList._fwl_1F1R._sprites = &map._wallSprites._fwl2;
+	}
+	else if (_wo[27]) {
+		_indoorList._fwl_1F1R._frame = 0;
+		_indoorList._fwl_1F1R._sprites = &map._wallSprites._fwl1;
+	}
+	else if (_wo[207]) {
+		_indoorList._fwl_1F1R._frame = 8;
+		_indoorList._fwl_1F1R._sprites = &map._wallSprites._fwl2;
+	}
+	else if (_wo[227]) {
+		_indoorList._fwl_1F1R._frame = 7;
+		_indoorList._fwl_1F1R._sprites = &map._wallSprites._fwl2;
+	}
+	else if (_wo[247]) {
+		_indoorList._fwl_1F1R._frame = 6;
+		_indoorList._fwl_1F1R._sprites = &map._wallSprites._fwl1;
+	}
+	else if (_wo[267]) {
+		_indoorList._fwl_1F1R._frame = 4;
+		_indoorList._fwl_1F1R._sprites = &map._wallSprites._fwl2;
+	}
+	else if (_wo[287]) {
+		_indoorList._fwl_1F1R._frame = 5;
+		_indoorList._fwl_1F1R._sprites = &map._wallSprites._fwl2;
+	}
+	else if (_wo[307]) {
+		_indoorList._fwl_1F1R._frame = 6;
+		_indoorList._fwl_1F1R._sprites = &map._wallSprites._fwl2;
+	}
+
+	if (_wo[28]) {
+		_indoorList._swl_0F1L._frame = 0;
+	}
+	else if (_wo[72]) {
+		_indoorList._swl_0F1L._frame = 24;
+	}
+
+	if (_wo[29]) {
+		_indoorList._swl_0F1R._frame = 1;
+	}
+	else if (_wo[73]) {
+		_indoorList._swl_0F1R._frame = 25;
+	}
+
+	map.cellFlagLookup(_vm->_party._mazePosition);
+
+	// WORKAROUND: Original did an array lookup on _skySprites.
+	// Was this a feature for multiple skys that was abandoned?
+	_indoorList[0]._sprites = &map._skySprites;
+	_indoorList[0]._flags = _flipSky ? SPRFLAG_HORIZ_FLIPPED : 0;
+
+	if (_vm->_openDoor) {
+		Common::Point pt(
+			_vm->_party._mazePosition.x + SCREEN_POSITIONING_X[
+				_vm->_party._mazeDirection][_vm->_party._mazePosition.x],
+			_vm->_party._mazePosition.y + SCREEN_POSITIONING_Y[
+				_vm->_party._mazeDirection][_vm->_party._mazePosition.y]
+			);
+		map.cellFlagLookup(pt);
+		
+		_indoorList._sky._sprites = &map._skySprites;
+	} else {
+		_indoorList._sky._sprites = _indoorList[0]._sprites;
+	}
+
+	_indoorList._sky._flags = _flipSky ? SPRFLAG_HORIZ_FLIPPED : 0;
+	_indoorList._ground._flags = _flipGround ? SPRFLAG_HORIZ_FLIPPED : 0;
+	_indoorList._horizon._frame = 7;
+
+	// Finally draw the darn indoor scene
+	_vm->_screen->_windows[3].drawList(&_indoorList[0], _indoorList.size());
+
+	// Check for any character shooting
+	_isShooting = false;
+	for (int i = 0; i < _vm->_party._partyCount; ++i) {
+		if (_vm->_combat->_shooting[i])
+			_isShooting = true;
+	}
 	
+	_charsShooting = _isShooting;
 
 	// TODO
 }
diff --git a/engines/xeen/interface.h b/engines/xeen/interface.h
index 43b1f31..f84885f 100644
--- a/engines/xeen/interface.h
+++ b/engines/xeen/interface.h
@@ -117,6 +117,8 @@ private:
 	int _intrIndex1;
 	bool _flipWtr;
 	bool _flipWall;
+	bool _flipSky;
+	bool _flipGround;
 	bool _flag1;
 	int _animCounter;
 	bool _isAnimReset;
@@ -127,6 +129,7 @@ private:
 	byte _wo[308];
 	bool _thinWall;
 	int _overallFrame;
+	bool _isShooting;
 
 	void loadSprites();
 
diff --git a/engines/xeen/map.cpp b/engines/xeen/map.cpp
index 3650c9d..e410333 100644
--- a/engines/xeen/map.cpp
+++ b/engines/xeen/map.cpp
@@ -861,7 +861,7 @@ Map::Map(XeenEngine *vm) : _vm(vm), _mobData(vm) {
 	_currentCantRest = false;
 	_currentIsDrain = false;
 	_currentIsEvent = false;
-	_currentIsObject = false;
+	_currentSky = false;
 	_currentMonsterFlags = 0;
 }
 
@@ -1330,7 +1330,7 @@ void Map::cellFlagLookup(const Common::Point &pt) {
 	_currentCantRest = cell._flags & FLAG_WATER;
 	_currentIsDrain = cell._flags & OUTFLAG_DRAIN;
 	_currentIsEvent = cell._flags & FLAG_AUTOEXECUTE_EVENT;
-	_currentIsObject = cell._flags & OUTFLAG_OBJECT_EXISTS;
+	_currentSky = cell._flags & OUTFLAG_OBJECT_EXISTS;
 	_currentMonsterFlags = cell._flags & 7;
 }
 
diff --git a/engines/xeen/map.h b/engines/xeen/map.h
index d68bc2b..faffe97 100644
--- a/engines/xeen/map.h
+++ b/engines/xeen/map.h
@@ -362,8 +362,6 @@ private:
 	bool _currentSteppedOn;
 
 	void loadEvents(int mapId);
-
-	void cellFlagLookup(const Common::Point &pt);
 public:
 	bool _isOutdoors;
 	MonsterObjectData _mobData;
@@ -380,7 +378,7 @@ public:
 	bool _currentCantRest;
 	bool _currentIsDrain;
 	bool _currentIsEvent;
-	bool _currentIsObject;
+	bool _currentSky;
 	int _currentMonsterFlags;
 	MazeWallLayers _currentWall;
 	int _currentTile;
@@ -392,6 +390,8 @@ public:
 
 	int mazeLookup(const Common::Point &pt, int directionLayerIndex);
 
+	void cellFlagLookup(const Common::Point &pt);
+
 	void setCellSurfaceFlags(const Common::Point &pt, int bits);
 
 	void saveMaze();
diff --git a/engines/xeen/screen.cpp b/engines/xeen/screen.cpp
index cfde780..783f1ff 100644
--- a/engines/xeen/screen.cpp
+++ b/engines/xeen/screen.cpp
@@ -170,7 +170,7 @@ void Window::drawList(DrawStruct *items, int count) {
 	Screen &screen = *_vm->_screen;
 
 	for (int i = 0; i < count; ++i, ++items) {
-		if (items->_frame == -1 || items->_scale == -1)
+		if (items->_frame == -1 || items->_scale == -1 || items->_sprites == nullptr)
 			continue;
 
 		Common::Rect bounds = _innerBounds;
diff --git a/engines/xeen/xeen.cpp b/engines/xeen/xeen.cpp
index c749129..b3758b5 100644
--- a/engines/xeen/xeen.cpp
+++ b/engines/xeen/xeen.cpp
@@ -54,6 +54,7 @@ XeenEngine::XeenEngine(OSystem *syst, const XeenGameDescription *gameDesc)
 	_falling = 0;
 	_moveMonsters = false;
 	_mode = MODE_0;
+	_openDoor = 0;
 }
 
 XeenEngine::~XeenEngine() {
diff --git a/engines/xeen/xeen.h b/engines/xeen/xeen.h
index 5927977..e6bcd8c 100644
--- a/engines/xeen/xeen.h
+++ b/engines/xeen/xeen.h
@@ -146,6 +146,7 @@ public:
 	bool _noDirectionSense;
 	int _falling;
 	bool _moveMonsters;
+	int _openDoor;
 public:
 	XeenEngine(OSystem *syst, const XeenGameDescription *gameDesc);
 	virtual ~XeenEngine();


Commit: e6383519a167eebdbf5877e81c2e9e32e6a101a3
    https://github.com/scummvm/scummvm/commit/e6383519a167eebdbf5877e81c2e9e32e6a101a3
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-01-14T20:39:56-05:00

Commit Message:
XEEN: Split in-game scene draw code into a separate file

Changed paths:
  A engines/xeen/interface_map.cpp
  A engines/xeen/interface_map.h
    engines/xeen/interface.cpp
    engines/xeen/interface.h
    engines/xeen/module.mk



diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp
index ec66434..deb8761 100644
--- a/engines/xeen/interface.cpp
+++ b/engines/xeen/interface.cpp
@@ -27,340 +27,7 @@
 
 namespace Xeen {
 
-OutdoorDrawList::OutdoorDrawList() : _skySprite(_data[1]), _groundSprite(_data[2]) {
-	_data[0] = DrawStruct(0, 8, 8);
-	_data[1] = DrawStruct(1, 8, 25);
-	_data[2] = DrawStruct(0, 8, 67);
-	_data[3] = DrawStruct(0, 8, 67);
-	_data[4] = DrawStruct(0, 38, 67);
-	_data[5] = DrawStruct(0, 84, 67);
-	_data[6] = DrawStruct(0, 134, 67);
-	_data[7] = DrawStruct(0, 117, 67);
-	_data[8] = DrawStruct(0, 117, 67);
-	_data[9] = DrawStruct(0, 103, 67);
-	_data[10] = DrawStruct(0, 8, 73);
-	_data[11] = DrawStruct(0, 8, 73);
-	_data[12] = DrawStruct(0, 30, 73);
-	_data[13] = DrawStruct(0, 181, 73);
-	_data[14] = DrawStruct(0, 154, 73);
-	_data[15] = DrawStruct(0, 129, 73);
-	_data[16] = DrawStruct(0, 87, 73);
-	_data[17] = DrawStruct(0, 8, 81);
-	_data[18] = DrawStruct(0, 8, 81);
-	_data[19] = DrawStruct(0, 202, 81);
-	_data[20] = DrawStruct(0, 145, 81);
-	_data[21] = DrawStruct(0, 63, 81);
-	_data[22] = DrawStruct(0, 8, 93);
-	_data[23] = DrawStruct(0, 169, 93);
-	_data[24] = DrawStruct(0, 31, 93);
-	_data[25] = DrawStruct(0, 8, 109);
-	_data[26] = DrawStruct(0, 201, 109);
-	_data[27] = DrawStruct(0, 8, 109);
-	_data[28] = DrawStruct(1, 65472, 61, 14, SPRFLAG_2000);
-	_data[29] = DrawStruct(1, 65496, 61, 14, 0);
-	_data[30] = DrawStruct(1, 65520, 61, 14, 0);
-	_data[31] = DrawStruct(1, 8, 61, 14, 0);
-	_data[32] = DrawStruct(1, 128, 61, 14, SPRFLAG_HORIZ_FLIPPED | SPRFLAG_2000);
-	_data[33] = DrawStruct(1, 104, 61, 14, SPRFLAG_HORIZ_FLIPPED);
-	_data[34] = DrawStruct(1, 80, 61, 14, SPRFLAG_HORIZ_FLIPPED);
-	_data[35] = DrawStruct(1, 56, 61, 14, SPRFLAG_HORIZ_FLIPPED);
-	_data[36] = DrawStruct(1, 32, 61, 14, 0);
-	_data[37] = DrawStruct(0, 65527, 61, 14, 0);
-	_data[38] = DrawStruct(0, 65478, 61, 14, 0);
-	_data[39] = DrawStruct(0, 40, 61, 14, 0);
-	_data[40] = DrawStruct(0, 65454, 61, 14, 0);
-	_data[41] = DrawStruct(0, 64, 61, 14, 0);
-	_data[42] = DrawStruct(0, 65495, 61, 14, 0);
-	_data[43] = DrawStruct(0, 65510, 61, 14, 0);
-	_data[44] = DrawStruct(0, 65502, 61, 14, 0);
-	_data[45] = DrawStruct(0, 65520, 61, 14, 0);
-	_data[46] = DrawStruct(0, 23, 61, 14, 0);
-	_data[47] = DrawStruct(0, 16, 61, 14, 0);
-	_data[48] = DrawStruct(0, 65478, 61, 14, 0);
-	_data[49] = DrawStruct(0, 40, 61, 14, 0);
-	_data[50] = DrawStruct(0, 65519, 61, 14, 0);
-	_data[51] = DrawStruct(0, 65535, 58, 14, 0);
-	_data[52] = DrawStruct(0, 65527, 58, 14, 0);
-	_data[53] = DrawStruct(0, 72, 58, 12, 0);
-	_data[54] = DrawStruct(0, 72, 58, 12, SPRFLAG_HORIZ_FLIPPED);
-	_data[55] = DrawStruct(0, 69, 63, 12, 0);
-	_data[56] = DrawStruct(0, 75, 63, 12, SPRFLAG_HORIZ_FLIPPED);
-	_data[57] = DrawStruct(0, 73, 53, 12, 0);
-	_data[58] = DrawStruct(0, 71, 53, 12, SPRFLAG_HORIZ_FLIPPED);
-	_data[59] = DrawStruct(0, 80, 57, 12, 0);
-	_data[60] = DrawStruct(0, 64, 57, 12, SPRFLAG_HORIZ_FLIPPED);
-	_data[61] = DrawStruct(2, 65525, 54, 8, 0);
-	_data[62] = DrawStruct(1, 65515, 54, 11, 0);
-	_data[63] = DrawStruct(2, 165, 54, 8, SPRFLAG_HORIZ_FLIPPED);
-	_data[64] = DrawStruct(1, 86, 54, 11, SPRFLAG_HORIZ_FLIPPED);
-	_data[65] = DrawStruct(1, 33, 54, 11, 0);
-	_data[66] = DrawStruct(0, 65528, 54, 12, 0);
-	_data[67] = DrawStruct(0, 65463, 54, 12, 0);
-	_data[68] = DrawStruct(0, 57, 54, 12, 0);
-	_data[69] = DrawStruct(0, 65471, 54, 12, 0);
-	_data[70] = DrawStruct(0, 65455, 54, 12, 0);
-	_data[71] = DrawStruct(0, 49, 54, 12, 0);
-	_data[72] = DrawStruct(0, 65, 54, 12, 0);
-	_data[73] = DrawStruct(0, 65512, 54, 12, 0);
-	_data[74] = DrawStruct(0, 9, 50, 12, 0);
-	_data[75] = DrawStruct(0, 65528, 50, 12, 0);
-	_data[76] = DrawStruct(0, 72, 53, 8, 0);
-	_data[77] = DrawStruct(0, 72, 53, 8, SPRFLAG_HORIZ_FLIPPED);
-	_data[78] = DrawStruct(0, 77, 58, 8, 0);
-	_data[79] = DrawStruct(0, 67, 58, 8, SPRFLAG_HORIZ_FLIPPED);
-	_data[80] = DrawStruct(0, 81, 47, 8, 0);
-	_data[81] = DrawStruct(0, 63, 47, 8, SPRFLAG_HORIZ_FLIPPED);
-	_data[82] = DrawStruct(0, 94, 52, 8, 0);
-	_data[83] = DrawStruct(0, 50, 52, 8, SPRFLAG_HORIZ_FLIPPED);
-	_data[84] = DrawStruct(2, 8, 40);
-	_data[85] = DrawStruct(2, 146, 40, 0, SPRFLAG_HORIZ_FLIPPED);
-	_data[86] = DrawStruct(1, 32, 40, 6, 0);
-	_data[87] = DrawStruct(0, 65529, 30, 7, 0);
-	_data[88] = DrawStruct(0, 65424, 30, 7, SPRFLAG_2000);
-	_data[89] = DrawStruct(0, 98, 30, 7, SPRFLAG_2000);
-	_data[90] = DrawStruct(0, 65424, 30, 8, SPRFLAG_2000);
-	_data[91] = DrawStruct(0, 98, 30, 8, SPRFLAG_2000);
-	_data[92] = DrawStruct(0, 65498, 30, 8, 0);
-	_data[93] = DrawStruct(0, 25, 30, 8, 0);
-	_data[94] = DrawStruct(0, 65529, 30, 8, 0);
-	_data[95] = DrawStruct(0, 72, 48, 4, 0);
-	_data[96] = DrawStruct(0, 72, 48, 4, SPRFLAG_HORIZ_FLIPPED);
-	_data[97] = DrawStruct(0, 85, 53, 4, 0);
-	_data[98] = DrawStruct(0, 59, 53, 4, SPRFLAG_HORIZ_FLIPPED);
-	_data[99] = DrawStruct(0, 89, 41, 4, 0);
-	_data[100] = DrawStruct(0, 55, 41, 4, SPRFLAG_HORIZ_FLIPPED);
-	_data[101] = DrawStruct(0, 106, 47, 4, 0);
-	_data[102] = DrawStruct(0, 38, 47, 4, SPRFLAG_HORIZ_FLIPPED);
-	_data[103] = DrawStruct(0, 8, 24);
-	_data[104] = DrawStruct(0, 169, 24, 0, SPRFLAG_HORIZ_FLIPPED);
-	_data[105] = DrawStruct(1, 32, 24);
-	_data[106] = DrawStruct(0, 65513, 40, 0, SPRFLAG_2000);
-	_data[107] = DrawStruct(0, 200, 40, 0, SPRFLAG_HORIZ_FLIPPED | SPRFLAG_2000);
-	_data[108] = DrawStruct(0, 8, 47);
-	_data[109] = DrawStruct(0, 169, 47, 0, SPRFLAG_HORIZ_FLIPPED);
-	_data[110] = DrawStruct(1, 65480, 65532, 32768, SPRFLAG_4000 | SPRFLAG_2000);
-	_data[111] = DrawStruct(0, 65531, 2, 0, SPRFLAG_4000 | SPRFLAG_2000);
-	_data[112] = DrawStruct(0, 65469, 2, 0, SPRFLAG_4000 | SPRFLAG_2000);
-	_data[113] = DrawStruct(0, 44, 73);
-	_data[114] = DrawStruct(0, 44, 73);
-	_data[115] = DrawStruct(0, 58, 14, 0, SPRFLAG_4000 | SPRFLAG_2000);
-	_data[116] = DrawStruct(0, 169, 73);
-	_data[117] = DrawStruct(0, 169, 73);
-	_data[118] = DrawStruct(0, 65531, 14, 0, SPRFLAG_4000 | SPRFLAG_2000);
-	_data[119] = DrawStruct(0, 110, 73);
-	_data[120] = DrawStruct(0, 110, 73);
-	_data[121] = DrawStruct(0, 65531, 14, 0, SPRFLAG_4000 | SPRFLAG_2000);
-	_data[122] = DrawStruct(0, 110, 73);
-	_data[123] = DrawStruct(0, 110, 73);
-	_data[124] = DrawStruct(0, 72, 43);
-	_data[125] = DrawStruct(0, 72, 43, 0, SPRFLAG_HORIZ_FLIPPED);
-	_data[126] = DrawStruct(0, 93, 48);
-	_data[127] = DrawStruct(0, 51, 48, 0, SPRFLAG_HORIZ_FLIPPED);
-	_data[128] = DrawStruct(0, 97, 36);
-	_data[129] = DrawStruct(0, 47, 36, 0, SPRFLAG_HORIZ_FLIPPED);
-	_data[130] = DrawStruct(0, 118, 42);
-	_data[131] = DrawStruct(0, 26, 42, 0, SPRFLAG_HORIZ_FLIPPED);
-}
-
-/*------------------------------------------------------------------------*/
-
-IndoorDrawList::IndoorDrawList() : 
-	_sky(_data[1]), _ground(_data[2]), _horizon(_data[28]),
-	_swl_0F1R(_data[ 46]), _swl_0F1L(_data[44]),  _swl_1F1R(_data[134]), 
-	_swl_1F1L(_data[133]), _swl_2F2R(_data[110]), _swl_2F1R(_data[109]), 
-	_swl_2F1L(_data[108]), _swl_2F2L(_data[107]), _swl_3F1R(_data[ 78]), 
-	_swl_3F2R(_data[ 77]), _swl_3F3R(_data[ 76]), _swl_3F4R(_data[ 75]),
-	_swl_3F1L(_data[ 74]), _swl_3F2L(_data[ 73]), _swl_3F3L(_data[ 72]), 
-	_swl_3F4L(_data[ 71]), _swl_4F4R(_data[ 33]), _swl_4F3R(_data[ 34]), 
-	_swl_4F2R(_data[ 35]), _swl_4F1R(_data[ 36]), _swl_4F1L(_data[ 32]),
-	_swl_4F2L(_data[ 31]), _swl_4F3L(_data[ 30]), _swl_4F4L(_data[ 29]),
-	_fwl_4F4R(_data[ 45]), _fwl_4F3R(_data[ 44]), _fwl_4F2R(_data[ 43]), 
-	_fwl_4F1R(_data[ 42]), _fwl_4F(  _data[ 41]), _fwl_4F1L(_data[ 40]), 
-	_fwl_4F2L(_data[ 39]), _fwl_4F3L(_data[ 38]), _fwl_4F4L(_data[ 37]),
-	_fwl_2F1R(_data[121]), _fwl_2F(  _data[120]), _fwl_2F1L(_data[119]), 
-	_fwl_3F2R(_data[ 91]), _fwl_3F1R(_data[ 90]), _fwl_3F(  _data[ 89]), 
-	_fwl_3F1L(_data[ 88]), _fwl_3F2L(_data[ 87]), _fwl_1F(  _data[147]),
-	_fwl_1F1R(_data[145]), _fwl_1F1L(_data[143]),
-	_objects0(_data[149]), _objects1(_data[125]), _objects2(_data[126]),
-	_objects3(_data[127]), _objects4(_data[97]), _objects5(_data[98]),
-	_objects6(_data[99]), _objects7(_data[55]), _objects8(_data[56]),
-	_objects9(_data[58]), _objects10(_data[57]), _objects11(_data[59]) {
-	// Setup draw structure positions
-	_data[0] = DrawStruct(0, 8, 8);
-	_data[1] = DrawStruct(1, 8, 25);
-	_data[2] = DrawStruct(0, 8, 67);
-	_data[3] = DrawStruct(0, 8, 67);
-	_data[4] = DrawStruct(0, 38, 67);
-	_data[5] = DrawStruct(0, 84, 67);
-	_data[6] = DrawStruct(0, 134, 67);
-	_data[7] = DrawStruct(0, 117, 67);
-	_data[8] = DrawStruct(0, 117, 67);
-	_data[9] = DrawStruct(0, 103, 67);
-	_data[10] = DrawStruct(0, 8, 73);
-	_data[11] = DrawStruct(0, 8, 73);
-	_data[12] = DrawStruct(0, 30, 73);
-	_data[13] = DrawStruct(0, 181, 73);
-	_data[14] = DrawStruct(0, 154, 73);
-	_data[15] = DrawStruct(0, 129, 73);
-	_data[16] = DrawStruct(0, 87, 73);
-	_data[17] = DrawStruct(0, 8, 81);
-	_data[18] = DrawStruct(0, 8, 81);
-	_data[19] = DrawStruct(0, 202, 81);
-	_data[20] = DrawStruct(0, 145, 81);
-	_data[21] = DrawStruct(0, 63, 81);
-	_data[22] = DrawStruct(0, 8, 93);
-	_data[23] = DrawStruct(0, 169, 93);
-	_data[24] = DrawStruct(0, 31, 93);
-	_data[25] = DrawStruct(0, 8, 109);
-	_data[26] = DrawStruct(0, 201, 109);
-	_data[27] = DrawStruct(0, 8, 109);
-	_data[28] = DrawStruct(7, 8, 64);
-	_data[29] = DrawStruct(22, 32, 60);
-	_data[30] = DrawStruct(20, 56, 60);
-	_data[31] = DrawStruct(18, 80, 60);
-	_data[32] = DrawStruct(16, 104, 60);
-	_data[33] = DrawStruct(23, 152, 60, 0, SPRFLAG_HORIZ_FLIPPED);
-	_data[34] = DrawStruct(21, 144, 60, 0, SPRFLAG_HORIZ_FLIPPED);
-	_data[35] = DrawStruct(19, 131, 60, 0, SPRFLAG_HORIZ_FLIPPED);
-	_data[36] = DrawStruct(17, 120, 60, 0, SPRFLAG_HORIZ_FLIPPED);
-	_data[37] = DrawStruct(14, 8, 60);
-	_data[38] = DrawStruct(12, 32, 60);
-	_data[39] = DrawStruct(10, 56, 60);
-	_data[40] = DrawStruct(14, 80, 60);
-	_data[41] = DrawStruct(14, 104, 60);
-	_data[42] = DrawStruct(14, 128, 60);
-	_data[43] = DrawStruct(14, 152, 60);
-	_data[44] = DrawStruct(8, 176, 60);
-	_data[45] = DrawStruct(8, 200, 60);
-	_data[46] = DrawStruct(0, 65472, 61, 14, 0);
-	_data[47] = DrawStruct(0, 65496, 61, 14, 0);
-	_data[48] = DrawStruct(0, 65520, 61, 14, 0);
-	_data[49] = DrawStruct(0, 8, 61, 14, 0);
-	_data[50] = DrawStruct(0, 32, 61, 14, 0);
-	_data[51] = DrawStruct(0, 56, 61, 14, 0);
-	_data[52] = DrawStruct(0, 80, 61, 14, 0);
-	_data[53] = DrawStruct(0, 104, 61, 14, 0);
-	_data[54] = DrawStruct(0, 128, 61, 14, 0);
-	_data[55] = DrawStruct(0, 65527, 58, 14, 0);
-	_data[56] = DrawStruct(0, 65502, 58, 14, 0);
-	_data[57] = DrawStruct(0, 16, 58, 14, 0);
-	_data[58] = DrawStruct(0, 65478, 58, 14, 0);
-	_data[59] = DrawStruct(0, 40, 58, 14, 0);
-	_data[60] = DrawStruct(0, 65495, 58, 14, 0);
-	_data[61] = DrawStruct(0, 65510, 58, 14, 0);
-	_data[62] = DrawStruct(0, 65502, 58, 14, 0);
-	_data[63] = DrawStruct(0, 65520, 58, 14, 0);
-	_data[64] = DrawStruct(0, 23, 58, 14, 0);
-	_data[65] = DrawStruct(0, 16, 58, 14, 0);
-	_data[66] = DrawStruct(0, 65478, 58, 14, 0);
-	_data[67] = DrawStruct(0, 40, 58, 14, 0);
-	_data[68] = DrawStruct(0, 65519, 58, 14, 0);
-	_data[69] = DrawStruct(0, 65535, 58, 14, 0);
-	_data[70] = DrawStruct(0, 65527, 58, 14, 0);
-	_data[71] = DrawStruct(14, 8, 58);
-	_data[72] = DrawStruct(12, 8, 55);
-	_data[73] = DrawStruct(10, 32, 52);
-	_data[74] = DrawStruct(14, 88, 52);
-	_data[75] = DrawStruct(14, 128, 52, 0, SPRFLAG_HORIZ_FLIPPED);
-	_data[76] = DrawStruct(14, 152, 52, 0, SPRFLAG_HORIZ_FLIPPED);
-	_data[77] = DrawStruct(0, 176, 55, 0, SPRFLAG_HORIZ_FLIPPED);
-	_data[78] = DrawStruct(0, 200, 58, 0, SPRFLAG_HORIZ_FLIPPED);
-	_data[79] = DrawStruct(0, 72, 58, 12, 0);
-	_data[80] = DrawStruct(0, 72, 58, 12, SPRFLAG_HORIZ_FLIPPED);
-	_data[81] = DrawStruct(0, 69, 63, 12, 0);
-	_data[82] = DrawStruct(0, 75, 63, 12, SPRFLAG_HORIZ_FLIPPED);
-	_data[83] = DrawStruct(0, 73, 53, 12, 0);
-	_data[84] = DrawStruct(0, 71, 53, 12, SPRFLAG_HORIZ_FLIPPED);
-	_data[85] = DrawStruct(0, 80, 57, 12, 0);
-	_data[86] = DrawStruct(0, 64, 57, 12, SPRFLAG_HORIZ_FLIPPED);
-	_data[87] = DrawStruct(7, 65512, 52, 0, SPRFLAG_2000);
-	_data[88] = DrawStruct(7, 32, 52);
-	_data[89] = DrawStruct(7, 88, 52);
-	_data[90] = DrawStruct(0, 144, 52);
-	_data[91] = DrawStruct(0, 200, 52, 0, SPRFLAG_2000);
-	_data[92] = DrawStruct(0, 65457, 52, 11, SPRFLAG_2000);
-	_data[93] = DrawStruct(0, 65509, 52, 11, 0);
-	_data[94] = DrawStruct(0, 32, 52, 11, 0);
-	_data[95] = DrawStruct(0, 89, 52, 11, 0);
-	_data[96] = DrawStruct(0, 145, 52, 11, SPRFLAG_2000);
-	_data[97] = DrawStruct(0, 65528, 50, 12, 0);
-	_data[98] = DrawStruct(0, 65471, 50, 12, 0);
-	_data[99] = DrawStruct(0, 49, 50, 12, 0);
-	_data[100] = DrawStruct(0, 65471, 50, 12, 0);
-	_data[101] = DrawStruct(0, 65455, 50, 12, 0);
-	_data[102] = DrawStruct(0, 49, 50, 12, 0);
-	_data[103] = DrawStruct(0, 65, 50, 12, 0);
-	_data[104] = DrawStruct(0, 65512, 50, 12, 0);
-	_data[105] = DrawStruct(0, 9, 50, 12, 0);
-	_data[106] = DrawStruct(0, 65528, 50, 12, 0);
-	_data[107] = DrawStruct(7, 8, 48);
-	_data[108] = DrawStruct(7, 64, 40);
-	_data[109] = DrawStruct(6, 144, 40, 0, SPRFLAG_HORIZ_FLIPPED);
-	_data[110] = DrawStruct(6, 200, 48, 0, SPRFLAG_HORIZ_FLIPPED);
-	_data[111] = DrawStruct(0, 72, 53, 8, 0);
-	_data[112] = DrawStruct(0, 72, 53, 8, SPRFLAG_HORIZ_FLIPPED);
-	_data[113] = DrawStruct(0, 77, 58, 8, 0);
-	_data[114] = DrawStruct(0, 67, 58, 8, SPRFLAG_HORIZ_FLIPPED);
-	_data[115] = DrawStruct(0, 81, 47, 8, 0);
-	_data[116] = DrawStruct(0, 63, 47, 8, SPRFLAG_HORIZ_FLIPPED);
-	_data[117] = DrawStruct(0, 94, 52, 8, 0);
-	_data[118] = DrawStruct(0, 50, 52, 8, SPRFLAG_HORIZ_FLIPPED);
-	_data[119] = DrawStruct(6, 65496, 40, 0, SPRFLAG_2000);
-	_data[120] = DrawStruct(6, 64, 40);
-	_data[121] = DrawStruct(0, 168, 40, 0, SPRFLAG_2000);
-	_data[122] = DrawStruct(0, 65464, 40, 6, SPRFLAG_2000);
-	_data[123] = DrawStruct(0, 32, 40, 6, 0);
-	_data[124] = DrawStruct(0, 137, 40, 6, SPRFLAG_2000);
-	_data[125] = DrawStruct(0, 65529, 25, 7, 0);
-	_data[126] = DrawStruct(0, 65424, 25, 7, SPRFLAG_2000);
-	_data[127] = DrawStruct(0, 98, 25, 7, SPRFLAG_2000);
-	_data[128] = DrawStruct(0, 65424, 29, 8, SPRFLAG_2000);
-	_data[129] = DrawStruct(0, 98, 29, 8, SPRFLAG_2000);
-	_data[130] = DrawStruct(0, 65498, 29, 8, 0);
-	_data[131] = DrawStruct(0, 25, 29, 8, 0);
-	_data[132] = DrawStruct(0, 65529, 29, 8, 0);
-	_data[133] = DrawStruct(6, 32, 24);
-	_data[134] = DrawStruct(0, 168, 24, 0, SPRFLAG_HORIZ_FLIPPED);
-	_data[135] = DrawStruct(0, 72, 48, 4, 0);
-	_data[136] = DrawStruct(0, 72, 48, 4, SPRFLAG_HORIZ_FLIPPED);
-	_data[137] = DrawStruct(0, 85, 53, 4, 0);
-	_data[138] = DrawStruct(0, 59, 53, 4, SPRFLAG_HORIZ_FLIPPED);
-	_data[139] = DrawStruct(0, 89, 41, 4, 0);
-	_data[140] = DrawStruct(0, 55, 41, 4, SPRFLAG_HORIZ_FLIPPED);
-	_data[141] = DrawStruct(0, 106, 47, 4, 0);
-	_data[142] = DrawStruct(0, 38, 47, 4, SPRFLAG_HORIZ_FLIPPED);
-	_data[143] = DrawStruct(0, 65400, 24, 0, SPRFLAG_2000);
-	_data[144] = DrawStruct(0, 8, 12);
-	_data[145] = DrawStruct(0, 32, 24);
-	_data[146] = DrawStruct(0, 200, 12, 0, SPRFLAG_HORIZ_FLIPPED);
-	_data[147] = DrawStruct(0, 200, 24, 0, SPRFLAG_2000);
-	_data[148] = DrawStruct(0, 32, 24);
-	_data[149] = DrawStruct(0, 65531, 2, 0, SPRFLAG_4000 | SPRFLAG_2000);
-	_data[150] = DrawStruct(0, 65469, 10, 0, SPRFLAG_4000 | SPRFLAG_2000);
-	_data[151] = DrawStruct(0, 44, 73);
-	_data[152] = DrawStruct(0, 44, 73);
-	_data[153] = DrawStruct(0, 58, 14, 0, SPRFLAG_4000 | SPRFLAG_2000);
-	_data[154] = DrawStruct(0, 169, 73);
-	_data[155] = DrawStruct(0, 169, 73);
-	_data[156] = DrawStruct(0, 65531, 14, 0, SPRFLAG_4000 | SPRFLAG_2000);
-	_data[157] = DrawStruct(0, 110, 73);
-	_data[158] = DrawStruct(0, 110, 73);
-	_data[159] = DrawStruct(0, 65531, 14, 0, SPRFLAG_4000 | SPRFLAG_2000);
-	_data[160] = DrawStruct(0, 110, 73);
-	_data[161] = DrawStruct(0, 110, 73);
-	_data[162] = DrawStruct(0, 72, 43);
-	_data[163] = DrawStruct(0, 72, 43, 0, SPRFLAG_HORIZ_FLIPPED);
-	_data[164] = DrawStruct(0, 93, 48);
-	_data[165] = DrawStruct(0, 51, 48, 0, SPRFLAG_HORIZ_FLIPPED);
-	_data[166] = DrawStruct(0, 97, 36);
-	_data[167] = DrawStruct(0, 47, 36, 0, SPRFLAG_HORIZ_FLIPPED);
-	_data[168] = DrawStruct(0, 118, 42);
-	_data[169] = DrawStruct(0, 26, 42, 0, SPRFLAG_HORIZ_FLIPPED);
-}
-
-/*------------------------------------------------------------------------*/
-
-Interface::Interface(XeenEngine *vm) : ButtonContainer(), _vm(vm) {
+Interface::Interface(XeenEngine *vm) : ButtonContainer(), InterfaceMap(vm), _vm(vm) {
 	Common::fill(&_partyFaces[0], &_partyFaces[MAX_ACTIVE_PARTY], nullptr);
 	_batUIFrame = 0;
 	_spotDoorsUIFrame = 0;
@@ -376,27 +43,18 @@ Interface::Interface(XeenEngine *vm) : ButtonContainer(), _vm(vm) {
 	_buttonsLoaded = false;
 	_hiliteChar = -1;
 	_intrIndex1 = 0;
-	_flipWtr = false;
-	_flipWall = false;
-	_flipSky = false;
-	_flipGround = false;
 	_flag1 = false;
 	_animCounter = 0;
 	_isAnimReset = false;
-	_charsShooting = false;
 	_tillMove = 0;
-	_objNumber = 0;
 	_thinWall = false;
 	_overallFrame = 0;
-	_isShooting = false;
 
 	Common::fill(&_combatCharIds[0], &_combatCharIds[8], 0);
-	Common::fill(&_wp[0], &_wp[20], 0);
-	Common::fill(&_wo[0], &_wo[308], 0);
-
 	initDrawStructs();
 }
 
+
 void Interface::initDrawStructs() {
 	_faceDrawStructs[0] = DrawStruct(0, 0, 0);
 	_faceDrawStructs[1] = DrawStruct(0, 101, 0);
@@ -963,8 +621,8 @@ void Interface::draw3d(bool updateFlag) {
 		const int INDOOR_COMBAT_POS[3][2] = { { 102, 134 }, { 36, 67 }, { 161, 161 } };
 		const int INDOOR_COMBAT_POS2[4] = { 8, 6, 4, 2 };
 
-		// TODO: Double check this, since it's not being used?
-		MazeObject &objObject = map._mobData._objects[_objNumber - 1];
+		// Double check this, since it's not being used?
+		//MazeObject &objObject = map._mobData._objects[_objNumber - 1];
 
 		for (int idx = 0; idx < 3; ++idx) {
 			DrawStruct &ds1 = _indoorList[INDOOR_INDEXES[idx]];
@@ -1091,201 +749,6 @@ void Interface::animate3d() {
 
 }
 
-void Interface::setIndoorsMonsters() {
-
-}
-
-void Interface::setIndoorObjects() {
-	Common::Point mazePos = _vm->_party._mazePosition;
-	_objNumber = 0;
-	const int8 *posOffset = &SCREEN_POSITIONING_X[_vm->_party._mazeDirection][0];
-	Common::Point pt;
-
-	Common::Array<MazeObject> &objects = _vm->_map->_mobData._objects;
-	for (uint idx = 0; idx < objects.size(); ++idx) {
-		MazeObject &mazeObject = objects[idx];
-
-		// Determine which half of the X/Y lists to use
-		int listOffset;
-		if (_vm->_files->_isDarkCc) {
-			listOffset = mazeObject._spriteId == 47 ? 1 : 0;
-		}
-		else {
-			listOffset = mazeObject._spriteId == 113 ? 1 : 0;
-		}
-
-		// Position 1
-		pt = Common::Point(mazePos.x + posOffset[2], mazePos.y + posOffset[194]);
-		if (pt == mazeObject._position && _indoorList._objects0._frame == -1) {
-			_indoorList._objects0._x = INDOOR_OBJECT_X[listOffset][0];
-			_indoorList._objects0._y = INDOOR_OBJECT_Y[listOffset][0];
-			_indoorList._objects0._frame = mazeObject._frame;
-			_indoorList._objects0._sprites = mazeObject._sprites;
-			_indoorList._objects0._flags &= ~SPRFLAG_HORIZ_FLIPPED;
-			if (mazeObject._flipped)
-				_indoorList._objects0._flags |= SPRFLAG_HORIZ_FLIPPED;
-			_objNumber = idx;
-		}
-
-		// Position 2
-		pt = Common::Point(mazePos.x + posOffset[7], mazePos.y + posOffset[199]);
-		if (pt == mazeObject._position && !_wo[27] && _indoorList._objects1._frame == -1) {
-			_indoorList._objects1._x = INDOOR_OBJECT_X[listOffset][1];
-			_indoorList._objects1._y = INDOOR_OBJECT_Y[listOffset][1];
-			_indoorList._objects1._frame = mazeObject._frame;
-			_indoorList._objects1._sprites = mazeObject._sprites;
-			_indoorList._objects1._flags &= ~SPRFLAG_HORIZ_FLIPPED;
-			if (mazeObject._flipped)
-				_indoorList._objects1._flags |= SPRFLAG_HORIZ_FLIPPED;
-		}
-
-		// Position 3
-		pt = Common::Point(mazePos.x + posOffset[5], mazePos.y + posOffset[197]);
-		if (pt == mazeObject._position && (!_wo[27] || !_wo[25]) && (!_wo[27] || !_wo[28]) &&
-				(!_wo[23] || !_wo[25]) && (!_wo[23] || !_wo[28]) && 
-				_indoorList._objects2._frame == -1) {
-			_indoorList._objects2._x = INDOOR_OBJECT_X[listOffset][2];
-			_indoorList._objects2._y = INDOOR_OBJECT_Y[listOffset][2];
-			_indoorList._objects2._frame = mazeObject._frame;
-			_indoorList._objects2._sprites = mazeObject._sprites;
-			_indoorList._objects2._flags &= ~SPRFLAG_HORIZ_FLIPPED;
-			if (mazeObject._flipped)
-				_indoorList._objects2._flags |= SPRFLAG_HORIZ_FLIPPED;
-		}
-
-		// Position 4
-		pt = Common::Point(mazePos.x + posOffset[9], mazePos.y + posOffset[201]);
-		if (pt == mazeObject._position && (!_wo[27] || !_wo[26]) && (!_wo[27] || !_wo[29]) &&
-				(!_wo[24] || !_wo[26]) && (!_wo[24] || !_wo[29]) && _indoorList._objects3._frame == -1) {
-			_indoorList._objects3._x = INDOOR_OBJECT_X[listOffset][3];
-			_indoorList._objects3._y = INDOOR_OBJECT_Y[listOffset][3];
-			_indoorList._objects3._frame = mazeObject._frame;
-			_indoorList._objects3._sprites = mazeObject._sprites;
-			_indoorList._objects3._flags &= ~SPRFLAG_HORIZ_FLIPPED;
-			if (mazeObject._flipped)
-				_indoorList._objects3._flags |= SPRFLAG_HORIZ_FLIPPED;
-		}
-
-		// Position 5
-		pt = Common::Point(mazePos.x + posOffset[14], mazePos.y + posOffset[206]);
-		if (pt == mazeObject._position && !_wo[22] && !_wo[27] && _indoorList._objects4._frame == -1) {
-			_indoorList._objects4._x = INDOOR_OBJECT_X[listOffset][4];
-			_indoorList._objects4._y = INDOOR_OBJECT_Y[listOffset][4];
-			_indoorList._objects4._frame = mazeObject._frame;
-			_indoorList._objects4._sprites = mazeObject._sprites;
-			_indoorList._objects4._flags &= ~SPRFLAG_HORIZ_FLIPPED;
-			if (mazeObject._flipped)
-				_indoorList._objects4._flags |= SPRFLAG_HORIZ_FLIPPED;
-		}
-
-		// Position 6
-		pt = Common::Point(mazePos.x + posOffset[12], mazePos.y + posOffset[204]);
-		if (pt == mazeObject._position && !_wo[27] && (!_wo[22] || !_wo[23]) && (!_wo[22] || !_wo[20]) &&
-				(!_wo[23] || !_wo[17]) && (!_wo[20] || !_wo[17]) && _indoorList._objects5._frame == -1) {
-			_indoorList._objects5._x = INDOOR_OBJECT_X[listOffset][5];
-			_indoorList._objects5._y = INDOOR_OBJECT_Y[listOffset][5];
-			_indoorList._objects5._frame = mazeObject._frame;
-			_indoorList._objects5._sprites = mazeObject._sprites;
-			_indoorList._objects5._flags &= ~SPRFLAG_HORIZ_FLIPPED;
-			if (mazeObject._flipped)
-				_indoorList._objects5._flags |= SPRFLAG_HORIZ_FLIPPED;
-		}
-
-		// Position 7
-		pt = Common::Point(mazePos.x + posOffset[16], mazePos.y + posOffset[208]);
-		if (pt == mazeObject._position && !_wo[27] && (!_wo[22] || !_wo[24]) && (!_wo[22] || !_wo[21]) &&
-			(!_wo[24] || !_wo[19]) && (!_wo[21] || !_wo[19]) && _indoorList._objects6._frame == -1) {
-			_indoorList._objects6._x = INDOOR_OBJECT_X[listOffset][6];
-			_indoorList._objects6._y = INDOOR_OBJECT_Y[listOffset][6];
-			_indoorList._objects6._frame = mazeObject._frame;
-			_indoorList._objects6._sprites = mazeObject._sprites;
-			_indoorList._objects6._flags &= ~SPRFLAG_HORIZ_FLIPPED;
-			if (mazeObject._flipped)
-				_indoorList._objects6._flags |= SPRFLAG_HORIZ_FLIPPED;
-		}
-
-		// Position 8
-		pt = Common::Point(mazePos.x + posOffset[27], mazePos.y + posOffset[219]);
-		if (pt == mazeObject._position && !_wo[27] && !_wo[22] && !_wo[15] &&  _indoorList._objects7._frame == -1) {
-			_indoorList._objects7._x = INDOOR_OBJECT_X[listOffset][7];
-			_indoorList._objects7._y = INDOOR_OBJECT_Y[listOffset][7];
-			_indoorList._objects7._frame = mazeObject._frame;
-			_indoorList._objects7._sprites = mazeObject._sprites;
-			_indoorList._objects7._flags &= ~SPRFLAG_HORIZ_FLIPPED;
-			if (mazeObject._flipped)
-				_indoorList._objects7._flags |= SPRFLAG_HORIZ_FLIPPED;
-		}
-
-		// Position 9
-		pt = Common::Point(mazePos.x + posOffset[25], mazePos.y + posOffset[217]);
-		if (pt == mazeObject._position && !_wo[27] && (!_wo[15] || !_wo[17]) && (!_wo[15] || !_wo[12]) &&
-				(!_wo[12] || !_wo[7]) && (!_wo[17] || !_wo[7]) && _indoorList._objects5._frame == -1) {
-			_indoorList._objects8._x = INDOOR_OBJECT_X[listOffset][8];
-			_indoorList._objects8._y = INDOOR_OBJECT_Y[listOffset][8];
-			_indoorList._objects8._frame = mazeObject._frame;
-			_indoorList._objects8._sprites = mazeObject._sprites;
-			_indoorList._objects8._flags &= ~SPRFLAG_HORIZ_FLIPPED;
-			if (mazeObject._flipped)
-				_indoorList._objects8._flags |= SPRFLAG_HORIZ_FLIPPED;
-		}
-
-		// Position 10
-		pt = Common::Point(mazePos.x + posOffset[23], mazePos.y + posOffset[215]);
-		if (pt == mazeObject._position && !_wo[27] && (!_wo[22] || !_wo[20]) && (!_wo[22] || !_wo[23]) &&
-				(!_wo[20] || !_wo[17]) && (!_wo[23] || !_wo[17]) && !_wo[12] && !_wo[8] &&			
-				_indoorList._objects9._frame == -1) {
-			_indoorList._objects9._x = INDOOR_OBJECT_X[listOffset][9];
-			_indoorList._objects9._y = INDOOR_OBJECT_Y[listOffset][9];
-			_indoorList._objects9._frame = mazeObject._frame;
-			_indoorList._objects9._sprites = mazeObject._sprites;
-			_indoorList._objects9._flags &= ~SPRFLAG_HORIZ_FLIPPED;
-			if (mazeObject._flipped)
-				_indoorList._objects9._flags |= SPRFLAG_HORIZ_FLIPPED;
-		}
-
-		// Block 11
-		pt = Common::Point(mazePos.x + posOffset[29], mazePos.y + posOffset[221]);
-		if (pt == mazeObject._position && !_wo[27] && !_wo[22] && (!_wo[15] || !_wo[19]) && 
-				(!_wo[15] || !_wo[14]) && (!_wo[14] || !_wo[9]) && (!_wo[19] || !_wo[9]) && 
-				_indoorList._objects10._frame == -1) {
-			_indoorList._objects10._x = INDOOR_OBJECT_X[listOffset][10];
-			_indoorList._objects10._y = INDOOR_OBJECT_Y[listOffset][10];
-			_indoorList._objects10._frame = mazeObject._frame;
-			_indoorList._objects10._sprites = mazeObject._sprites;
-			_indoorList._objects10._flags &= ~SPRFLAG_HORIZ_FLIPPED;
-			if (mazeObject._flipped)
-				_indoorList._objects10._flags |= SPRFLAG_HORIZ_FLIPPED;
-		}
-
-		// Block 12
-		pt = Common::Point(mazePos.x + posOffset[31], mazePos.y + posOffset[223]);
-		if (pt == mazeObject._position && !_wo[27] && (!_wo[22] || !_wo[21]) && (!_wo[22] || !_wo[24]) && 
-				(!_wo[21] || !_wo[19]) && (!_wo[24] || !_wo[19]) && !_wo[14] && !_wo[10] &&
-				_indoorList._objects11._frame == -1) {
-			_indoorList._objects11._x = INDOOR_OBJECT_X[listOffset][11];
-			_indoorList._objects11._y = INDOOR_OBJECT_Y[listOffset][11];
-			_indoorList._objects11._frame = mazeObject._frame;
-			_indoorList._objects11._sprites = mazeObject._sprites;
-			_indoorList._objects11._flags &= ~SPRFLAG_HORIZ_FLIPPED;
-			if (mazeObject._flipped)
-				_indoorList._objects11._flags |= SPRFLAG_HORIZ_FLIPPED;
-		}
-	}
-}
-
-void Interface::setIndoorWallPics() {
-	// TODO
-}
-
-
-void Interface::setOutdoorsMonsters() {
-
-}
-
-void Interface::setOutdoorsObjects() {
-
-}
-
 void Interface::startup() {
 	Screen &screen = *_vm->_screen;
 	loadCharIcons();
@@ -2845,1140 +2308,6 @@ void Interface::setMazeBits() {
 	}
 }
 
-void Interface::drawIndoors() {
-	Map &map = *_vm->_map;
-	int surfaceId;
-	int idx;
-
-	for (int cellIndex = 0; cellIndex < 25; ++cellIndex) {
-		map.getCell(DRAW_NUMBERS[cellIndex]);
-
-		DrawStruct &drawStruct = _indoorList[3 + cellIndex];
-		drawStruct._sprites = &map._surfaceSprites[map._currentSurfaceId];
-
-		surfaceId = map.mazeData()._surfaceTypes[map._currentSurfaceId];
-		if (surfaceId == 5 || surfaceId == 12) {
-			drawStruct._flags = _flipWtr;
-			drawStruct._frame = DRAW_FRAMES[cellIndex][_flipWtr ? 1 : 0];
-		}
-		else {
-			drawStruct._frame = DRAW_FRAMES[cellIndex][_flipWall ? 1 : 0];
-			drawStruct._flags = _flipWall ? 0 : SPRFLAG_HORIZ_FLIPPED;
-		}
-	}
-
-	if (!_wo[27] && !_wo[20] && !_wo[23] && !_wo[12] && !_wo[8] && !_wo[30]) {
-		if (_wo[39])
-			_indoorList._swl_4F4L._frame = 22;
-		else if (_wo[83])
-			_indoorList._swl_4F4L._frame = 46;
-	}
-
-	if (!_wo[27] && !_wo[22] && !_wo[17] && !_wo[12] && !_wo[8]) {
-		if (_wo[38])
-			_indoorList._swl_4F3L._frame = 20;
-		else if (_wo[82])
-			_indoorList._swl_4F3L._frame = 44;
-	}
-
-	if (!_wo[27] && !_wo[22] && !_wo[15] && !_wo[2] && !_wo[7]) {
-		if (_wo[37])
-			_indoorList._swl_4F2L._frame = 18;
-		else if (_wo[81])
-			_indoorList._swl_4F2L._frame = 42;
-	}
-
-	if (!_wo[27] && !_wo[22] && !_wo[15] && !_wo[6]) {
-		if (_wo[36])
-			_indoorList._swl_4F1L._frame = 16;
-		else if (_wo[80])
-			_indoorList._swl_4F1L._frame = 40;
-	}
-
-	if (!_wo[27] && !_wo[21] && !_wo[24] && !_wo[14] && !_wo[10] && !_wo[31]) {
-		if (_wo[43])
-			_indoorList._swl_4F4R._frame = 23;
-		else if (_wo[87])
-			_indoorList._swl_4F4R._frame = 47;
-	}
-
-	if (!_wo[27] && !_wo[22] && !_wo[19] && !_wo[14] && !_wo[10]) {
-		if (_wo[42])
-			_indoorList._swl_4F3R._frame = 21;
-		else if (_wo[86])
-			_indoorList._swl_4F3R._frame = 45;
-	}
-
-	if (!_wo[27] && !_wo[22] && !_wo[15] && !_wo[5] && !_wo[9]) {
-		if (_wo[41])
-			_indoorList._swl_4F2R._frame = 19;
-		else if (_wo[85])
-			_indoorList._swl_4F2R._frame = 43;
-	}
-
-	if (!_wo[27] && !_wo[22] && !_wo[15] && !_wo[6]) {
-		if (_wo[40])
-			_indoorList._swl_4F1R._frame = 17;
-		else if (_wo[84])
-			_indoorList._swl_4F1R._frame = 41;
-	}
-
-	if (!_wo[25] && !_wo[28] && !_wo[20] && !_wo[11] &&
-		!_wo[16] && !_wo[30] && !_wo[32]) {
-		if (_wo[88])
-			_indoorList._fwl_4F4L._frame = 7;
-		else if (_wo[78])
-			_indoorList._fwl_4F4L._frame = 16;
-		else if (_wo[148])
-			_indoorList._fwl_4F4L._frame = _overallFrame + 1;
-		else if (_wo[108])
-			_indoorList._fwl_4F4L._frame = 8;
-		else if (_wo[168])
-			_indoorList._fwl_4F4L._frame = 10;
-		else if (_wo[128])
-			_indoorList._fwl_4F4L._frame = 9;
-		else if (_wo[34])
-			_indoorList._fwl_4F4L._frame = 0;
-		else if (_wo[188])
-			_indoorList._fwl_4F4L._frame = 15;
-		else if (_wo[208])
-			_indoorList._fwl_4F4L._frame = 14;
-		else if (_wo[228])
-			_indoorList._fwl_4F4L._frame = 6;
-		else if (_wo[248])
-			_indoorList._fwl_4F4L._frame = 11;
-		else if (_wo[268])
-			_indoorList._fwl_4F4L._frame = 12;
-		else if (_wo[288])
-			_indoorList._fwl_4F4L._frame = 13;
-	}
-
-	if (!_wo[26] && !_wo[29] && !_wo[21] && !_wo[13] && !_wo[18] && !_wo[31] && !_wo[33]) {
-		if (_wo[93])
-			_indoorList._fwl_4F4R._frame = 7;
-		else if (_wo[79])
-			_indoorList._fwl_4F4R._frame = 16;
-		else if (_wo[153])
-			_indoorList._fwl_4F4R._frame = _overallFrame + 1;
-		else if (_wo[113])
-			_indoorList._fwl_4F4R._frame = 8;
-		else if (_wo[173])
-			_indoorList._fwl_4F4R._frame = 10;
-		else if (_wo[133])
-			_indoorList._fwl_4F4R._frame = 9;
-		else if (_wo[35])
-			_indoorList._fwl_4F4R._frame = 0;
-		else if (_wo[79])
-			_indoorList._fwl_4F4R._frame = 15;
-		else if (_wo[213])
-			_indoorList._fwl_4F4R._frame = 14;
-		else if (_wo[233])
-			_indoorList._fwl_4F4R._frame = 6;
-		else if (_wo[253])
-			_indoorList._fwl_4F4R._frame = 11;
-		else if (_wo[273])
-			_indoorList._fwl_4F4R._frame = 12;
-		else if (_wo[293])
-			_indoorList._fwl_4F4R._frame = 13;
-	}
-
-	if (!_wo[25] && !_wo[28] && !_wo[20] && !_wo[11] && !_wo[16] && !_wo[30]) {
-		if (_wo[32])
-			_indoorList._swl_3F4L._frame = 14;
-		else if (_wo[76])
-			_indoorList._swl_3F4L._frame = 38;
-	}
-
-	if (!_wo[26] && !_wo[29] && !_wo[21] && !_wo[13] && !_wo[18] && !_wo[31]) {
-		if (_wo[33])
-			_indoorList._fwl_3F1R._frame = 15;
-		else if (_wo[77])
-			_indoorList._swl_3F1R._frame = 39;
-	}
-
-	if (_wo[28] && _wo[27]) {
-	}
-	else if (_wo[28] && _wo[12]) {
-	}
-	else if (_wo[28] && _wo[23]) {
-	}
-	else if (_wo[28] && _wo[8]) {
-	}
-	else if (_wo[25] && _wo[27]) {
-	}
-	else if (_wo[25] && _wo[12]) {
-	}
-	else if (_wo[25] && _wo[23]) {
-	}
-	else if (_wo[25] && _wo[8]) {
-	}
-	else if (_wo[11] && _wo[27]) {
-	}
-	else if (_wo[11] && _wo[12]) {
-	}
-	else if (_wo[11] && _wo[23]) {
-	}
-	else if (_wo[11] && _wo[8]) {
-	}
-	else if (_wo[17] && _wo[27]) {
-	}
-	else if (_wo[17] && _wo[12]) {
-	}
-	else if (_wo[17] && _wo[23]) {
-	}
-	else if (_wo[17] && _wo[8]) {
-	}
-	else if (_wo[20]) {
-	}
-	else if (_wo[30]) {
-		_indoorList._swl_3F3L._frame = 12;
-	}
-	else if (_wo[74]) {
-		_indoorList._swl_3F3L._frame = 36;
-	}
-
-	if (_wo[29] && _wo[27]) {
-	}
-	else if (_wo[29] && _wo[14]) {
-	}
-	else if (_wo[29] && _wo[24]) {
-	}
-	else if (_wo[29] && _wo[10]) {
-	}
-	else if (_wo[26] && _wo[27]) {
-	}
-	else if (_wo[26] && _wo[14]) {
-	}
-	else if (_wo[26] && _wo[24]) {
-	}
-	else if (_wo[26] && _wo[10]) {
-	}
-	else if (_wo[13] && _wo[27]) {
-	}
-	else if (_wo[13] && _wo[14]) {
-	}
-	else if (_wo[13] && _wo[24]) {
-	}
-	else if (_wo[13] && _wo[10]) {
-	}
-	else if (_wo[19] && _wo[27]) {
-	}
-	else if (_wo[19] && _wo[24]) {
-	}
-	else if (_wo[19] && _wo[10]) {
-	}
-	else if (_wo[21]) {
-	}
-	else if (_wo[31]) {
-		_indoorList._swl_3F2R._frame = 13;
-	}
-	else if (_wo[75]) {
-		_indoorList._swl_3F2R._frame = 37;
-	}
-
-	if (!_wo[27] && !_wo[20] && !_wo[12] && !_wo[23] && !_wo[8] && !_wo[30]) {
-		if (_wo[89])
-			_indoorList._fwl_4F3L._frame = 7;
-		else if (_wo[44])
-			_indoorList._fwl_4F3L._frame = 16;
-		else if (_wo[149])
-			_indoorList._fwl_4F3L._frame = _overallFrame + 1;
-		else if (_wo[109])
-			_indoorList._fwl_4F3L._frame = 8;
-		else if (_wo[169])
-			_indoorList._fwl_4F3L._frame = 10;
-		else if (_wo[129])
-			_indoorList._fwl_4F3L._frame = 9;
-		else if (_wo[0])
-			_indoorList._fwl_4F3L._frame = 0;
-		else if (_wo[189])
-			_indoorList._fwl_4F3L._frame = 15;
-		else if (_wo[209])
-			_indoorList._fwl_4F3L._frame = 14;
-		else if (_wo[229])
-			_indoorList._fwl_4F3L._frame = 6;
-		else if (_wo[249])
-			_indoorList._fwl_4F3L._frame = 11;
-		else if (_wo[269])
-			_indoorList._fwl_4F3L._frame = 12;
-		else if (_wo[289])
-			_indoorList._fwl_4F3L._frame = 13;
-	}
-
-	if (_wo[22] && _wo[20]) {
-	}
-	else if (_wo[22] && _wo[23]) {
-	}
-	else if (_wo[20] && _wo[17]) {
-	}
-	else if (_wo[23] && _wo[17]) {
-	}
-	else if (_wo[12]) {
-	}
-	else if (_wo[8]) {
-	}
-	else if (_wo[90]) {
-		_indoorList._fwl_4F2L._frame = 7;
-	}
-	else if (_wo[45])  {
-		_indoorList._fwl_4F2L._frame = 16;
-	}
-	else if (_wo[150]) {
-		_indoorList._fwl_4F2L._frame = _overallFrame + 1;
-	}
-	else if (_wo[110]) {
-		_indoorList._fwl_4F2L._frame = 8;
-	}
-	else if (_wo[170]) {
-		_indoorList._fwl_4F2L._frame = 10;
-	}
-	else if (_wo[130]) {
-		_indoorList._fwl_4F2L._frame = 9;
-	}
-	else if (_wo[1]) {
-		_indoorList._fwl_4F2L._frame = 0;
-	}
-	else if (_wo[190]) {
-		_indoorList._fwl_4F2L._frame = 15;
-	}
-	else if (_wo[210]) {
-		_indoorList._fwl_4F2L._frame = 14;
-	}
-	else if (_wo[230]) {
-		_indoorList._fwl_4F2L._frame = 6;
-	}
-	else if (_wo[250]) {
-		_indoorList._fwl_4F2L._frame = 11;
-	}
-	else if (_wo[270]) {
-		_indoorList._fwl_4F2L._frame = 12;
-	}
-	else if (_wo[290]) {
-		_indoorList._fwl_4F2L._frame = 13;
-	}
-
-	if (_wo[15] && _wo[17]) {
-	}
-	else if (_wo[15] && _wo[12]) {
-	}
-	else if (_wo[12] && _wo[7]) {
-	}
-	else if (_wo[17] && _wo[7]) {
-	}
-	else if (_wo[91]) {
-		_indoorList._fwl_4F1L._frame = 7;
-	}
-	else if (_wo[46]) {
-		_indoorList._fwl_4F1L._frame = 16;
-	}
-	else if (_wo[151]) {
-		_indoorList._fwl_4F1L._frame = _overallFrame + 1;
-	}
-	else if (_wo[111]) {
-		_indoorList._fwl_4F1L._frame = 8;
-	}
-	else if (_wo[171]) {
-		_indoorList._fwl_4F1L._frame = 10;
-	}
-	else if (_wo[131]) {
-		_indoorList._fwl_4F1L._frame = 9;
-	}
-	else if (_wo[2]) {
-		_indoorList._fwl_4F1L._frame = 0;
-	}
-	else if (_wo[191]) {
-		_indoorList._fwl_4F1L._frame = 15;
-	}
-	else if (_wo[211]) {
-		_indoorList._fwl_4F1L._frame = 14;
-	}
-	else if (_wo[231]) {
-		_indoorList._fwl_4F1L._frame = 6;
-	}
-	else if (_wo[251]) {
-		_indoorList._fwl_4F1L._frame = 11;
-	}
-	else if (_wo[271]) {
-		_indoorList._fwl_4F1L._frame = 12;
-	}
-	else if (_wo[291]) {
-		_indoorList._fwl_4F1L._frame = 13;
-	}
-
-	if (!_wo[27] && !_wo[21] && !_wo[14] && !_wo[24] && !_wo[10] && !_wo[31]) {
-		if (_wo[92]) {
-			_indoorList._fwl_4F3R._frame = 7;
-		}
-		else if (_wo[47]) {
-			_indoorList._fwl_4F3R._frame = 16;
-		}
-		else if (_wo[152]) {
-			_indoorList._fwl_4F3R._frame = _overallFrame + 1;
-		}
-		else if (_wo[112]) {
-			_indoorList._fwl_4F3R._frame = 8;
-		}
-		else if (_wo[172]) {
-			_indoorList._fwl_4F3R._frame = 10;
-		}
-		else if (_wo[132]) {
-			_indoorList._fwl_4F3R._frame = 9;
-		}
-		else if (_wo[3]) {
-			_indoorList._fwl_4F3R._frame = 0;
-		}
-		else if (_wo[192]) {
-			_indoorList._fwl_4F3R._frame = 15;
-		}
-		else if (_wo[212]) {
-			_indoorList._fwl_4F3R._frame = 14;
-		}
-		else if (_wo[232]) {
-			_indoorList._fwl_4F3R._frame = 6;
-		}
-		else if (_wo[252]) {
-			_indoorList._fwl_4F3R._frame = 11;
-		}
-		else if (_wo[272]) {
-			_indoorList._fwl_4F3R._frame = 12;
-		}
-		else if (_wo[292]) {
-			_indoorList._fwl_4F3R._frame = 13;
-		}
-	}
-
-	if (_wo[22] && _wo[21]) {
-	}
-	else if (_wo[22] && _wo[24]) {
-	}
-	else if (_wo[21] && _wo[19]) {
-	}
-	else if (_wo[24] && _wo[19]) {
-	}
-	else if (_wo[14] || _wo[10]) {
-	}
-	else if (_wo[94]) {
-		_indoorList._fwl_4F2R._frame = 7;
-	}
-	else if (_wo[48]) {
-		_indoorList._fwl_4F2R._frame = 16;
-	}
-	else if (_wo[154]) {
-		_indoorList._fwl_4F2R._frame = _overallFrame + 1;
-	}
-	else if (_wo[114]) {
-		_indoorList._fwl_4F2R._frame = 8;
-	}
-	else if (_wo[174]) {
-		_indoorList._fwl_4F2R._frame = 10;
-	}
-	else if (_wo[134]) {
-		_indoorList._fwl_4F2R._frame = 9;
-	}
-	else if (_wo[4]) {
-		_indoorList._fwl_4F2R._frame = 0;
-	}
-	else if (_wo[194]) {
-		_indoorList._fwl_4F2R._frame = 15;
-	}
-	else if (_wo[214]) {
-		_indoorList._fwl_4F2R._frame = 14;
-	}
-	else if (_wo[234]) {
-		_indoorList._fwl_4F2R._frame = 6;
-	}
-	else if (_wo[254]) {
-		_indoorList._fwl_4F2R._frame = 11;
-	}
-	else if (_wo[274]) {
-		_indoorList._fwl_4F2R._frame = 12;
-	}
-	else if (_wo[294]) {
-		_indoorList._fwl_4F2R._frame = 13;
-	}
-
-	if (_wo[15] && _wo[19]) {
-	}
-	else if (_wo[15] && _wo[14]) {
-	}
-	else if (_wo[14] && _wo[9]) {
-	}
-	else if (_wo[19] && _wo[9]) {
-	}
-	else if (_wo[95]) {
-		_indoorList._fwl_4F1R._frame = 7;
-	}
-	else if (_wo[49]) {
-		_indoorList._fwl_4F1R._frame = 16;
-	}
-	else if (_wo[155]) {
-		_indoorList._fwl_4F1R._frame = _overallFrame + 1;
-	}
-	else if (_wo[115]) {
-		_indoorList._fwl_4F1R._frame = 8;
-	}
-	else if (_wo[175]) {
-		_indoorList._fwl_4F1R._frame = 10;
-	}
-	else if (_wo[135]) {
-		_indoorList._fwl_4F1R._frame = 9;
-	}
-	else if (_wo[5]) {
-		_indoorList._fwl_4F1R._frame = 0;
-	}
-	else if (_wo[195]) {
-		_indoorList._fwl_4F1R._frame = 15;
-	}
-	else if (_wo[215]) {
-		_indoorList._fwl_4F1R._frame = 14;
-	}
-	else if (_wo[235]) {
-		_indoorList._fwl_4F1R._frame = 6;
-	}
-	else if (_wo[255]) {
-		_indoorList._fwl_4F1R._frame = 11;
-	}
-	else if (_wo[275]) {
-		_indoorList._fwl_4F1R._frame = 12;
-	}
-	else if (_wo[295]) {
-		_indoorList._fwl_4F1R._frame = 13;
-	}
-
-	if (_wo[27] || _wo[22] || _wo[15] || _wo[96]) {
-	}
-	else if (_wo[50]) {
-		_indoorList._fwl_4F._frame = 16;
-	}
-	else if (_wo[156]) {
-		_indoorList._fwl_4F._frame = _overallFrame + 1;
-	}
-	else if (_wo[116]) {
-		_indoorList._fwl_4F._frame = 8;
-	}
-	else if (_wo[176]) {
-		_indoorList._fwl_4F._frame = 10;
-	}
-	else if (_wo[136]) {
-		_indoorList._fwl_4F._frame = 9;
-	}
-	else if (_wo[6]) {
-		_indoorList._fwl_4F._frame = 0;
-	}
-	else if (_wo[196]) {
-		_indoorList._fwl_4F._frame = 15;
-	}
-	else if (_wo[216]) {
-		_indoorList._fwl_4F._frame = 14;
-	}
-	else if (_wo[236]) {
-		_indoorList._fwl_4F._frame = 6;
-	}
-	else if (_wo[256]) {
-		_indoorList._fwl_4F._frame = 11;
-	}
-	else if (_wo[276]) {
-		_indoorList._fwl_4F._frame = 12;
-	}
-	else if (_wo[296]) {
-		_indoorList._fwl_4F._frame = 13;
-	}
-
-	if (!_wo[27] && !_wo[22] && !_wo[15]) {
-		if (_wo[7])
-			_indoorList._swl_3F1L._frame = 8;
-		else if (_wo[51])
-			_indoorList._swl_3F1L._frame = 32;
-	}
-
-	if (_wo[22] && _wo[23]) {
-	}
-	else if (_wo[22] && _wo[20]) {
-	}
-	else if (_wo[17] && _wo[23]) {
-	}
-	else if (_wo[17] && _wo[20]) {
-	}
-	else if (_wo[8]) {
-		_indoorList._swl_3F2L._frame = 10;
-	}
-	else if (_wo[52]) {
-		_indoorList._swl_3F2L._frame = 34;
-	}
-
-	if (_wo[27] || _wo[22] || _wo[15]) {
-	}
-	else if (_wo[9]) {
-		_indoorList._swl_3F4R._frame = 9;
-	}
-	else if (_wo[53]) {
-		_indoorList._swl_3F4R._frame = 33;
-	}
-
-	if (_wo[22] && _wo[24]) {
-	}
-	else if (_wo[22] && _wo[21]) {
-	}
-	else if (_wo[19] && _wo[24]) {
-	}
-	else if (_wo[19] && _wo[21]) {
-	}
-	else if (_wo[14]) {
-	}
-	else if (_wo[10]) {
-		_indoorList._swl_3F3R._frame = 11;
-	}
-	else if (_wo[54]) {
-		_indoorList._swl_3F3R._frame = 35;
-	}
-
-	if (_wo[25] || _wo[28] || _wo[20] || _wo[16]) {
-	}
-	else if (_wo[97]) {
-		_indoorList._fwl_3F2L._frame = 24;
-	}
-	else if (_wo[55]) {
-		_indoorList._fwl_3F2L._frame = 33;
-	}
-	else if (_wo[137]) {
-		_indoorList._fwl_3F2L._frame = 26;
-	}
-	else if (_wo[157]) {
-		_indoorList._fwl_3F2L._frame = _overallFrame + 18;
-	}
-	else if (_wo[117]) {
-		_indoorList._fwl_3F2L._frame = 25;
-	}
-	else if (_wo[177]) {
-		_indoorList._fwl_3F2L._frame = 27;
-	}
-	else if (_wo[11]) {
-		_indoorList._fwl_3F2L._frame = 17;
-	}
-	else if (_wo[197]) {
-		_indoorList._fwl_3F2L._frame = 32;
-	}
-	else if (_wo[217]) {
-		_indoorList._fwl_3F2L._frame = 31;
-	}
-	else if (_wo[237]) {
-		_indoorList._fwl_3F2L._frame = 23;
-	}
-	else if (_wo[257]) {
-		_indoorList._fwl_3F2L._frame = 28;
-	}
-	else if (_wo[277]) {
-		_indoorList._fwl_3F2L._frame = 29;
-	}
-	else if (_wo[297]) {
-		_indoorList._fwl_3F2L._frame = 30;
-	}
-
-	if (_wo[22] && _wo[23]) {
-	}
-	else if (_wo[22] && _wo[20]) {
-	}
-	else if (_wo[23] && _wo[17]) {
-	}
-	else if (_wo[20] && _wo[17]) {
-	}
-	else if (_wo[98]) {
-		_indoorList._fwl_3F1L._frame = 24;
-	}
-	else if (_wo[56]) {
-		_indoorList._fwl_3F1L._frame = 33;
-	}
-	else if (_wo[178]) {
-		_indoorList._fwl_3F1L._frame = 27;
-	}
-	else if (_wo[118]) {
-		_indoorList._fwl_3F1L._frame = 25;
-	}
-	else if (_wo[158]) {
-		_indoorList._fwl_3F1L._frame = _overallFrame + 18;
-	}
-	else if (_wo[138]) {
-		_indoorList._fwl_3F1L._frame = 26;
-	}
-	else if (_wo[12]) {
-		_indoorList._fwl_3F1L._frame = 17;
-	}
-	else if (_wo[198]) {
-		_indoorList._fwl_3F1L._frame = 32;
-	}
-	else if (_wo[218]) {
-		_indoorList._fwl_3F1L._frame = 31;
-	}
-	else if (_wo[238]) {
-		_indoorList._fwl_3F1L._frame = 23;
-	}
-	else if (_wo[258]) {
-		_indoorList._fwl_3F1L._frame = 28;
-	}
-	else if (_wo[278]) {
-		_indoorList._fwl_3F1L._frame = 29;
-	}
-	else if (_wo[298]) {
-		_indoorList._fwl_3F1L._frame = 30;
-	}
-
-	if (_wo[26] || _wo[29] || _wo[21] || _wo[18]) {
-	}
-	else if (_wo[99]) {
-		_indoorList._fwl_3F2R._frame = 24;
-	}
-	else if (_wo[57]) {
-		_indoorList._fwl_3F2R._frame = 33;
-	}
-	else if (_wo[139]) {
-		_indoorList._fwl_3F2R._frame = 26;
-	}
-	else if (_wo[159]) {
-		_indoorList._fwl_3F2R._frame = _overallFrame + 18;
-	}
-	else if (_wo[119]) {
-		_indoorList._fwl_3F2R._frame = 25;
-	}
-	else if (_wo[179]) {
-		_indoorList._fwl_3F2R._frame = 27;
-	}
-	else if (_wo[13]) {
-		_indoorList._fwl_3F2R._frame = 17;
-	}
-	else if (_wo[199]) {
-		_indoorList._fwl_3F2R._frame = 32;
-	}
-	else if (_wo[219]) {
-		_indoorList._fwl_3F2R._frame = 31;
-	}
-	else if (_wo[239]) {
-		_indoorList._fwl_3F2R._frame = 23;
-	}
-	else if (_wo[259]) {
-		_indoorList._fwl_3F2R._frame = 28;
-	}
-	else if (_wo[279]) {
-		_indoorList._fwl_3F2R._frame = 29;
-	}
-	else if (_wo[299]) {
-		_indoorList._fwl_3F2R._frame = 30;
-	}
-
-	if (_wo[22] && _wo[24]) {
-	}
-	else if (_wo[22] && _wo[21]) {
-	}
-	else if (_wo[24] && _wo[19]) {
-	}
-	else if (_wo[21] && _wo[19]) {
-	}
-	else if (_wo[100]) {
-		_indoorList._fwl_3F1R._frame = 24;
-	}
-	else if (_wo[58]) {
-		_indoorList._fwl_3F1R._frame = 33;
-	}
-	else if (_wo[140]) {
-		_indoorList._fwl_3F1R._frame = 26;
-	}
-	else if (_wo[160]) {
-		_indoorList._fwl_3F1R._frame = _overallFrame + 18;
-	}
-	else if (_wo[120]) {
-		_indoorList._fwl_3F1R._frame = 25;
-	}
-	else if (_wo[180]) {
-		_indoorList._fwl_3F1R._frame = 27;
-	}
-	else if (_wo[14]) {
-		_indoorList._fwl_3F1R._frame = 17;
-	}
-	else if (_wo[200]) {
-		_indoorList._fwl_3F1R._frame = 32;
-	}
-	else if (_wo[220]) {
-		_indoorList._fwl_3F1R._frame = 31;
-	}
-	else if (_wo[240]) {
-		_indoorList._fwl_3F1R._frame = 23;
-	}
-	else if (_wo[260]) {
-		_indoorList._fwl_3F1R._frame = 28;
-	}
-	else if (_wo[280]) {
-		_indoorList._fwl_3F1R._frame = 29;
-	}
-	else if (_wo[300]) {
-		_indoorList._fwl_3F1R._frame = 30;
-	}
-
-	if (_wo[22] || _wo[27]) {
-	}
-	else if (_wo[101]) {
-		_indoorList._fwl_3F._frame = 24;
-	}
-	else if (_wo[59]) {
-		_indoorList._fwl_3F._frame = 33;
-	}
-	else if (_wo[141]) {
-		_indoorList._fwl_3F._frame = 26;
-	}
-	else if (_wo[161]) {
-		_indoorList._fwl_3F._frame = _overallFrame + 18;
-	}
-	else if (_wo[121]) {
-		_indoorList._fwl_3F._frame = 25;
-	}
-	else if (_wo[181]) {
-		_indoorList._fwl_3F._frame = 27;
-	}
-	else if (_wo[15]) {
-		_indoorList._fwl_3F._frame = 17;
-	}
-	else if (_wo[201]) {
-		_indoorList._fwl_3F._frame = 32;
-	}
-	else if (_wo[221]) {
-		_indoorList._fwl_3F._frame = 31;
-	}
-	else if (_wo[241]) {
-		_indoorList._fwl_3F._frame = 23;
-	}
-	else if (_wo[261]) {
-		_indoorList._fwl_3F._frame = 28;
-	}
-	else if (_wo[281]) {
-		_indoorList._fwl_3F._frame = 29;
-	}
-	else if (_wo[301]) {
-		_indoorList._fwl_3F._frame = 30;
-	}
-
-	if (_wo[25] || _wo[28] || _wo[20]) {
-	}
-	else if (_wo[16]) {
-		_indoorList._swl_2F2L._frame = 6;
-	}
-	else if (_wo[60]) {
-		_indoorList._swl_2F2L._frame = 30;
-	}
-
-	if (_wo[27] || _wo[22]) {
-	}
-	else if (_wo[17]) {
-		_indoorList._swl_2F1L._frame = 4;
-	}
-	else if (_wo[61]) {
-		_indoorList._swl_2F1L._frame = 28;
-	}
-
-	if (_wo[26] || _wo[29] || _wo[21]) {
-	}
-	else if (_wo[18]) {
-		_indoorList._swl_2F2R._frame = 7;
-	}
-	else if (_wo[62]) {
-		_indoorList._swl_2F2R._frame = 31;
-	}
-
-	if (_wo[27] || _wo[22]) {
-	}
-	else if (_wo[19]) {
-		_indoorList._swl_2F1R._frame = 5;
-	}
-	else if (_wo[63]) {
-		_indoorList._swl_2F1R._frame = 29;
-	}
-
-	if (_wo[27] && _wo[25]) {
-	}
-	else if (_wo[27] && _wo[28]) {
-	}
-	else if (_wo[23] & _wo[25]) {
-	}
-	else if (_wo[23] && _wo[28]) {
-	}
-	else if (_wo[102]) {
-		_indoorList._fwl_2F1L._frame = 7;
-	}
-	else if (_wo[64]) {
-		_indoorList._fwl_2F1L._frame = 16;
-	}
-	else if (_wo[182]) {
-		_indoorList._fwl_2F1L._frame = 10;
-	}
-	else if (_wo[122]) {
-		_indoorList._fwl_2F1L._frame = 8;
-	}
-	else if (_wo[142]) {
-		_indoorList._fwl_2F1L._frame = 9;
-	}
-	else if (_wo[162]) {
-		_indoorList._fwl_2F1L._frame = _overallFrame + 1;
-	}
-	else if (_wo[20]) {
-		_indoorList._fwl_2F1L._frame = 0;
-	}
-	else if (_wo[202]) {
-		_indoorList._fwl_2F1L._frame = 15;
-	}
-	else if (_wo[222]) {
-		_indoorList._fwl_2F1L._frame = 14;
-	}
-	else if (_wo[242]) {
-		_indoorList._fwl_2F1L._frame = 6;
-	}
-	else if (_wo[262]) {
-		_indoorList._fwl_2F1L._frame = 11;
-	}
-	else if (_wo[282]) {
-		_indoorList._fwl_2F1L._frame = 12;
-	}
-	else if (_wo[302]) {
-		_indoorList._fwl_2F1L._frame = 13;
-	}
-
-	if (_wo[27] && _wo[26]) {
-	}
-	else if (_wo[27] && _wo[29]) {
-	}
-	else if (_wo[24] && _wo[26]) {
-	}
-	else if (_wo[24] && _wo[29]) {
-	}
-	else if (_wo[103]) {
-		_indoorList._fwl_2F1R._frame = 7;
-	}
-	else if (_wo[65]) {
-		_indoorList._fwl_2F1R._frame = 16;
-	}
-	else if (_wo[183]) {
-		_indoorList._fwl_2F1R._frame = 10;
-	}
-	else if (_wo[123]) {
-		_indoorList._fwl_2F1R._frame = 8;
-	}
-	else if (_wo[143]) {
-		_indoorList._fwl_2F1R._frame = 9;
-	}
-	else if (_wo[163]) {
-		_indoorList._fwl_2F1R._frame = _overallFrame + 1;
-	}
-	else if (_wo[21]) {
-		_indoorList._fwl_2F1R._frame = 0;
-	}
-	else if (_wo[203]) {
-		_indoorList._fwl_2F1R._frame = 15;
-	}
-	else if (_wo[223]) {
-		_indoorList._fwl_2F1R._frame = 14;
-	}
-	else if (_wo[243]) {
-		_indoorList._fwl_2F1R._frame = 6;
-	}
-	else if (_wo[263]) {
-		_indoorList._fwl_2F1R._frame = 11;
-	}
-	else if (_wo[283]) {
-		_indoorList._fwl_2F1R._frame = 12;
-	}
-	else if (_wo[303]) {
-		_indoorList._fwl_2F1R._frame = 13;
-	}
-
-	if (_wo[27]) {
-
-	}
-	else if (_wo[104]) {
-		_indoorList._fwl_2F._frame = 7;
-	}
-	else if (_wo[66]) {
-		_indoorList._fwl_2F._frame = 16;
-	}
-	else if (_wo[184]) {
-		_indoorList._fwl_2F._frame = 10;
-	}
-	else if (_wo[124]) {
-		_indoorList._fwl_2F._frame = 8;
-	}
-	else if (_wo[144]) {
-		_indoorList._fwl_2F._frame = 9;
-	}
-	else if (_wo[164]) {
-		_indoorList._fwl_2F._frame = _overallFrame + 1;
-	}
-	else if (_wo[22]) {
-		_indoorList._fwl_2F._frame = 0;
-	}
-	else if (_wo[204]) {
-		_indoorList._fwl_2F._frame = 15;
-	}
-	else if (_wo[224]) {
-		_indoorList._fwl_2F._frame = 14;
-	}
-	else if (_wo[244]) {
-		_indoorList._fwl_2F._frame = 6;
-	}
-	else if (_wo[264]) {
-		_indoorList._fwl_2F._frame = 11;
-	}
-	else if (_wo[284]) {
-		_indoorList._fwl_2F._frame = 12;
-	}
-	else if (_wo[304]) {
-		_indoorList._fwl_2F._frame = 13;
-	}
-
-	if (_wo[27]) {
-	}
-	else if (_wo[23]) {
-		_indoorList._swl_1F1L._frame = 2;
-	}
-	else if (_wo[67]) {
-		_indoorList._swl_1F1L._frame = 26;
-	}
-
-	if (_wo[27]) {
-	}
-	else if (_wo[24]) {
-		_indoorList._swl_1F1R._frame = 3;
-	}
-	else if (_wo[68]) {
-		_indoorList._swl_1F1R._frame = 27;
-	}
-
-	if (_wo[28]) {
-	}
-	else if (_wo[105] || _wo[25] || _wo[165] || _wo[125] || _wo[185] || _wo[145]) {
-		_indoorList._fwl_1F1L._frame = 0;
-		_indoorList._fwl_1F1L._sprites = &map._wallSprites._fwl1;
-	}
-	else if (_wo[69]) {
-		_indoorList._fwl_1F1L._frame = 9;
-		_indoorList._fwl_1F1L._sprites = &map._wallSprites._fwl2;
-	}
-
-	if (_wo[29]) {
-	}
-	else if (_wo[106] || _wo[26] || _wo[166] || _wo[126] || _wo[186] || _wo[146]) {
-		_indoorList._fwl_1F._frame = 0;
-		_indoorList._fwl_1F._sprites = &map._wallSprites._fwl1;
-	}
-	else if (_wo[70]) {
-		_indoorList._fwl_1F._frame = 9;
-		_indoorList._fwl_1F._sprites = &map._wallSprites._fwl2;
-	}
-
-	if (_wo[107]) {
-		_indoorList._fwl_1F1R._sprites = &map._wallSprites._fwl2;
-		if (_vm->_openDoor)
-			_indoorList._fwl_1F1R._frame = 0;
-		else
-			_indoorList._fwl_1F1R._frame = map.mazeData()._wallKind ? 1 : 10;
-	}
-	else if (_wo[71]) {
-		_indoorList._fwl_1F1R._frame = 9;
-		_indoorList._fwl_1F1R._sprites = &map._wallSprites._fwl2;
-	}
-	else if (_wo[167]) {
-		_indoorList._fwl_1F1R._frame = _overallFrame + 1;
-		_indoorList._fwl_1F1R._sprites = &map._wallSprites._fwl2;
-	}
-	else if (_wo[127]) {
-		_indoorList._fwl_1F1R._frame = 1;
-		_indoorList._fwl_1F1R._sprites = &map._wallSprites._fwl2;
-	}
-	else if (_wo[147]) {
-		_indoorList._fwl_1F1R._frame = 2;
-		_indoorList._fwl_1F1R._sprites = &map._wallSprites._fwl2;
-	}
-	else if (_wo[187]) {
-		_indoorList._fwl_1F1R._frame = 3;
-		_indoorList._fwl_1F1R._sprites = &map._wallSprites._fwl2;
-	}
-	else if (_wo[27]) {
-		_indoorList._fwl_1F1R._frame = 0;
-		_indoorList._fwl_1F1R._sprites = &map._wallSprites._fwl1;
-	}
-	else if (_wo[207]) {
-		_indoorList._fwl_1F1R._frame = 8;
-		_indoorList._fwl_1F1R._sprites = &map._wallSprites._fwl2;
-	}
-	else if (_wo[227]) {
-		_indoorList._fwl_1F1R._frame = 7;
-		_indoorList._fwl_1F1R._sprites = &map._wallSprites._fwl2;
-	}
-	else if (_wo[247]) {
-		_indoorList._fwl_1F1R._frame = 6;
-		_indoorList._fwl_1F1R._sprites = &map._wallSprites._fwl1;
-	}
-	else if (_wo[267]) {
-		_indoorList._fwl_1F1R._frame = 4;
-		_indoorList._fwl_1F1R._sprites = &map._wallSprites._fwl2;
-	}
-	else if (_wo[287]) {
-		_indoorList._fwl_1F1R._frame = 5;
-		_indoorList._fwl_1F1R._sprites = &map._wallSprites._fwl2;
-	}
-	else if (_wo[307]) {
-		_indoorList._fwl_1F1R._frame = 6;
-		_indoorList._fwl_1F1R._sprites = &map._wallSprites._fwl2;
-	}
-
-	if (_wo[28]) {
-		_indoorList._swl_0F1L._frame = 0;
-	}
-	else if (_wo[72]) {
-		_indoorList._swl_0F1L._frame = 24;
-	}
-
-	if (_wo[29]) {
-		_indoorList._swl_0F1R._frame = 1;
-	}
-	else if (_wo[73]) {
-		_indoorList._swl_0F1R._frame = 25;
-	}
-
-	map.cellFlagLookup(_vm->_party._mazePosition);
-
-	// WORKAROUND: Original did an array lookup on _skySprites.
-	// Was this a feature for multiple skys that was abandoned?
-	_indoorList[0]._sprites = &map._skySprites;
-	_indoorList[0]._flags = _flipSky ? SPRFLAG_HORIZ_FLIPPED : 0;
-
-	if (_vm->_openDoor) {
-		Common::Point pt(
-			_vm->_party._mazePosition.x + SCREEN_POSITIONING_X[
-				_vm->_party._mazeDirection][_vm->_party._mazePosition.x],
-			_vm->_party._mazePosition.y + SCREEN_POSITIONING_Y[
-				_vm->_party._mazeDirection][_vm->_party._mazePosition.y]
-			);
-		map.cellFlagLookup(pt);
-		
-		_indoorList._sky._sprites = &map._skySprites;
-	} else {
-		_indoorList._sky._sprites = _indoorList[0]._sprites;
-	}
-
-	_indoorList._sky._flags = _flipSky ? SPRFLAG_HORIZ_FLIPPED : 0;
-	_indoorList._ground._flags = _flipGround ? SPRFLAG_HORIZ_FLIPPED : 0;
-	_indoorList._horizon._frame = 7;
-
-	// Finally draw the darn indoor scene
-	_vm->_screen->_windows[3].drawList(&_indoorList[0], _indoorList.size());
-
-	// Check for any character shooting
-	_isShooting = false;
-	for (int i = 0; i < _vm->_party._partyCount; ++i) {
-		if (_vm->_combat->_shooting[i])
-			_isShooting = true;
-	}
-	
-	_charsShooting = _isShooting;
-
-	// TODO
-}
-
 void Interface::updateAutoMap() {
 	// TODO
 }
diff --git a/engines/xeen/interface.h b/engines/xeen/interface.h
index f84885f..4667592 100644
--- a/engines/xeen/interface.h
+++ b/engines/xeen/interface.h
@@ -25,6 +25,7 @@
 
 #include "common/scummsys.h"
 #include "xeen/dialogs.h"
+#include "xeen/interface_map.h"
 #include "xeen/party.h"
 #include "xeen/screen.h"
 
@@ -32,55 +33,7 @@ namespace Xeen {
 
 class XeenEngine;
 
-class OutdoorDrawList {
-public:
-	DrawStruct _data[132];
-	DrawStruct &_skySprite;
-	DrawStruct &_groundSprite;
-public:
-	OutdoorDrawList();
-
-	DrawStruct &operator[](int idx) { 
-		assert(idx < size());
-		return _data[idx]; 
-	}
-
-	int size() const { return 132; }
-};
-
-class IndoorDrawList {
-public:
-	DrawStruct _data[170];
-	DrawStruct &_sky;
-	DrawStruct &_ground;
-	DrawStruct &_horizon;
-	DrawStruct &_swl_0F1R, _swl_0F1L, _swl_1F1R, _swl_1F1L,
-		_swl_2F2R, _swl_2F1R, _swl_2F1L, _swl_2F2L,
-		_swl_3F1R, _swl_3F2R, _swl_3F3R, _swl_3F4R,
-		_swl_3F1L, _swl_3F2L, _swl_3F3L, _swl_3F4L,
-		_swl_4F4R, _swl_4F3R, _swl_4F2R, _swl_4F1R,
-		_swl_4F1L, _swl_4F2L, _swl_4F3L, _swl_4F4L;
-	DrawStruct &_fwl_4F4R, _fwl_4F3R, _fwl_4F2R, _fwl_4F1R,
-		_fwl_4F, _fwl_4F1L, _fwl_4F2L, _fwl_4F3L, _fwl_4F4L;
-	DrawStruct &_fwl_2F1R, _fwl_2F, _fwl_2F1L, _fwl_3F2R,
-		_fwl_3F1R, _fwl_3F, _fwl_3F1L, _fwl_3F2L;
-	DrawStruct &_fwl_1F, _fwl_1F1R, _fwl_1F1L;
-	DrawStruct &_objects0, _objects1, _objects2, _objects3;
-	DrawStruct &_objects4, _objects5, _objects6, _objects7;
-	DrawStruct &_objects8, _objects9, _objects10, _objects11;
-public:
-	IndoorDrawList();
-
-	DrawStruct &operator[](int idx) { 
-		assert(idx < size());
-		return _data[idx]; 
-	}
-
-	int size() const { return 170; }
-};
-
-
-class Interface: public ButtonContainer {
+class Interface: public ButtonContainer, public InterfaceMap {
 private:
 	XeenEngine *_vm;
 	SpriteResource _dseFace;
@@ -115,26 +68,17 @@ private:
 	Common::String _interfaceText;
 	int _hiliteChar;
 	int _intrIndex1;
-	bool _flipWtr;
-	bool _flipWall;
-	bool _flipSky;
-	bool _flipGround;
 	bool _flag1;
 	int _animCounter;
 	bool _isAnimReset;
-	bool _charsShooting;
 	byte _tillMove;
-	int _objNumber;
-	byte _wp[20];
-	byte _wo[308];
 	bool _thinWall;
 	int _overallFrame;
-	bool _isShooting;
-
-	void loadSprites();
 
 	void initDrawStructs();
 
+	void loadSprites();
+
 	void assembleBorder();
 
 	void setupBackground();
@@ -149,18 +93,6 @@ private:
 
 	void animate3d();
 
-	void setIndoorsMonsters();
-
-	void setIndoorObjects();
-
-	void setIndoorWallPics();
-
-	void drawIndoors();
-
-	void setOutdoorsMonsters();
-
-	void setOutdoorsObjects();
-
 	void moveMonsters();
 
 	void setMainButtons();
diff --git a/engines/xeen/interface_map.cpp b/engines/xeen/interface_map.cpp
new file mode 100644
index 0000000..d88f942
--- /dev/null
+++ b/engines/xeen/interface_map.cpp
@@ -0,0 +1,1704 @@
+/* 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 "xeen/interface.h"
+#include "xeen/dialogs_error.h"
+#include "xeen/resources.h"
+#include "xeen/xeen.h"
+
+namespace Xeen {
+
+OutdoorDrawList::OutdoorDrawList() : _skySprite(_data[1]), _groundSprite(_data[2]) {
+	_data[0] = DrawStruct(0, 8, 8);
+	_data[1] = DrawStruct(1, 8, 25);
+	_data[2] = DrawStruct(0, 8, 67);
+	_data[3] = DrawStruct(0, 8, 67);
+	_data[4] = DrawStruct(0, 38, 67);
+	_data[5] = DrawStruct(0, 84, 67);
+	_data[6] = DrawStruct(0, 134, 67);
+	_data[7] = DrawStruct(0, 117, 67);
+	_data[8] = DrawStruct(0, 117, 67);
+	_data[9] = DrawStruct(0, 103, 67);
+	_data[10] = DrawStruct(0, 8, 73);
+	_data[11] = DrawStruct(0, 8, 73);
+	_data[12] = DrawStruct(0, 30, 73);
+	_data[13] = DrawStruct(0, 181, 73);
+	_data[14] = DrawStruct(0, 154, 73);
+	_data[15] = DrawStruct(0, 129, 73);
+	_data[16] = DrawStruct(0, 87, 73);
+	_data[17] = DrawStruct(0, 8, 81);
+	_data[18] = DrawStruct(0, 8, 81);
+	_data[19] = DrawStruct(0, 202, 81);
+	_data[20] = DrawStruct(0, 145, 81);
+	_data[21] = DrawStruct(0, 63, 81);
+	_data[22] = DrawStruct(0, 8, 93);
+	_data[23] = DrawStruct(0, 169, 93);
+	_data[24] = DrawStruct(0, 31, 93);
+	_data[25] = DrawStruct(0, 8, 109);
+	_data[26] = DrawStruct(0, 201, 109);
+	_data[27] = DrawStruct(0, 8, 109);
+	_data[28] = DrawStruct(1, 65472, 61, 14, SPRFLAG_2000);
+	_data[29] = DrawStruct(1, 65496, 61, 14, 0);
+	_data[30] = DrawStruct(1, 65520, 61, 14, 0);
+	_data[31] = DrawStruct(1, 8, 61, 14, 0);
+	_data[32] = DrawStruct(1, 128, 61, 14, SPRFLAG_HORIZ_FLIPPED | SPRFLAG_2000);
+	_data[33] = DrawStruct(1, 104, 61, 14, SPRFLAG_HORIZ_FLIPPED);
+	_data[34] = DrawStruct(1, 80, 61, 14, SPRFLAG_HORIZ_FLIPPED);
+	_data[35] = DrawStruct(1, 56, 61, 14, SPRFLAG_HORIZ_FLIPPED);
+	_data[36] = DrawStruct(1, 32, 61, 14, 0);
+	_data[37] = DrawStruct(0, 65527, 61, 14, 0);
+	_data[38] = DrawStruct(0, 65478, 61, 14, 0);
+	_data[39] = DrawStruct(0, 40, 61, 14, 0);
+	_data[40] = DrawStruct(0, 65454, 61, 14, 0);
+	_data[41] = DrawStruct(0, 64, 61, 14, 0);
+	_data[42] = DrawStruct(0, 65495, 61, 14, 0);
+	_data[43] = DrawStruct(0, 65510, 61, 14, 0);
+	_data[44] = DrawStruct(0, 65502, 61, 14, 0);
+	_data[45] = DrawStruct(0, 65520, 61, 14, 0);
+	_data[46] = DrawStruct(0, 23, 61, 14, 0);
+	_data[47] = DrawStruct(0, 16, 61, 14, 0);
+	_data[48] = DrawStruct(0, 65478, 61, 14, 0);
+	_data[49] = DrawStruct(0, 40, 61, 14, 0);
+	_data[50] = DrawStruct(0, 65519, 61, 14, 0);
+	_data[51] = DrawStruct(0, 65535, 58, 14, 0);
+	_data[52] = DrawStruct(0, 65527, 58, 14, 0);
+	_data[53] = DrawStruct(0, 72, 58, 12, 0);
+	_data[54] = DrawStruct(0, 72, 58, 12, SPRFLAG_HORIZ_FLIPPED);
+	_data[55] = DrawStruct(0, 69, 63, 12, 0);
+	_data[56] = DrawStruct(0, 75, 63, 12, SPRFLAG_HORIZ_FLIPPED);
+	_data[57] = DrawStruct(0, 73, 53, 12, 0);
+	_data[58] = DrawStruct(0, 71, 53, 12, SPRFLAG_HORIZ_FLIPPED);
+	_data[59] = DrawStruct(0, 80, 57, 12, 0);
+	_data[60] = DrawStruct(0, 64, 57, 12, SPRFLAG_HORIZ_FLIPPED);
+	_data[61] = DrawStruct(2, 65525, 54, 8, 0);
+	_data[62] = DrawStruct(1, 65515, 54, 11, 0);
+	_data[63] = DrawStruct(2, 165, 54, 8, SPRFLAG_HORIZ_FLIPPED);
+	_data[64] = DrawStruct(1, 86, 54, 11, SPRFLAG_HORIZ_FLIPPED);
+	_data[65] = DrawStruct(1, 33, 54, 11, 0);
+	_data[66] = DrawStruct(0, 65528, 54, 12, 0);
+	_data[67] = DrawStruct(0, 65463, 54, 12, 0);
+	_data[68] = DrawStruct(0, 57, 54, 12, 0);
+	_data[69] = DrawStruct(0, 65471, 54, 12, 0);
+	_data[70] = DrawStruct(0, 65455, 54, 12, 0);
+	_data[71] = DrawStruct(0, 49, 54, 12, 0);
+	_data[72] = DrawStruct(0, 65, 54, 12, 0);
+	_data[73] = DrawStruct(0, 65512, 54, 12, 0);
+	_data[74] = DrawStruct(0, 9, 50, 12, 0);
+	_data[75] = DrawStruct(0, 65528, 50, 12, 0);
+	_data[76] = DrawStruct(0, 72, 53, 8, 0);
+	_data[77] = DrawStruct(0, 72, 53, 8, SPRFLAG_HORIZ_FLIPPED);
+	_data[78] = DrawStruct(0, 77, 58, 8, 0);
+	_data[79] = DrawStruct(0, 67, 58, 8, SPRFLAG_HORIZ_FLIPPED);
+	_data[80] = DrawStruct(0, 81, 47, 8, 0);
+	_data[81] = DrawStruct(0, 63, 47, 8, SPRFLAG_HORIZ_FLIPPED);
+	_data[82] = DrawStruct(0, 94, 52, 8, 0);
+	_data[83] = DrawStruct(0, 50, 52, 8, SPRFLAG_HORIZ_FLIPPED);
+	_data[84] = DrawStruct(2, 8, 40);
+	_data[85] = DrawStruct(2, 146, 40, 0, SPRFLAG_HORIZ_FLIPPED);
+	_data[86] = DrawStruct(1, 32, 40, 6, 0);
+	_data[87] = DrawStruct(0, 65529, 30, 7, 0);
+	_data[88] = DrawStruct(0, 65424, 30, 7, SPRFLAG_2000);
+	_data[89] = DrawStruct(0, 98, 30, 7, SPRFLAG_2000);
+	_data[90] = DrawStruct(0, 65424, 30, 8, SPRFLAG_2000);
+	_data[91] = DrawStruct(0, 98, 30, 8, SPRFLAG_2000);
+	_data[92] = DrawStruct(0, 65498, 30, 8, 0);
+	_data[93] = DrawStruct(0, 25, 30, 8, 0);
+	_data[94] = DrawStruct(0, 65529, 30, 8, 0);
+	_data[95] = DrawStruct(0, 72, 48, 4, 0);
+	_data[96] = DrawStruct(0, 72, 48, 4, SPRFLAG_HORIZ_FLIPPED);
+	_data[97] = DrawStruct(0, 85, 53, 4, 0);
+	_data[98] = DrawStruct(0, 59, 53, 4, SPRFLAG_HORIZ_FLIPPED);
+	_data[99] = DrawStruct(0, 89, 41, 4, 0);
+	_data[100] = DrawStruct(0, 55, 41, 4, SPRFLAG_HORIZ_FLIPPED);
+	_data[101] = DrawStruct(0, 106, 47, 4, 0);
+	_data[102] = DrawStruct(0, 38, 47, 4, SPRFLAG_HORIZ_FLIPPED);
+	_data[103] = DrawStruct(0, 8, 24);
+	_data[104] = DrawStruct(0, 169, 24, 0, SPRFLAG_HORIZ_FLIPPED);
+	_data[105] = DrawStruct(1, 32, 24);
+	_data[106] = DrawStruct(0, 65513, 40, 0, SPRFLAG_2000);
+	_data[107] = DrawStruct(0, 200, 40, 0, SPRFLAG_HORIZ_FLIPPED | SPRFLAG_2000);
+	_data[108] = DrawStruct(0, 8, 47);
+	_data[109] = DrawStruct(0, 169, 47, 0, SPRFLAG_HORIZ_FLIPPED);
+	_data[110] = DrawStruct(1, 65480, 65532, 32768, SPRFLAG_4000 | SPRFLAG_2000);
+	_data[111] = DrawStruct(0, 65531, 2, 0, SPRFLAG_4000 | SPRFLAG_2000);
+	_data[112] = DrawStruct(0, 65469, 2, 0, SPRFLAG_4000 | SPRFLAG_2000);
+	_data[113] = DrawStruct(0, 44, 73);
+	_data[114] = DrawStruct(0, 44, 73);
+	_data[115] = DrawStruct(0, 58, 14, 0, SPRFLAG_4000 | SPRFLAG_2000);
+	_data[116] = DrawStruct(0, 169, 73);
+	_data[117] = DrawStruct(0, 169, 73);
+	_data[118] = DrawStruct(0, 65531, 14, 0, SPRFLAG_4000 | SPRFLAG_2000);
+	_data[119] = DrawStruct(0, 110, 73);
+	_data[120] = DrawStruct(0, 110, 73);
+	_data[121] = DrawStruct(0, 65531, 14, 0, SPRFLAG_4000 | SPRFLAG_2000);
+	_data[122] = DrawStruct(0, 110, 73);
+	_data[123] = DrawStruct(0, 110, 73);
+	_data[124] = DrawStruct(0, 72, 43);
+	_data[125] = DrawStruct(0, 72, 43, 0, SPRFLAG_HORIZ_FLIPPED);
+	_data[126] = DrawStruct(0, 93, 48);
+	_data[127] = DrawStruct(0, 51, 48, 0, SPRFLAG_HORIZ_FLIPPED);
+	_data[128] = DrawStruct(0, 97, 36);
+	_data[129] = DrawStruct(0, 47, 36, 0, SPRFLAG_HORIZ_FLIPPED);
+	_data[130] = DrawStruct(0, 118, 42);
+	_data[131] = DrawStruct(0, 26, 42, 0, SPRFLAG_HORIZ_FLIPPED);
+}
+
+/*------------------------------------------------------------------------*/
+
+IndoorDrawList::IndoorDrawList() : 
+	_sky(_data[1]), _ground(_data[2]), _horizon(_data[28]),
+	_swl_0F1R(_data[ 46]), _swl_0F1L(_data[44]),  _swl_1F1R(_data[134]), 
+	_swl_1F1L(_data[133]), _swl_2F2R(_data[110]), _swl_2F1R(_data[109]), 
+	_swl_2F1L(_data[108]), _swl_2F2L(_data[107]), _swl_3F1R(_data[ 78]), 
+	_swl_3F2R(_data[ 77]), _swl_3F3R(_data[ 76]), _swl_3F4R(_data[ 75]),
+	_swl_3F1L(_data[ 74]), _swl_3F2L(_data[ 73]), _swl_3F3L(_data[ 72]), 
+	_swl_3F4L(_data[ 71]), _swl_4F4R(_data[ 33]), _swl_4F3R(_data[ 34]), 
+	_swl_4F2R(_data[ 35]), _swl_4F1R(_data[ 36]), _swl_4F1L(_data[ 32]),
+	_swl_4F2L(_data[ 31]), _swl_4F3L(_data[ 30]), _swl_4F4L(_data[ 29]),
+	_fwl_4F4R(_data[ 45]), _fwl_4F3R(_data[ 44]), _fwl_4F2R(_data[ 43]), 
+	_fwl_4F1R(_data[ 42]), _fwl_4F(  _data[ 41]), _fwl_4F1L(_data[ 40]), 
+	_fwl_4F2L(_data[ 39]), _fwl_4F3L(_data[ 38]), _fwl_4F4L(_data[ 37]),
+	_fwl_2F1R(_data[121]), _fwl_2F(  _data[120]), _fwl_2F1L(_data[119]), 
+	_fwl_3F2R(_data[ 91]), _fwl_3F1R(_data[ 90]), _fwl_3F(  _data[ 89]), 
+	_fwl_3F1L(_data[ 88]), _fwl_3F2L(_data[ 87]), _fwl_1F(  _data[147]),
+	_fwl_1F1R(_data[145]), _fwl_1F1L(_data[143]),
+	_objects0(_data[149]), _objects1(_data[125]), _objects2(_data[126]),
+	_objects3(_data[127]), _objects4(_data[97]), _objects5(_data[98]),
+	_objects6(_data[99]), _objects7(_data[55]), _objects8(_data[56]),
+	_objects9(_data[58]), _objects10(_data[57]), _objects11(_data[59]) {
+	// Setup draw structure positions
+	_data[0] = DrawStruct(0, 8, 8);
+	_data[1] = DrawStruct(1, 8, 25);
+	_data[2] = DrawStruct(0, 8, 67);
+	_data[3] = DrawStruct(0, 8, 67);
+	_data[4] = DrawStruct(0, 38, 67);
+	_data[5] = DrawStruct(0, 84, 67);
+	_data[6] = DrawStruct(0, 134, 67);
+	_data[7] = DrawStruct(0, 117, 67);
+	_data[8] = DrawStruct(0, 117, 67);
+	_data[9] = DrawStruct(0, 103, 67);
+	_data[10] = DrawStruct(0, 8, 73);
+	_data[11] = DrawStruct(0, 8, 73);
+	_data[12] = DrawStruct(0, 30, 73);
+	_data[13] = DrawStruct(0, 181, 73);
+	_data[14] = DrawStruct(0, 154, 73);
+	_data[15] = DrawStruct(0, 129, 73);
+	_data[16] = DrawStruct(0, 87, 73);
+	_data[17] = DrawStruct(0, 8, 81);
+	_data[18] = DrawStruct(0, 8, 81);
+	_data[19] = DrawStruct(0, 202, 81);
+	_data[20] = DrawStruct(0, 145, 81);
+	_data[21] = DrawStruct(0, 63, 81);
+	_data[22] = DrawStruct(0, 8, 93);
+	_data[23] = DrawStruct(0, 169, 93);
+	_data[24] = DrawStruct(0, 31, 93);
+	_data[25] = DrawStruct(0, 8, 109);
+	_data[26] = DrawStruct(0, 201, 109);
+	_data[27] = DrawStruct(0, 8, 109);
+	_data[28] = DrawStruct(7, 8, 64);
+	_data[29] = DrawStruct(22, 32, 60);
+	_data[30] = DrawStruct(20, 56, 60);
+	_data[31] = DrawStruct(18, 80, 60);
+	_data[32] = DrawStruct(16, 104, 60);
+	_data[33] = DrawStruct(23, 152, 60, 0, SPRFLAG_HORIZ_FLIPPED);
+	_data[34] = DrawStruct(21, 144, 60, 0, SPRFLAG_HORIZ_FLIPPED);
+	_data[35] = DrawStruct(19, 131, 60, 0, SPRFLAG_HORIZ_FLIPPED);
+	_data[36] = DrawStruct(17, 120, 60, 0, SPRFLAG_HORIZ_FLIPPED);
+	_data[37] = DrawStruct(14, 8, 60);
+	_data[38] = DrawStruct(12, 32, 60);
+	_data[39] = DrawStruct(10, 56, 60);
+	_data[40] = DrawStruct(14, 80, 60);
+	_data[41] = DrawStruct(14, 104, 60);
+	_data[42] = DrawStruct(14, 128, 60);
+	_data[43] = DrawStruct(14, 152, 60);
+	_data[44] = DrawStruct(8, 176, 60);
+	_data[45] = DrawStruct(8, 200, 60);
+	_data[46] = DrawStruct(0, 65472, 61, 14, 0);
+	_data[47] = DrawStruct(0, 65496, 61, 14, 0);
+	_data[48] = DrawStruct(0, 65520, 61, 14, 0);
+	_data[49] = DrawStruct(0, 8, 61, 14, 0);
+	_data[50] = DrawStruct(0, 32, 61, 14, 0);
+	_data[51] = DrawStruct(0, 56, 61, 14, 0);
+	_data[52] = DrawStruct(0, 80, 61, 14, 0);
+	_data[53] = DrawStruct(0, 104, 61, 14, 0);
+	_data[54] = DrawStruct(0, 128, 61, 14, 0);
+	_data[55] = DrawStruct(0, 65527, 58, 14, 0);
+	_data[56] = DrawStruct(0, 65502, 58, 14, 0);
+	_data[57] = DrawStruct(0, 16, 58, 14, 0);
+	_data[58] = DrawStruct(0, 65478, 58, 14, 0);
+	_data[59] = DrawStruct(0, 40, 58, 14, 0);
+	_data[60] = DrawStruct(0, 65495, 58, 14, 0);
+	_data[61] = DrawStruct(0, 65510, 58, 14, 0);
+	_data[62] = DrawStruct(0, 65502, 58, 14, 0);
+	_data[63] = DrawStruct(0, 65520, 58, 14, 0);
+	_data[64] = DrawStruct(0, 23, 58, 14, 0);
+	_data[65] = DrawStruct(0, 16, 58, 14, 0);
+	_data[66] = DrawStruct(0, 65478, 58, 14, 0);
+	_data[67] = DrawStruct(0, 40, 58, 14, 0);
+	_data[68] = DrawStruct(0, 65519, 58, 14, 0);
+	_data[69] = DrawStruct(0, 65535, 58, 14, 0);
+	_data[70] = DrawStruct(0, 65527, 58, 14, 0);
+	_data[71] = DrawStruct(14, 8, 58);
+	_data[72] = DrawStruct(12, 8, 55);
+	_data[73] = DrawStruct(10, 32, 52);
+	_data[74] = DrawStruct(14, 88, 52);
+	_data[75] = DrawStruct(14, 128, 52, 0, SPRFLAG_HORIZ_FLIPPED);
+	_data[76] = DrawStruct(14, 152, 52, 0, SPRFLAG_HORIZ_FLIPPED);
+	_data[77] = DrawStruct(0, 176, 55, 0, SPRFLAG_HORIZ_FLIPPED);
+	_data[78] = DrawStruct(0, 200, 58, 0, SPRFLAG_HORIZ_FLIPPED);
+	_data[79] = DrawStruct(0, 72, 58, 12, 0);
+	_data[80] = DrawStruct(0, 72, 58, 12, SPRFLAG_HORIZ_FLIPPED);
+	_data[81] = DrawStruct(0, 69, 63, 12, 0);
+	_data[82] = DrawStruct(0, 75, 63, 12, SPRFLAG_HORIZ_FLIPPED);
+	_data[83] = DrawStruct(0, 73, 53, 12, 0);
+	_data[84] = DrawStruct(0, 71, 53, 12, SPRFLAG_HORIZ_FLIPPED);
+	_data[85] = DrawStruct(0, 80, 57, 12, 0);
+	_data[86] = DrawStruct(0, 64, 57, 12, SPRFLAG_HORIZ_FLIPPED);
+	_data[87] = DrawStruct(7, 65512, 52, 0, SPRFLAG_2000);
+	_data[88] = DrawStruct(7, 32, 52);
+	_data[89] = DrawStruct(7, 88, 52);
+	_data[90] = DrawStruct(0, 144, 52);
+	_data[91] = DrawStruct(0, 200, 52, 0, SPRFLAG_2000);
+	_data[92] = DrawStruct(0, 65457, 52, 11, SPRFLAG_2000);
+	_data[93] = DrawStruct(0, 65509, 52, 11, 0);
+	_data[94] = DrawStruct(0, 32, 52, 11, 0);
+	_data[95] = DrawStruct(0, 89, 52, 11, 0);
+	_data[96] = DrawStruct(0, 145, 52, 11, SPRFLAG_2000);
+	_data[97] = DrawStruct(0, 65528, 50, 12, 0);
+	_data[98] = DrawStruct(0, 65471, 50, 12, 0);
+	_data[99] = DrawStruct(0, 49, 50, 12, 0);
+	_data[100] = DrawStruct(0, 65471, 50, 12, 0);
+	_data[101] = DrawStruct(0, 65455, 50, 12, 0);
+	_data[102] = DrawStruct(0, 49, 50, 12, 0);
+	_data[103] = DrawStruct(0, 65, 50, 12, 0);
+	_data[104] = DrawStruct(0, 65512, 50, 12, 0);
+	_data[105] = DrawStruct(0, 9, 50, 12, 0);
+	_data[106] = DrawStruct(0, 65528, 50, 12, 0);
+	_data[107] = DrawStruct(7, 8, 48);
+	_data[108] = DrawStruct(7, 64, 40);
+	_data[109] = DrawStruct(6, 144, 40, 0, SPRFLAG_HORIZ_FLIPPED);
+	_data[110] = DrawStruct(6, 200, 48, 0, SPRFLAG_HORIZ_FLIPPED);
+	_data[111] = DrawStruct(0, 72, 53, 8, 0);
+	_data[112] = DrawStruct(0, 72, 53, 8, SPRFLAG_HORIZ_FLIPPED);
+	_data[113] = DrawStruct(0, 77, 58, 8, 0);
+	_data[114] = DrawStruct(0, 67, 58, 8, SPRFLAG_HORIZ_FLIPPED);
+	_data[115] = DrawStruct(0, 81, 47, 8, 0);
+	_data[116] = DrawStruct(0, 63, 47, 8, SPRFLAG_HORIZ_FLIPPED);
+	_data[117] = DrawStruct(0, 94, 52, 8, 0);
+	_data[118] = DrawStruct(0, 50, 52, 8, SPRFLAG_HORIZ_FLIPPED);
+	_data[119] = DrawStruct(6, 65496, 40, 0, SPRFLAG_2000);
+	_data[120] = DrawStruct(6, 64, 40);
+	_data[121] = DrawStruct(0, 168, 40, 0, SPRFLAG_2000);
+	_data[122] = DrawStruct(0, 65464, 40, 6, SPRFLAG_2000);
+	_data[123] = DrawStruct(0, 32, 40, 6, 0);
+	_data[124] = DrawStruct(0, 137, 40, 6, SPRFLAG_2000);
+	_data[125] = DrawStruct(0, 65529, 25, 7, 0);
+	_data[126] = DrawStruct(0, 65424, 25, 7, SPRFLAG_2000);
+	_data[127] = DrawStruct(0, 98, 25, 7, SPRFLAG_2000);
+	_data[128] = DrawStruct(0, 65424, 29, 8, SPRFLAG_2000);
+	_data[129] = DrawStruct(0, 98, 29, 8, SPRFLAG_2000);
+	_data[130] = DrawStruct(0, 65498, 29, 8, 0);
+	_data[131] = DrawStruct(0, 25, 29, 8, 0);
+	_data[132] = DrawStruct(0, 65529, 29, 8, 0);
+	_data[133] = DrawStruct(6, 32, 24);
+	_data[134] = DrawStruct(0, 168, 24, 0, SPRFLAG_HORIZ_FLIPPED);
+	_data[135] = DrawStruct(0, 72, 48, 4, 0);
+	_data[136] = DrawStruct(0, 72, 48, 4, SPRFLAG_HORIZ_FLIPPED);
+	_data[137] = DrawStruct(0, 85, 53, 4, 0);
+	_data[138] = DrawStruct(0, 59, 53, 4, SPRFLAG_HORIZ_FLIPPED);
+	_data[139] = DrawStruct(0, 89, 41, 4, 0);
+	_data[140] = DrawStruct(0, 55, 41, 4, SPRFLAG_HORIZ_FLIPPED);
+	_data[141] = DrawStruct(0, 106, 47, 4, 0);
+	_data[142] = DrawStruct(0, 38, 47, 4, SPRFLAG_HORIZ_FLIPPED);
+	_data[143] = DrawStruct(0, 65400, 24, 0, SPRFLAG_2000);
+	_data[144] = DrawStruct(0, 8, 12);
+	_data[145] = DrawStruct(0, 32, 24);
+	_data[146] = DrawStruct(0, 200, 12, 0, SPRFLAG_HORIZ_FLIPPED);
+	_data[147] = DrawStruct(0, 200, 24, 0, SPRFLAG_2000);
+	_data[148] = DrawStruct(0, 32, 24);
+	_data[149] = DrawStruct(0, 65531, 2, 0, SPRFLAG_4000 | SPRFLAG_2000);
+	_data[150] = DrawStruct(0, 65469, 10, 0, SPRFLAG_4000 | SPRFLAG_2000);
+	_data[151] = DrawStruct(0, 44, 73);
+	_data[152] = DrawStruct(0, 44, 73);
+	_data[153] = DrawStruct(0, 58, 14, 0, SPRFLAG_4000 | SPRFLAG_2000);
+	_data[154] = DrawStruct(0, 169, 73);
+	_data[155] = DrawStruct(0, 169, 73);
+	_data[156] = DrawStruct(0, 65531, 14, 0, SPRFLAG_4000 | SPRFLAG_2000);
+	_data[157] = DrawStruct(0, 110, 73);
+	_data[158] = DrawStruct(0, 110, 73);
+	_data[159] = DrawStruct(0, 65531, 14, 0, SPRFLAG_4000 | SPRFLAG_2000);
+	_data[160] = DrawStruct(0, 110, 73);
+	_data[161] = DrawStruct(0, 110, 73);
+	_data[162] = DrawStruct(0, 72, 43);
+	_data[163] = DrawStruct(0, 72, 43, 0, SPRFLAG_HORIZ_FLIPPED);
+	_data[164] = DrawStruct(0, 93, 48);
+	_data[165] = DrawStruct(0, 51, 48, 0, SPRFLAG_HORIZ_FLIPPED);
+	_data[166] = DrawStruct(0, 97, 36);
+	_data[167] = DrawStruct(0, 47, 36, 0, SPRFLAG_HORIZ_FLIPPED);
+	_data[168] = DrawStruct(0, 118, 42);
+	_data[169] = DrawStruct(0, 26, 42, 0, SPRFLAG_HORIZ_FLIPPED);
+}
+
+/*------------------------------------------------------------------------*/
+
+InterfaceMap::InterfaceMap(XeenEngine *vm): _vm(vm) {
+	Common::fill(&_wp[0], &_wp[20], 0);
+	Common::fill(&_wo[0], &_wo[308], 0);
+	_overallFrame = 0;
+	_flipWtr = false;
+	_flipWall = false;
+	_flipSky = false;
+	_flipGround = false;
+	_isShooting = false;
+	_charsShooting = false;
+	_objNumber = 0;
+}
+
+void InterfaceMap::setIndoorsMonsters() {
+
+}
+
+void InterfaceMap::setIndoorObjects() {
+	Common::Point mazePos = _vm->_party._mazePosition;
+	_objNumber = 0;
+	const int8 *posOffset = &SCREEN_POSITIONING_X[_vm->_party._mazeDirection][0];
+	Common::Point pt;
+
+	Common::Array<MazeObject> &objects = _vm->_map->_mobData._objects;
+	for (uint idx = 0; idx < objects.size(); ++idx) {
+		MazeObject &mazeObject = objects[idx];
+
+		// Determine which half of the X/Y lists to use
+		int listOffset;
+		if (_vm->_files->_isDarkCc) {
+			listOffset = mazeObject._spriteId == 47 ? 1 : 0;
+		}
+		else {
+			listOffset = mazeObject._spriteId == 113 ? 1 : 0;
+		}
+
+		// Position 1
+		pt = Common::Point(mazePos.x + posOffset[2], mazePos.y + posOffset[194]);
+		if (pt == mazeObject._position && _indoorList._objects0._frame == -1) {
+			_indoorList._objects0._x = INDOOR_OBJECT_X[listOffset][0];
+			_indoorList._objects0._y = INDOOR_OBJECT_Y[listOffset][0];
+			_indoorList._objects0._frame = mazeObject._frame;
+			_indoorList._objects0._sprites = mazeObject._sprites;
+			_indoorList._objects0._flags &= ~SPRFLAG_HORIZ_FLIPPED;
+			if (mazeObject._flipped)
+				_indoorList._objects0._flags |= SPRFLAG_HORIZ_FLIPPED;
+			_objNumber = idx;
+		}
+
+		// Position 2
+		pt = Common::Point(mazePos.x + posOffset[7], mazePos.y + posOffset[199]);
+		if (pt == mazeObject._position && !_wo[27] && _indoorList._objects1._frame == -1) {
+			_indoorList._objects1._x = INDOOR_OBJECT_X[listOffset][1];
+			_indoorList._objects1._y = INDOOR_OBJECT_Y[listOffset][1];
+			_indoorList._objects1._frame = mazeObject._frame;
+			_indoorList._objects1._sprites = mazeObject._sprites;
+			_indoorList._objects1._flags &= ~SPRFLAG_HORIZ_FLIPPED;
+			if (mazeObject._flipped)
+				_indoorList._objects1._flags |= SPRFLAG_HORIZ_FLIPPED;
+		}
+
+		// Position 3
+		pt = Common::Point(mazePos.x + posOffset[5], mazePos.y + posOffset[197]);
+		if (pt == mazeObject._position && (!_wo[27] || !_wo[25]) && (!_wo[27] || !_wo[28]) &&
+				(!_wo[23] || !_wo[25]) && (!_wo[23] || !_wo[28]) && 
+				_indoorList._objects2._frame == -1) {
+			_indoorList._objects2._x = INDOOR_OBJECT_X[listOffset][2];
+			_indoorList._objects2._y = INDOOR_OBJECT_Y[listOffset][2];
+			_indoorList._objects2._frame = mazeObject._frame;
+			_indoorList._objects2._sprites = mazeObject._sprites;
+			_indoorList._objects2._flags &= ~SPRFLAG_HORIZ_FLIPPED;
+			if (mazeObject._flipped)
+				_indoorList._objects2._flags |= SPRFLAG_HORIZ_FLIPPED;
+		}
+
+		// Position 4
+		pt = Common::Point(mazePos.x + posOffset[9], mazePos.y + posOffset[201]);
+		if (pt == mazeObject._position && (!_wo[27] || !_wo[26]) && (!_wo[27] || !_wo[29]) &&
+				(!_wo[24] || !_wo[26]) && (!_wo[24] || !_wo[29]) && _indoorList._objects3._frame == -1) {
+			_indoorList._objects3._x = INDOOR_OBJECT_X[listOffset][3];
+			_indoorList._objects3._y = INDOOR_OBJECT_Y[listOffset][3];
+			_indoorList._objects3._frame = mazeObject._frame;
+			_indoorList._objects3._sprites = mazeObject._sprites;
+			_indoorList._objects3._flags &= ~SPRFLAG_HORIZ_FLIPPED;
+			if (mazeObject._flipped)
+				_indoorList._objects3._flags |= SPRFLAG_HORIZ_FLIPPED;
+		}
+
+		// Position 5
+		pt = Common::Point(mazePos.x + posOffset[14], mazePos.y + posOffset[206]);
+		if (pt == mazeObject._position && !_wo[22] && !_wo[27] && _indoorList._objects4._frame == -1) {
+			_indoorList._objects4._x = INDOOR_OBJECT_X[listOffset][4];
+			_indoorList._objects4._y = INDOOR_OBJECT_Y[listOffset][4];
+			_indoorList._objects4._frame = mazeObject._frame;
+			_indoorList._objects4._sprites = mazeObject._sprites;
+			_indoorList._objects4._flags &= ~SPRFLAG_HORIZ_FLIPPED;
+			if (mazeObject._flipped)
+				_indoorList._objects4._flags |= SPRFLAG_HORIZ_FLIPPED;
+		}
+
+		// Position 6
+		pt = Common::Point(mazePos.x + posOffset[12], mazePos.y + posOffset[204]);
+		if (pt == mazeObject._position && !_wo[27] && (!_wo[22] || !_wo[23]) && (!_wo[22] || !_wo[20]) &&
+				(!_wo[23] || !_wo[17]) && (!_wo[20] || !_wo[17]) && _indoorList._objects5._frame == -1) {
+			_indoorList._objects5._x = INDOOR_OBJECT_X[listOffset][5];
+			_indoorList._objects5._y = INDOOR_OBJECT_Y[listOffset][5];
+			_indoorList._objects5._frame = mazeObject._frame;
+			_indoorList._objects5._sprites = mazeObject._sprites;
+			_indoorList._objects5._flags &= ~SPRFLAG_HORIZ_FLIPPED;
+			if (mazeObject._flipped)
+				_indoorList._objects5._flags |= SPRFLAG_HORIZ_FLIPPED;
+		}
+
+		// Position 7
+		pt = Common::Point(mazePos.x + posOffset[16], mazePos.y + posOffset[208]);
+		if (pt == mazeObject._position && !_wo[27] && (!_wo[22] || !_wo[24]) && (!_wo[22] || !_wo[21]) &&
+			(!_wo[24] || !_wo[19]) && (!_wo[21] || !_wo[19]) && _indoorList._objects6._frame == -1) {
+			_indoorList._objects6._x = INDOOR_OBJECT_X[listOffset][6];
+			_indoorList._objects6._y = INDOOR_OBJECT_Y[listOffset][6];
+			_indoorList._objects6._frame = mazeObject._frame;
+			_indoorList._objects6._sprites = mazeObject._sprites;
+			_indoorList._objects6._flags &= ~SPRFLAG_HORIZ_FLIPPED;
+			if (mazeObject._flipped)
+				_indoorList._objects6._flags |= SPRFLAG_HORIZ_FLIPPED;
+		}
+
+		// Position 8
+		pt = Common::Point(mazePos.x + posOffset[27], mazePos.y + posOffset[219]);
+		if (pt == mazeObject._position && !_wo[27] && !_wo[22] && !_wo[15] &&  _indoorList._objects7._frame == -1) {
+			_indoorList._objects7._x = INDOOR_OBJECT_X[listOffset][7];
+			_indoorList._objects7._y = INDOOR_OBJECT_Y[listOffset][7];
+			_indoorList._objects7._frame = mazeObject._frame;
+			_indoorList._objects7._sprites = mazeObject._sprites;
+			_indoorList._objects7._flags &= ~SPRFLAG_HORIZ_FLIPPED;
+			if (mazeObject._flipped)
+				_indoorList._objects7._flags |= SPRFLAG_HORIZ_FLIPPED;
+		}
+
+		// Position 9
+		pt = Common::Point(mazePos.x + posOffset[25], mazePos.y + posOffset[217]);
+		if (pt == mazeObject._position && !_wo[27] && (!_wo[15] || !_wo[17]) && (!_wo[15] || !_wo[12]) &&
+				(!_wo[12] || !_wo[7]) && (!_wo[17] || !_wo[7]) && _indoorList._objects5._frame == -1) {
+			_indoorList._objects8._x = INDOOR_OBJECT_X[listOffset][8];
+			_indoorList._objects8._y = INDOOR_OBJECT_Y[listOffset][8];
+			_indoorList._objects8._frame = mazeObject._frame;
+			_indoorList._objects8._sprites = mazeObject._sprites;
+			_indoorList._objects8._flags &= ~SPRFLAG_HORIZ_FLIPPED;
+			if (mazeObject._flipped)
+				_indoorList._objects8._flags |= SPRFLAG_HORIZ_FLIPPED;
+		}
+
+		// Position 10
+		pt = Common::Point(mazePos.x + posOffset[23], mazePos.y + posOffset[215]);
+		if (pt == mazeObject._position && !_wo[27] && (!_wo[22] || !_wo[20]) && (!_wo[22] || !_wo[23]) &&
+				(!_wo[20] || !_wo[17]) && (!_wo[23] || !_wo[17]) && !_wo[12] && !_wo[8] &&			
+				_indoorList._objects9._frame == -1) {
+			_indoorList._objects9._x = INDOOR_OBJECT_X[listOffset][9];
+			_indoorList._objects9._y = INDOOR_OBJECT_Y[listOffset][9];
+			_indoorList._objects9._frame = mazeObject._frame;
+			_indoorList._objects9._sprites = mazeObject._sprites;
+			_indoorList._objects9._flags &= ~SPRFLAG_HORIZ_FLIPPED;
+			if (mazeObject._flipped)
+				_indoorList._objects9._flags |= SPRFLAG_HORIZ_FLIPPED;
+		}
+
+		// Block 11
+		pt = Common::Point(mazePos.x + posOffset[29], mazePos.y + posOffset[221]);
+		if (pt == mazeObject._position && !_wo[27] && !_wo[22] && (!_wo[15] || !_wo[19]) && 
+				(!_wo[15] || !_wo[14]) && (!_wo[14] || !_wo[9]) && (!_wo[19] || !_wo[9]) && 
+				_indoorList._objects10._frame == -1) {
+			_indoorList._objects10._x = INDOOR_OBJECT_X[listOffset][10];
+			_indoorList._objects10._y = INDOOR_OBJECT_Y[listOffset][10];
+			_indoorList._objects10._frame = mazeObject._frame;
+			_indoorList._objects10._sprites = mazeObject._sprites;
+			_indoorList._objects10._flags &= ~SPRFLAG_HORIZ_FLIPPED;
+			if (mazeObject._flipped)
+				_indoorList._objects10._flags |= SPRFLAG_HORIZ_FLIPPED;
+		}
+
+		// Block 12
+		pt = Common::Point(mazePos.x + posOffset[31], mazePos.y + posOffset[223]);
+		if (pt == mazeObject._position && !_wo[27] && (!_wo[22] || !_wo[21]) && (!_wo[22] || !_wo[24]) && 
+				(!_wo[21] || !_wo[19]) && (!_wo[24] || !_wo[19]) && !_wo[14] && !_wo[10] &&
+				_indoorList._objects11._frame == -1) {
+			_indoorList._objects11._x = INDOOR_OBJECT_X[listOffset][11];
+			_indoorList._objects11._y = INDOOR_OBJECT_Y[listOffset][11];
+			_indoorList._objects11._frame = mazeObject._frame;
+			_indoorList._objects11._sprites = mazeObject._sprites;
+			_indoorList._objects11._flags &= ~SPRFLAG_HORIZ_FLIPPED;
+			if (mazeObject._flipped)
+				_indoorList._objects11._flags |= SPRFLAG_HORIZ_FLIPPED;
+		}
+	}
+}
+
+void InterfaceMap::setIndoorWallPics() {
+	// TODO
+}
+
+void InterfaceMap::setOutdoorsMonsters() {
+
+}
+
+void InterfaceMap::setOutdoorsObjects() {
+
+}
+
+void InterfaceMap::drawIndoors() {
+	Map &map = *_vm->_map;
+	int surfaceId;
+	int idx;
+
+	for (int cellIndex = 0; cellIndex < 25; ++cellIndex) {
+		map.getCell(DRAW_NUMBERS[cellIndex]);
+
+		DrawStruct &drawStruct = _indoorList[3 + cellIndex];
+		drawStruct._sprites = &map._surfaceSprites[map._currentSurfaceId];
+
+		surfaceId = map.mazeData()._surfaceTypes[map._currentSurfaceId];
+		if (surfaceId == 5 || surfaceId == 12) {
+			drawStruct._flags = _flipWtr;
+			drawStruct._frame = DRAW_FRAMES[cellIndex][_flipWtr ? 1 : 0];
+		}
+		else {
+			drawStruct._frame = DRAW_FRAMES[cellIndex][_flipWall ? 1 : 0];
+			drawStruct._flags = _flipWall ? 0 : SPRFLAG_HORIZ_FLIPPED;
+		}
+	}
+
+	if (!_wo[27] && !_wo[20] && !_wo[23] && !_wo[12] && !_wo[8] && !_wo[30]) {
+		if (_wo[39])
+			_indoorList._swl_4F4L._frame = 22;
+		else if (_wo[83])
+			_indoorList._swl_4F4L._frame = 46;
+	}
+
+	if (!_wo[27] && !_wo[22] && !_wo[17] && !_wo[12] && !_wo[8]) {
+		if (_wo[38])
+			_indoorList._swl_4F3L._frame = 20;
+		else if (_wo[82])
+			_indoorList._swl_4F3L._frame = 44;
+	}
+
+	if (!_wo[27] && !_wo[22] && !_wo[15] && !_wo[2] && !_wo[7]) {
+		if (_wo[37])
+			_indoorList._swl_4F2L._frame = 18;
+		else if (_wo[81])
+			_indoorList._swl_4F2L._frame = 42;
+	}
+
+	if (!_wo[27] && !_wo[22] && !_wo[15] && !_wo[6]) {
+		if (_wo[36])
+			_indoorList._swl_4F1L._frame = 16;
+		else if (_wo[80])
+			_indoorList._swl_4F1L._frame = 40;
+	}
+
+	if (!_wo[27] && !_wo[21] && !_wo[24] && !_wo[14] && !_wo[10] && !_wo[31]) {
+		if (_wo[43])
+			_indoorList._swl_4F4R._frame = 23;
+		else if (_wo[87])
+			_indoorList._swl_4F4R._frame = 47;
+	}
+
+	if (!_wo[27] && !_wo[22] && !_wo[19] && !_wo[14] && !_wo[10]) {
+		if (_wo[42])
+			_indoorList._swl_4F3R._frame = 21;
+		else if (_wo[86])
+			_indoorList._swl_4F3R._frame = 45;
+	}
+
+	if (!_wo[27] && !_wo[22] && !_wo[15] && !_wo[5] && !_wo[9]) {
+		if (_wo[41])
+			_indoorList._swl_4F2R._frame = 19;
+		else if (_wo[85])
+			_indoorList._swl_4F2R._frame = 43;
+	}
+
+	if (!_wo[27] && !_wo[22] && !_wo[15] && !_wo[6]) {
+		if (_wo[40])
+			_indoorList._swl_4F1R._frame = 17;
+		else if (_wo[84])
+			_indoorList._swl_4F1R._frame = 41;
+	}
+
+	if (!_wo[25] && !_wo[28] && !_wo[20] && !_wo[11] &&
+		!_wo[16] && !_wo[30] && !_wo[32]) {
+		if (_wo[88])
+			_indoorList._fwl_4F4L._frame = 7;
+		else if (_wo[78])
+			_indoorList._fwl_4F4L._frame = 16;
+		else if (_wo[148])
+			_indoorList._fwl_4F4L._frame = _overallFrame + 1;
+		else if (_wo[108])
+			_indoorList._fwl_4F4L._frame = 8;
+		else if (_wo[168])
+			_indoorList._fwl_4F4L._frame = 10;
+		else if (_wo[128])
+			_indoorList._fwl_4F4L._frame = 9;
+		else if (_wo[34])
+			_indoorList._fwl_4F4L._frame = 0;
+		else if (_wo[188])
+			_indoorList._fwl_4F4L._frame = 15;
+		else if (_wo[208])
+			_indoorList._fwl_4F4L._frame = 14;
+		else if (_wo[228])
+			_indoorList._fwl_4F4L._frame = 6;
+		else if (_wo[248])
+			_indoorList._fwl_4F4L._frame = 11;
+		else if (_wo[268])
+			_indoorList._fwl_4F4L._frame = 12;
+		else if (_wo[288])
+			_indoorList._fwl_4F4L._frame = 13;
+	}
+
+	if (!_wo[26] && !_wo[29] && !_wo[21] && !_wo[13] && !_wo[18] && !_wo[31] && !_wo[33]) {
+		if (_wo[93])
+			_indoorList._fwl_4F4R._frame = 7;
+		else if (_wo[79])
+			_indoorList._fwl_4F4R._frame = 16;
+		else if (_wo[153])
+			_indoorList._fwl_4F4R._frame = _overallFrame + 1;
+		else if (_wo[113])
+			_indoorList._fwl_4F4R._frame = 8;
+		else if (_wo[173])
+			_indoorList._fwl_4F4R._frame = 10;
+		else if (_wo[133])
+			_indoorList._fwl_4F4R._frame = 9;
+		else if (_wo[35])
+			_indoorList._fwl_4F4R._frame = 0;
+		else if (_wo[79])
+			_indoorList._fwl_4F4R._frame = 15;
+		else if (_wo[213])
+			_indoorList._fwl_4F4R._frame = 14;
+		else if (_wo[233])
+			_indoorList._fwl_4F4R._frame = 6;
+		else if (_wo[253])
+			_indoorList._fwl_4F4R._frame = 11;
+		else if (_wo[273])
+			_indoorList._fwl_4F4R._frame = 12;
+		else if (_wo[293])
+			_indoorList._fwl_4F4R._frame = 13;
+	}
+
+	if (!_wo[25] && !_wo[28] && !_wo[20] && !_wo[11] && !_wo[16] && !_wo[30]) {
+		if (_wo[32])
+			_indoorList._swl_3F4L._frame = 14;
+		else if (_wo[76])
+			_indoorList._swl_3F4L._frame = 38;
+	}
+
+	if (!_wo[26] && !_wo[29] && !_wo[21] && !_wo[13] && !_wo[18] && !_wo[31]) {
+		if (_wo[33])
+			_indoorList._fwl_3F1R._frame = 15;
+		else if (_wo[77])
+			_indoorList._swl_3F1R._frame = 39;
+	}
+
+	if (_wo[28] && _wo[27]) {
+	}
+	else if (_wo[28] && _wo[12]) {
+	}
+	else if (_wo[28] && _wo[23]) {
+	}
+	else if (_wo[28] && _wo[8]) {
+	}
+	else if (_wo[25] && _wo[27]) {
+	}
+	else if (_wo[25] && _wo[12]) {
+	}
+	else if (_wo[25] && _wo[23]) {
+	}
+	else if (_wo[25] && _wo[8]) {
+	}
+	else if (_wo[11] && _wo[27]) {
+	}
+	else if (_wo[11] && _wo[12]) {
+	}
+	else if (_wo[11] && _wo[23]) {
+	}
+	else if (_wo[11] && _wo[8]) {
+	}
+	else if (_wo[17] && _wo[27]) {
+	}
+	else if (_wo[17] && _wo[12]) {
+	}
+	else if (_wo[17] && _wo[23]) {
+	}
+	else if (_wo[17] && _wo[8]) {
+	}
+	else if (_wo[20]) {
+	}
+	else if (_wo[30]) {
+		_indoorList._swl_3F3L._frame = 12;
+	}
+	else if (_wo[74]) {
+		_indoorList._swl_3F3L._frame = 36;
+	}
+
+	if (_wo[29] && _wo[27]) {
+	}
+	else if (_wo[29] && _wo[14]) {
+	}
+	else if (_wo[29] && _wo[24]) {
+	}
+	else if (_wo[29] && _wo[10]) {
+	}
+	else if (_wo[26] && _wo[27]) {
+	}
+	else if (_wo[26] && _wo[14]) {
+	}
+	else if (_wo[26] && _wo[24]) {
+	}
+	else if (_wo[26] && _wo[10]) {
+	}
+	else if (_wo[13] && _wo[27]) {
+	}
+	else if (_wo[13] && _wo[14]) {
+	}
+	else if (_wo[13] && _wo[24]) {
+	}
+	else if (_wo[13] && _wo[10]) {
+	}
+	else if (_wo[19] && _wo[27]) {
+	}
+	else if (_wo[19] && _wo[24]) {
+	}
+	else if (_wo[19] && _wo[10]) {
+	}
+	else if (_wo[21]) {
+	}
+	else if (_wo[31]) {
+		_indoorList._swl_3F2R._frame = 13;
+	}
+	else if (_wo[75]) {
+		_indoorList._swl_3F2R._frame = 37;
+	}
+
+	if (!_wo[27] && !_wo[20] && !_wo[12] && !_wo[23] && !_wo[8] && !_wo[30]) {
+		if (_wo[89])
+			_indoorList._fwl_4F3L._frame = 7;
+		else if (_wo[44])
+			_indoorList._fwl_4F3L._frame = 16;
+		else if (_wo[149])
+			_indoorList._fwl_4F3L._frame = _overallFrame + 1;
+		else if (_wo[109])
+			_indoorList._fwl_4F3L._frame = 8;
+		else if (_wo[169])
+			_indoorList._fwl_4F3L._frame = 10;
+		else if (_wo[129])
+			_indoorList._fwl_4F3L._frame = 9;
+		else if (_wo[0])
+			_indoorList._fwl_4F3L._frame = 0;
+		else if (_wo[189])
+			_indoorList._fwl_4F3L._frame = 15;
+		else if (_wo[209])
+			_indoorList._fwl_4F3L._frame = 14;
+		else if (_wo[229])
+			_indoorList._fwl_4F3L._frame = 6;
+		else if (_wo[249])
+			_indoorList._fwl_4F3L._frame = 11;
+		else if (_wo[269])
+			_indoorList._fwl_4F3L._frame = 12;
+		else if (_wo[289])
+			_indoorList._fwl_4F3L._frame = 13;
+	}
+
+	if (_wo[22] && _wo[20]) {
+	}
+	else if (_wo[22] && _wo[23]) {
+	}
+	else if (_wo[20] && _wo[17]) {
+	}
+	else if (_wo[23] && _wo[17]) {
+	}
+	else if (_wo[12]) {
+	}
+	else if (_wo[8]) {
+	}
+	else if (_wo[90]) {
+		_indoorList._fwl_4F2L._frame = 7;
+	}
+	else if (_wo[45])  {
+		_indoorList._fwl_4F2L._frame = 16;
+	}
+	else if (_wo[150]) {
+		_indoorList._fwl_4F2L._frame = _overallFrame + 1;
+	}
+	else if (_wo[110]) {
+		_indoorList._fwl_4F2L._frame = 8;
+	}
+	else if (_wo[170]) {
+		_indoorList._fwl_4F2L._frame = 10;
+	}
+	else if (_wo[130]) {
+		_indoorList._fwl_4F2L._frame = 9;
+	}
+	else if (_wo[1]) {
+		_indoorList._fwl_4F2L._frame = 0;
+	}
+	else if (_wo[190]) {
+		_indoorList._fwl_4F2L._frame = 15;
+	}
+	else if (_wo[210]) {
+		_indoorList._fwl_4F2L._frame = 14;
+	}
+	else if (_wo[230]) {
+		_indoorList._fwl_4F2L._frame = 6;
+	}
+	else if (_wo[250]) {
+		_indoorList._fwl_4F2L._frame = 11;
+	}
+	else if (_wo[270]) {
+		_indoorList._fwl_4F2L._frame = 12;
+	}
+	else if (_wo[290]) {
+		_indoorList._fwl_4F2L._frame = 13;
+	}
+
+	if (_wo[15] && _wo[17]) {
+	}
+	else if (_wo[15] && _wo[12]) {
+	}
+	else if (_wo[12] && _wo[7]) {
+	}
+	else if (_wo[17] && _wo[7]) {
+	}
+	else if (_wo[91]) {
+		_indoorList._fwl_4F1L._frame = 7;
+	}
+	else if (_wo[46]) {
+		_indoorList._fwl_4F1L._frame = 16;
+	}
+	else if (_wo[151]) {
+		_indoorList._fwl_4F1L._frame = _overallFrame + 1;
+	}
+	else if (_wo[111]) {
+		_indoorList._fwl_4F1L._frame = 8;
+	}
+	else if (_wo[171]) {
+		_indoorList._fwl_4F1L._frame = 10;
+	}
+	else if (_wo[131]) {
+		_indoorList._fwl_4F1L._frame = 9;
+	}
+	else if (_wo[2]) {
+		_indoorList._fwl_4F1L._frame = 0;
+	}
+	else if (_wo[191]) {
+		_indoorList._fwl_4F1L._frame = 15;
+	}
+	else if (_wo[211]) {
+		_indoorList._fwl_4F1L._frame = 14;
+	}
+	else if (_wo[231]) {
+		_indoorList._fwl_4F1L._frame = 6;
+	}
+	else if (_wo[251]) {
+		_indoorList._fwl_4F1L._frame = 11;
+	}
+	else if (_wo[271]) {
+		_indoorList._fwl_4F1L._frame = 12;
+	}
+	else if (_wo[291]) {
+		_indoorList._fwl_4F1L._frame = 13;
+	}
+
+	if (!_wo[27] && !_wo[21] && !_wo[14] && !_wo[24] && !_wo[10] && !_wo[31]) {
+		if (_wo[92]) {
+			_indoorList._fwl_4F3R._frame = 7;
+		}
+		else if (_wo[47]) {
+			_indoorList._fwl_4F3R._frame = 16;
+		}
+		else if (_wo[152]) {
+			_indoorList._fwl_4F3R._frame = _overallFrame + 1;
+		}
+		else if (_wo[112]) {
+			_indoorList._fwl_4F3R._frame = 8;
+		}
+		else if (_wo[172]) {
+			_indoorList._fwl_4F3R._frame = 10;
+		}
+		else if (_wo[132]) {
+			_indoorList._fwl_4F3R._frame = 9;
+		}
+		else if (_wo[3]) {
+			_indoorList._fwl_4F3R._frame = 0;
+		}
+		else if (_wo[192]) {
+			_indoorList._fwl_4F3R._frame = 15;
+		}
+		else if (_wo[212]) {
+			_indoorList._fwl_4F3R._frame = 14;
+		}
+		else if (_wo[232]) {
+			_indoorList._fwl_4F3R._frame = 6;
+		}
+		else if (_wo[252]) {
+			_indoorList._fwl_4F3R._frame = 11;
+		}
+		else if (_wo[272]) {
+			_indoorList._fwl_4F3R._frame = 12;
+		}
+		else if (_wo[292]) {
+			_indoorList._fwl_4F3R._frame = 13;
+		}
+	}
+
+	if (_wo[22] && _wo[21]) {
+	}
+	else if (_wo[22] && _wo[24]) {
+	}
+	else if (_wo[21] && _wo[19]) {
+	}
+	else if (_wo[24] && _wo[19]) {
+	}
+	else if (_wo[14] || _wo[10]) {
+	}
+	else if (_wo[94]) {
+		_indoorList._fwl_4F2R._frame = 7;
+	}
+	else if (_wo[48]) {
+		_indoorList._fwl_4F2R._frame = 16;
+	}
+	else if (_wo[154]) {
+		_indoorList._fwl_4F2R._frame = _overallFrame + 1;
+	}
+	else if (_wo[114]) {
+		_indoorList._fwl_4F2R._frame = 8;
+	}
+	else if (_wo[174]) {
+		_indoorList._fwl_4F2R._frame = 10;
+	}
+	else if (_wo[134]) {
+		_indoorList._fwl_4F2R._frame = 9;
+	}
+	else if (_wo[4]) {
+		_indoorList._fwl_4F2R._frame = 0;
+	}
+	else if (_wo[194]) {
+		_indoorList._fwl_4F2R._frame = 15;
+	}
+	else if (_wo[214]) {
+		_indoorList._fwl_4F2R._frame = 14;
+	}
+	else if (_wo[234]) {
+		_indoorList._fwl_4F2R._frame = 6;
+	}
+	else if (_wo[254]) {
+		_indoorList._fwl_4F2R._frame = 11;
+	}
+	else if (_wo[274]) {
+		_indoorList._fwl_4F2R._frame = 12;
+	}
+	else if (_wo[294]) {
+		_indoorList._fwl_4F2R._frame = 13;
+	}
+
+	if (_wo[15] && _wo[19]) {
+	}
+	else if (_wo[15] && _wo[14]) {
+	}
+	else if (_wo[14] && _wo[9]) {
+	}
+	else if (_wo[19] && _wo[9]) {
+	}
+	else if (_wo[95]) {
+		_indoorList._fwl_4F1R._frame = 7;
+	}
+	else if (_wo[49]) {
+		_indoorList._fwl_4F1R._frame = 16;
+	}
+	else if (_wo[155]) {
+		_indoorList._fwl_4F1R._frame = _overallFrame + 1;
+	}
+	else if (_wo[115]) {
+		_indoorList._fwl_4F1R._frame = 8;
+	}
+	else if (_wo[175]) {
+		_indoorList._fwl_4F1R._frame = 10;
+	}
+	else if (_wo[135]) {
+		_indoorList._fwl_4F1R._frame = 9;
+	}
+	else if (_wo[5]) {
+		_indoorList._fwl_4F1R._frame = 0;
+	}
+	else if (_wo[195]) {
+		_indoorList._fwl_4F1R._frame = 15;
+	}
+	else if (_wo[215]) {
+		_indoorList._fwl_4F1R._frame = 14;
+	}
+	else if (_wo[235]) {
+		_indoorList._fwl_4F1R._frame = 6;
+	}
+	else if (_wo[255]) {
+		_indoorList._fwl_4F1R._frame = 11;
+	}
+	else if (_wo[275]) {
+		_indoorList._fwl_4F1R._frame = 12;
+	}
+	else if (_wo[295]) {
+		_indoorList._fwl_4F1R._frame = 13;
+	}
+
+	if (_wo[27] || _wo[22] || _wo[15] || _wo[96]) {
+	}
+	else if (_wo[50]) {
+		_indoorList._fwl_4F._frame = 16;
+	}
+	else if (_wo[156]) {
+		_indoorList._fwl_4F._frame = _overallFrame + 1;
+	}
+	else if (_wo[116]) {
+		_indoorList._fwl_4F._frame = 8;
+	}
+	else if (_wo[176]) {
+		_indoorList._fwl_4F._frame = 10;
+	}
+	else if (_wo[136]) {
+		_indoorList._fwl_4F._frame = 9;
+	}
+	else if (_wo[6]) {
+		_indoorList._fwl_4F._frame = 0;
+	}
+	else if (_wo[196]) {
+		_indoorList._fwl_4F._frame = 15;
+	}
+	else if (_wo[216]) {
+		_indoorList._fwl_4F._frame = 14;
+	}
+	else if (_wo[236]) {
+		_indoorList._fwl_4F._frame = 6;
+	}
+	else if (_wo[256]) {
+		_indoorList._fwl_4F._frame = 11;
+	}
+	else if (_wo[276]) {
+		_indoorList._fwl_4F._frame = 12;
+	}
+	else if (_wo[296]) {
+		_indoorList._fwl_4F._frame = 13;
+	}
+
+	if (!_wo[27] && !_wo[22] && !_wo[15]) {
+		if (_wo[7])
+			_indoorList._swl_3F1L._frame = 8;
+		else if (_wo[51])
+			_indoorList._swl_3F1L._frame = 32;
+	}
+
+	if (_wo[22] && _wo[23]) {
+	}
+	else if (_wo[22] && _wo[20]) {
+	}
+	else if (_wo[17] && _wo[23]) {
+	}
+	else if (_wo[17] && _wo[20]) {
+	}
+	else if (_wo[8]) {
+		_indoorList._swl_3F2L._frame = 10;
+	}
+	else if (_wo[52]) {
+		_indoorList._swl_3F2L._frame = 34;
+	}
+
+	if (_wo[27] || _wo[22] || _wo[15]) {
+	}
+	else if (_wo[9]) {
+		_indoorList._swl_3F4R._frame = 9;
+	}
+	else if (_wo[53]) {
+		_indoorList._swl_3F4R._frame = 33;
+	}
+
+	if (_wo[22] && _wo[24]) {
+	}
+	else if (_wo[22] && _wo[21]) {
+	}
+	else if (_wo[19] && _wo[24]) {
+	}
+	else if (_wo[19] && _wo[21]) {
+	}
+	else if (_wo[14]) {
+	}
+	else if (_wo[10]) {
+		_indoorList._swl_3F3R._frame = 11;
+	}
+	else if (_wo[54]) {
+		_indoorList._swl_3F3R._frame = 35;
+	}
+
+	if (_wo[25] || _wo[28] || _wo[20] || _wo[16]) {
+	}
+	else if (_wo[97]) {
+		_indoorList._fwl_3F2L._frame = 24;
+	}
+	else if (_wo[55]) {
+		_indoorList._fwl_3F2L._frame = 33;
+	}
+	else if (_wo[137]) {
+		_indoorList._fwl_3F2L._frame = 26;
+	}
+	else if (_wo[157]) {
+		_indoorList._fwl_3F2L._frame = _overallFrame + 18;
+	}
+	else if (_wo[117]) {
+		_indoorList._fwl_3F2L._frame = 25;
+	}
+	else if (_wo[177]) {
+		_indoorList._fwl_3F2L._frame = 27;
+	}
+	else if (_wo[11]) {
+		_indoorList._fwl_3F2L._frame = 17;
+	}
+	else if (_wo[197]) {
+		_indoorList._fwl_3F2L._frame = 32;
+	}
+	else if (_wo[217]) {
+		_indoorList._fwl_3F2L._frame = 31;
+	}
+	else if (_wo[237]) {
+		_indoorList._fwl_3F2L._frame = 23;
+	}
+	else if (_wo[257]) {
+		_indoorList._fwl_3F2L._frame = 28;
+	}
+	else if (_wo[277]) {
+		_indoorList._fwl_3F2L._frame = 29;
+	}
+	else if (_wo[297]) {
+		_indoorList._fwl_3F2L._frame = 30;
+	}
+
+	if (_wo[22] && _wo[23]) {
+	}
+	else if (_wo[22] && _wo[20]) {
+	}
+	else if (_wo[23] && _wo[17]) {
+	}
+	else if (_wo[20] && _wo[17]) {
+	}
+	else if (_wo[98]) {
+		_indoorList._fwl_3F1L._frame = 24;
+	}
+	else if (_wo[56]) {
+		_indoorList._fwl_3F1L._frame = 33;
+	}
+	else if (_wo[178]) {
+		_indoorList._fwl_3F1L._frame = 27;
+	}
+	else if (_wo[118]) {
+		_indoorList._fwl_3F1L._frame = 25;
+	}
+	else if (_wo[158]) {
+		_indoorList._fwl_3F1L._frame = _overallFrame + 18;
+	}
+	else if (_wo[138]) {
+		_indoorList._fwl_3F1L._frame = 26;
+	}
+	else if (_wo[12]) {
+		_indoorList._fwl_3F1L._frame = 17;
+	}
+	else if (_wo[198]) {
+		_indoorList._fwl_3F1L._frame = 32;
+	}
+	else if (_wo[218]) {
+		_indoorList._fwl_3F1L._frame = 31;
+	}
+	else if (_wo[238]) {
+		_indoorList._fwl_3F1L._frame = 23;
+	}
+	else if (_wo[258]) {
+		_indoorList._fwl_3F1L._frame = 28;
+	}
+	else if (_wo[278]) {
+		_indoorList._fwl_3F1L._frame = 29;
+	}
+	else if (_wo[298]) {
+		_indoorList._fwl_3F1L._frame = 30;
+	}
+
+	if (_wo[26] || _wo[29] || _wo[21] || _wo[18]) {
+	}
+	else if (_wo[99]) {
+		_indoorList._fwl_3F2R._frame = 24;
+	}
+	else if (_wo[57]) {
+		_indoorList._fwl_3F2R._frame = 33;
+	}
+	else if (_wo[139]) {
+		_indoorList._fwl_3F2R._frame = 26;
+	}
+	else if (_wo[159]) {
+		_indoorList._fwl_3F2R._frame = _overallFrame + 18;
+	}
+	else if (_wo[119]) {
+		_indoorList._fwl_3F2R._frame = 25;
+	}
+	else if (_wo[179]) {
+		_indoorList._fwl_3F2R._frame = 27;
+	}
+	else if (_wo[13]) {
+		_indoorList._fwl_3F2R._frame = 17;
+	}
+	else if (_wo[199]) {
+		_indoorList._fwl_3F2R._frame = 32;
+	}
+	else if (_wo[219]) {
+		_indoorList._fwl_3F2R._frame = 31;
+	}
+	else if (_wo[239]) {
+		_indoorList._fwl_3F2R._frame = 23;
+	}
+	else if (_wo[259]) {
+		_indoorList._fwl_3F2R._frame = 28;
+	}
+	else if (_wo[279]) {
+		_indoorList._fwl_3F2R._frame = 29;
+	}
+	else if (_wo[299]) {
+		_indoorList._fwl_3F2R._frame = 30;
+	}
+
+	if (_wo[22] && _wo[24]) {
+	}
+	else if (_wo[22] && _wo[21]) {
+	}
+	else if (_wo[24] && _wo[19]) {
+	}
+	else if (_wo[21] && _wo[19]) {
+	}
+	else if (_wo[100]) {
+		_indoorList._fwl_3F1R._frame = 24;
+	}
+	else if (_wo[58]) {
+		_indoorList._fwl_3F1R._frame = 33;
+	}
+	else if (_wo[140]) {
+		_indoorList._fwl_3F1R._frame = 26;
+	}
+	else if (_wo[160]) {
+		_indoorList._fwl_3F1R._frame = _overallFrame + 18;
+	}
+	else if (_wo[120]) {
+		_indoorList._fwl_3F1R._frame = 25;
+	}
+	else if (_wo[180]) {
+		_indoorList._fwl_3F1R._frame = 27;
+	}
+	else if (_wo[14]) {
+		_indoorList._fwl_3F1R._frame = 17;
+	}
+	else if (_wo[200]) {
+		_indoorList._fwl_3F1R._frame = 32;
+	}
+	else if (_wo[220]) {
+		_indoorList._fwl_3F1R._frame = 31;
+	}
+	else if (_wo[240]) {
+		_indoorList._fwl_3F1R._frame = 23;
+	}
+	else if (_wo[260]) {
+		_indoorList._fwl_3F1R._frame = 28;
+	}
+	else if (_wo[280]) {
+		_indoorList._fwl_3F1R._frame = 29;
+	}
+	else if (_wo[300]) {
+		_indoorList._fwl_3F1R._frame = 30;
+	}
+
+	if (_wo[22] || _wo[27]) {
+	}
+	else if (_wo[101]) {
+		_indoorList._fwl_3F._frame = 24;
+	}
+	else if (_wo[59]) {
+		_indoorList._fwl_3F._frame = 33;
+	}
+	else if (_wo[141]) {
+		_indoorList._fwl_3F._frame = 26;
+	}
+	else if (_wo[161]) {
+		_indoorList._fwl_3F._frame = _overallFrame + 18;
+	}
+	else if (_wo[121]) {
+		_indoorList._fwl_3F._frame = 25;
+	}
+	else if (_wo[181]) {
+		_indoorList._fwl_3F._frame = 27;
+	}
+	else if (_wo[15]) {
+		_indoorList._fwl_3F._frame = 17;
+	}
+	else if (_wo[201]) {
+		_indoorList._fwl_3F._frame = 32;
+	}
+	else if (_wo[221]) {
+		_indoorList._fwl_3F._frame = 31;
+	}
+	else if (_wo[241]) {
+		_indoorList._fwl_3F._frame = 23;
+	}
+	else if (_wo[261]) {
+		_indoorList._fwl_3F._frame = 28;
+	}
+	else if (_wo[281]) {
+		_indoorList._fwl_3F._frame = 29;
+	}
+	else if (_wo[301]) {
+		_indoorList._fwl_3F._frame = 30;
+	}
+
+	if (_wo[25] || _wo[28] || _wo[20]) {
+	}
+	else if (_wo[16]) {
+		_indoorList._swl_2F2L._frame = 6;
+	}
+	else if (_wo[60]) {
+		_indoorList._swl_2F2L._frame = 30;
+	}
+
+	if (_wo[27] || _wo[22]) {
+	}
+	else if (_wo[17]) {
+		_indoorList._swl_2F1L._frame = 4;
+	}
+	else if (_wo[61]) {
+		_indoorList._swl_2F1L._frame = 28;
+	}
+
+	if (_wo[26] || _wo[29] || _wo[21]) {
+	}
+	else if (_wo[18]) {
+		_indoorList._swl_2F2R._frame = 7;
+	}
+	else if (_wo[62]) {
+		_indoorList._swl_2F2R._frame = 31;
+	}
+
+	if (_wo[27] || _wo[22]) {
+	}
+	else if (_wo[19]) {
+		_indoorList._swl_2F1R._frame = 5;
+	}
+	else if (_wo[63]) {
+		_indoorList._swl_2F1R._frame = 29;
+	}
+
+	if (_wo[27] && _wo[25]) {
+	}
+	else if (_wo[27] && _wo[28]) {
+	}
+	else if (_wo[23] & _wo[25]) {
+	}
+	else if (_wo[23] && _wo[28]) {
+	}
+	else if (_wo[102]) {
+		_indoorList._fwl_2F1L._frame = 7;
+	}
+	else if (_wo[64]) {
+		_indoorList._fwl_2F1L._frame = 16;
+	}
+	else if (_wo[182]) {
+		_indoorList._fwl_2F1L._frame = 10;
+	}
+	else if (_wo[122]) {
+		_indoorList._fwl_2F1L._frame = 8;
+	}
+	else if (_wo[142]) {
+		_indoorList._fwl_2F1L._frame = 9;
+	}
+	else if (_wo[162]) {
+		_indoorList._fwl_2F1L._frame = _overallFrame + 1;
+	}
+	else if (_wo[20]) {
+		_indoorList._fwl_2F1L._frame = 0;
+	}
+	else if (_wo[202]) {
+		_indoorList._fwl_2F1L._frame = 15;
+	}
+	else if (_wo[222]) {
+		_indoorList._fwl_2F1L._frame = 14;
+	}
+	else if (_wo[242]) {
+		_indoorList._fwl_2F1L._frame = 6;
+	}
+	else if (_wo[262]) {
+		_indoorList._fwl_2F1L._frame = 11;
+	}
+	else if (_wo[282]) {
+		_indoorList._fwl_2F1L._frame = 12;
+	}
+	else if (_wo[302]) {
+		_indoorList._fwl_2F1L._frame = 13;
+	}
+
+	if (_wo[27] && _wo[26]) {
+	}
+	else if (_wo[27] && _wo[29]) {
+	}
+	else if (_wo[24] && _wo[26]) {
+	}
+	else if (_wo[24] && _wo[29]) {
+	}
+	else if (_wo[103]) {
+		_indoorList._fwl_2F1R._frame = 7;
+	}
+	else if (_wo[65]) {
+		_indoorList._fwl_2F1R._frame = 16;
+	}
+	else if (_wo[183]) {
+		_indoorList._fwl_2F1R._frame = 10;
+	}
+	else if (_wo[123]) {
+		_indoorList._fwl_2F1R._frame = 8;
+	}
+	else if (_wo[143]) {
+		_indoorList._fwl_2F1R._frame = 9;
+	}
+	else if (_wo[163]) {
+		_indoorList._fwl_2F1R._frame = _overallFrame + 1;
+	}
+	else if (_wo[21]) {
+		_indoorList._fwl_2F1R._frame = 0;
+	}
+	else if (_wo[203]) {
+		_indoorList._fwl_2F1R._frame = 15;
+	}
+	else if (_wo[223]) {
+		_indoorList._fwl_2F1R._frame = 14;
+	}
+	else if (_wo[243]) {
+		_indoorList._fwl_2F1R._frame = 6;
+	}
+	else if (_wo[263]) {
+		_indoorList._fwl_2F1R._frame = 11;
+	}
+	else if (_wo[283]) {
+		_indoorList._fwl_2F1R._frame = 12;
+	}
+	else if (_wo[303]) {
+		_indoorList._fwl_2F1R._frame = 13;
+	}
+
+	if (_wo[27]) {
+
+	}
+	else if (_wo[104]) {
+		_indoorList._fwl_2F._frame = 7;
+	}
+	else if (_wo[66]) {
+		_indoorList._fwl_2F._frame = 16;
+	}
+	else if (_wo[184]) {
+		_indoorList._fwl_2F._frame = 10;
+	}
+	else if (_wo[124]) {
+		_indoorList._fwl_2F._frame = 8;
+	}
+	else if (_wo[144]) {
+		_indoorList._fwl_2F._frame = 9;
+	}
+	else if (_wo[164]) {
+		_indoorList._fwl_2F._frame = _overallFrame + 1;
+	}
+	else if (_wo[22]) {
+		_indoorList._fwl_2F._frame = 0;
+	}
+	else if (_wo[204]) {
+		_indoorList._fwl_2F._frame = 15;
+	}
+	else if (_wo[224]) {
+		_indoorList._fwl_2F._frame = 14;
+	}
+	else if (_wo[244]) {
+		_indoorList._fwl_2F._frame = 6;
+	}
+	else if (_wo[264]) {
+		_indoorList._fwl_2F._frame = 11;
+	}
+	else if (_wo[284]) {
+		_indoorList._fwl_2F._frame = 12;
+	}
+	else if (_wo[304]) {
+		_indoorList._fwl_2F._frame = 13;
+	}
+
+	if (_wo[27]) {
+	}
+	else if (_wo[23]) {
+		_indoorList._swl_1F1L._frame = 2;
+	}
+	else if (_wo[67]) {
+		_indoorList._swl_1F1L._frame = 26;
+	}
+
+	if (_wo[27]) {
+	}
+	else if (_wo[24]) {
+		_indoorList._swl_1F1R._frame = 3;
+	}
+	else if (_wo[68]) {
+		_indoorList._swl_1F1R._frame = 27;
+	}
+
+	if (_wo[28]) {
+	}
+	else if (_wo[105] || _wo[25] || _wo[165] || _wo[125] || _wo[185] || _wo[145]) {
+		_indoorList._fwl_1F1L._frame = 0;
+		_indoorList._fwl_1F1L._sprites = &map._wallSprites._fwl1;
+	}
+	else if (_wo[69]) {
+		_indoorList._fwl_1F1L._frame = 9;
+		_indoorList._fwl_1F1L._sprites = &map._wallSprites._fwl2;
+	}
+
+	if (_wo[29]) {
+	}
+	else if (_wo[106] || _wo[26] || _wo[166] || _wo[126] || _wo[186] || _wo[146]) {
+		_indoorList._fwl_1F._frame = 0;
+		_indoorList._fwl_1F._sprites = &map._wallSprites._fwl1;
+	}
+	else if (_wo[70]) {
+		_indoorList._fwl_1F._frame = 9;
+		_indoorList._fwl_1F._sprites = &map._wallSprites._fwl2;
+	}
+
+	if (_wo[107]) {
+		_indoorList._fwl_1F1R._sprites = &map._wallSprites._fwl2;
+		if (_vm->_openDoor)
+			_indoorList._fwl_1F1R._frame = 0;
+		else
+			_indoorList._fwl_1F1R._frame = map.mazeData()._wallKind ? 1 : 10;
+	}
+	else if (_wo[71]) {
+		_indoorList._fwl_1F1R._frame = 9;
+		_indoorList._fwl_1F1R._sprites = &map._wallSprites._fwl2;
+	}
+	else if (_wo[167]) {
+		_indoorList._fwl_1F1R._frame = _overallFrame + 1;
+		_indoorList._fwl_1F1R._sprites = &map._wallSprites._fwl2;
+	}
+	else if (_wo[127]) {
+		_indoorList._fwl_1F1R._frame = 1;
+		_indoorList._fwl_1F1R._sprites = &map._wallSprites._fwl2;
+	}
+	else if (_wo[147]) {
+		_indoorList._fwl_1F1R._frame = 2;
+		_indoorList._fwl_1F1R._sprites = &map._wallSprites._fwl2;
+	}
+	else if (_wo[187]) {
+		_indoorList._fwl_1F1R._frame = 3;
+		_indoorList._fwl_1F1R._sprites = &map._wallSprites._fwl2;
+	}
+	else if (_wo[27]) {
+		_indoorList._fwl_1F1R._frame = 0;
+		_indoorList._fwl_1F1R._sprites = &map._wallSprites._fwl1;
+	}
+	else if (_wo[207]) {
+		_indoorList._fwl_1F1R._frame = 8;
+		_indoorList._fwl_1F1R._sprites = &map._wallSprites._fwl2;
+	}
+	else if (_wo[227]) {
+		_indoorList._fwl_1F1R._frame = 7;
+		_indoorList._fwl_1F1R._sprites = &map._wallSprites._fwl2;
+	}
+	else if (_wo[247]) {
+		_indoorList._fwl_1F1R._frame = 6;
+		_indoorList._fwl_1F1R._sprites = &map._wallSprites._fwl1;
+	}
+	else if (_wo[267]) {
+		_indoorList._fwl_1F1R._frame = 4;
+		_indoorList._fwl_1F1R._sprites = &map._wallSprites._fwl2;
+	}
+	else if (_wo[287]) {
+		_indoorList._fwl_1F1R._frame = 5;
+		_indoorList._fwl_1F1R._sprites = &map._wallSprites._fwl2;
+	}
+	else if (_wo[307]) {
+		_indoorList._fwl_1F1R._frame = 6;
+		_indoorList._fwl_1F1R._sprites = &map._wallSprites._fwl2;
+	}
+
+	if (_wo[28]) {
+		_indoorList._swl_0F1L._frame = 0;
+	}
+	else if (_wo[72]) {
+		_indoorList._swl_0F1L._frame = 24;
+	}
+
+	if (_wo[29]) {
+		_indoorList._swl_0F1R._frame = 1;
+	}
+	else if (_wo[73]) {
+		_indoorList._swl_0F1R._frame = 25;
+	}
+
+	map.cellFlagLookup(_vm->_party._mazePosition);
+
+	// WORKAROUND: Original did an array lookup on _skySprites.
+	// Was this a feature for multiple skys that was abandoned?
+	_indoorList[0]._sprites = &map._skySprites;
+	_indoorList[0]._flags = _flipSky ? SPRFLAG_HORIZ_FLIPPED : 0;
+
+	if (_vm->_openDoor) {
+		Common::Point pt(
+			_vm->_party._mazePosition.x + SCREEN_POSITIONING_X[
+				_vm->_party._mazeDirection][_vm->_party._mazePosition.x],
+			_vm->_party._mazePosition.y + SCREEN_POSITIONING_Y[
+				_vm->_party._mazeDirection][_vm->_party._mazePosition.y]
+			);
+		map.cellFlagLookup(pt);
+		
+		_indoorList._sky._sprites = &map._skySprites;
+	} else {
+		_indoorList._sky._sprites = _indoorList[0]._sprites;
+	}
+
+	_indoorList._sky._flags = _flipSky ? SPRFLAG_HORIZ_FLIPPED : 0;
+	_indoorList._ground._flags = _flipGround ? SPRFLAG_HORIZ_FLIPPED : 0;
+	_indoorList._horizon._frame = 7;
+
+	// Finally draw the darn indoor scene
+	_vm->_screen->_windows[3].drawList(&_indoorList[0], _indoorList.size());
+
+	// Check for any character shooting
+	_isShooting = false;
+	for (int i = 0; i < _vm->_party._partyCount; ++i) {
+		if (_vm->_combat->_shooting[i])
+			_isShooting = true;
+	}
+	
+	_charsShooting = _isShooting;
+
+	// TODO
+}
+
+} // End of namespace Xeen
diff --git a/engines/xeen/interface_map.h b/engines/xeen/interface_map.h
new file mode 100644
index 0000000..01cd1d2
--- /dev/null
+++ b/engines/xeen/interface_map.h
@@ -0,0 +1,118 @@
+/* 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_INTERFACE_MAP_H
+#define XEEN_INTERFACE_MAP_H
+
+#include "common/scummsys.h"
+#include "xeen/screen.h"
+
+namespace Xeen {
+
+class XeenEngine;
+
+class OutdoorDrawList {
+public:
+	DrawStruct _data[132];
+	DrawStruct &_skySprite;
+	DrawStruct &_groundSprite;
+public:
+	OutdoorDrawList();
+
+	DrawStruct &operator[](int idx) { 
+		assert(idx < size());
+		return _data[idx]; 
+	}
+
+	int size() const { return 132; }
+};
+
+class IndoorDrawList {
+public:
+	DrawStruct _data[170];
+	DrawStruct &_sky;
+	DrawStruct &_ground;
+	DrawStruct &_horizon;
+	DrawStruct &_swl_0F1R, _swl_0F1L, _swl_1F1R, _swl_1F1L,
+		_swl_2F2R, _swl_2F1R, _swl_2F1L, _swl_2F2L,
+		_swl_3F1R, _swl_3F2R, _swl_3F3R, _swl_3F4R,
+		_swl_3F1L, _swl_3F2L, _swl_3F3L, _swl_3F4L,
+		_swl_4F4R, _swl_4F3R, _swl_4F2R, _swl_4F1R,
+		_swl_4F1L, _swl_4F2L, _swl_4F3L, _swl_4F4L;
+	DrawStruct &_fwl_4F4R, _fwl_4F3R, _fwl_4F2R, _fwl_4F1R,
+		_fwl_4F, _fwl_4F1L, _fwl_4F2L, _fwl_4F3L, _fwl_4F4L;
+	DrawStruct &_fwl_2F1R, _fwl_2F, _fwl_2F1L, _fwl_3F2R,
+		_fwl_3F1R, _fwl_3F, _fwl_3F1L, _fwl_3F2L;
+	DrawStruct &_fwl_1F, _fwl_1F1R, _fwl_1F1L;
+	DrawStruct &_objects0, _objects1, _objects2, _objects3;
+	DrawStruct &_objects4, _objects5, _objects6, _objects7;
+	DrawStruct &_objects8, _objects9, _objects10, _objects11;
+public:
+	IndoorDrawList();
+
+	DrawStruct &operator[](int idx) { 
+		assert(idx < size());
+		return _data[idx]; 
+	}
+
+	int size() const { return 170; }
+};
+
+
+class InterfaceMap {
+private:
+	XeenEngine *_vm;
+
+	void initDrawStructs();
+protected:
+	byte _wp[20];
+	byte _wo[308];
+	int _overallFrame;
+	bool _flipWtr;
+	bool _flipWall;
+	bool _flipSky;
+	bool _flipGround;
+	bool _isShooting;
+	bool _charsShooting;
+	int _objNumber;
+public:
+	OutdoorDrawList _outdoorList;
+	IndoorDrawList _indoorList;
+public:
+	InterfaceMap(XeenEngine *vm);
+
+	void setIndoorsMonsters();
+
+	void setIndoorObjects();
+
+	void setIndoorWallPics();
+
+	void drawIndoors();
+
+	void setOutdoorsMonsters();
+
+	void setOutdoorsObjects();
+};
+
+} // End of namespace Xeen
+
+#endif /* XEEN_INTERFACE_MAP_H */
diff --git a/engines/xeen/module.mk b/engines/xeen/module.mk
index 2c22322..d6b8097 100644
--- a/engines/xeen/module.mk
+++ b/engines/xeen/module.mk
@@ -14,6 +14,7 @@ MODULE_OBJS := \
 	files.o \
 	font.o \
 	interface.o \
+	interface_map.o \
 	items.o \
 	map.o \
 	party.o \


Commit: 17f946305cfeeaa03b070510798c79437fe055ef
    https://github.com/scummvm/scummvm/commit/17f946305cfeeaa03b070510798c79437fe055ef
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-01-14T20:48:40-05:00

Commit Message:
XEEN: Formatting fixes

Changed paths:
    engines/xeen/interface_map.cpp



diff --git a/engines/xeen/interface_map.cpp b/engines/xeen/interface_map.cpp
index d88f942..af52178 100644
--- a/engines/xeen/interface_map.cpp
+++ b/engines/xeen/interface_map.cpp
@@ -582,8 +582,7 @@ void InterfaceMap::drawIndoors() {
 		if (surfaceId == 5 || surfaceId == 12) {
 			drawStruct._flags = _flipWtr;
 			drawStruct._frame = DRAW_FRAMES[cellIndex][_flipWtr ? 1 : 0];
-		}
-		else {
+		} else {
 			drawStruct._frame = DRAW_FRAMES[cellIndex][_flipWall ? 1 : 0];
 			drawStruct._flags = _flipWall ? 0 : SPRFLAG_HORIZ_FLIPPED;
 		}
@@ -719,82 +718,47 @@ void InterfaceMap::drawIndoors() {
 	}
 
 	if (_wo[28] && _wo[27]) {
-	}
-	else if (_wo[28] && _wo[12]) {
-	}
-	else if (_wo[28] && _wo[23]) {
-	}
-	else if (_wo[28] && _wo[8]) {
-	}
-	else if (_wo[25] && _wo[27]) {
-	}
-	else if (_wo[25] && _wo[12]) {
-	}
-	else if (_wo[25] && _wo[23]) {
-	}
-	else if (_wo[25] && _wo[8]) {
-	}
-	else if (_wo[11] && _wo[27]) {
-	}
-	else if (_wo[11] && _wo[12]) {
-	}
-	else if (_wo[11] && _wo[23]) {
-	}
-	else if (_wo[11] && _wo[8]) {
-	}
-	else if (_wo[17] && _wo[27]) {
-	}
-	else if (_wo[17] && _wo[12]) {
-	}
-	else if (_wo[17] && _wo[23]) {
-	}
-	else if (_wo[17] && _wo[8]) {
-	}
-	else if (_wo[20]) {
-	}
-	else if (_wo[30]) {
+	} else if (_wo[28] && _wo[12]) {
+	} else if (_wo[28] && _wo[23]) {
+	} else if (_wo[28] && _wo[8]) {
+	} else if (_wo[25] && _wo[27]) {
+	} else if (_wo[25] && _wo[12]) {
+	} else if (_wo[25] && _wo[23]) {
+	} else if (_wo[25] && _wo[8]) {
+	} else if (_wo[11] && _wo[27]) {
+	} else if (_wo[11] && _wo[12]) {
+	} else if (_wo[11] && _wo[23]) {
+	} else if (_wo[11] && _wo[8]) {
+	} else if (_wo[17] && _wo[27]) {
+	} else if (_wo[17] && _wo[12]) {
+	} else if (_wo[17] && _wo[23]) {
+	} else if (_wo[17] && _wo[8]) {
+	} else if (_wo[20]) {
+	} else if (_wo[30]) {
 		_indoorList._swl_3F3L._frame = 12;
-	}
-	else if (_wo[74]) {
+	} else if (_wo[74]) {
 		_indoorList._swl_3F3L._frame = 36;
 	}
 
 	if (_wo[29] && _wo[27]) {
-	}
-	else if (_wo[29] && _wo[14]) {
-	}
-	else if (_wo[29] && _wo[24]) {
-	}
-	else if (_wo[29] && _wo[10]) {
-	}
-	else if (_wo[26] && _wo[27]) {
-	}
-	else if (_wo[26] && _wo[14]) {
-	}
-	else if (_wo[26] && _wo[24]) {
-	}
-	else if (_wo[26] && _wo[10]) {
-	}
-	else if (_wo[13] && _wo[27]) {
-	}
-	else if (_wo[13] && _wo[14]) {
-	}
-	else if (_wo[13] && _wo[24]) {
-	}
-	else if (_wo[13] && _wo[10]) {
-	}
-	else if (_wo[19] && _wo[27]) {
-	}
-	else if (_wo[19] && _wo[24]) {
-	}
-	else if (_wo[19] && _wo[10]) {
-	}
-	else if (_wo[21]) {
-	}
-	else if (_wo[31]) {
+	} else if (_wo[29] && _wo[14]) {
+	} else if (_wo[29] && _wo[24]) {
+	} else if (_wo[29] && _wo[10]) {
+	} else if (_wo[26] && _wo[27]) {
+	} else if (_wo[26] && _wo[14]) {
+	} else if (_wo[26] && _wo[24]) {
+	} else if (_wo[26] && _wo[10]) {
+	} else if (_wo[13] && _wo[27]) {
+	} else if (_wo[13] && _wo[14]) {
+	} else if (_wo[13] && _wo[24]) {
+	} else if (_wo[13] && _wo[10]) {
+	} else if (_wo[19] && _wo[27]) {
+	} else if (_wo[19] && _wo[24]) {
+	} else if (_wo[19] && _wo[10]) {
+	} else if (_wo[21]) {
+	} else if (_wo[31]) {
 		_indoorList._swl_3F2R._frame = 13;
-	}
-	else if (_wo[75]) {
+	} else if (_wo[75]) {
 		_indoorList._swl_3F2R._frame = 37;
 	}
 
@@ -828,281 +792,190 @@ void InterfaceMap::drawIndoors() {
 	}
 
 	if (_wo[22] && _wo[20]) {
-	}
-	else if (_wo[22] && _wo[23]) {
-	}
-	else if (_wo[20] && _wo[17]) {
-	}
-	else if (_wo[23] && _wo[17]) {
-	}
-	else if (_wo[12]) {
-	}
-	else if (_wo[8]) {
-	}
-	else if (_wo[90]) {
+	} else if (_wo[22] && _wo[23]) {
+	} else if (_wo[20] && _wo[17]) {
+	} else if (_wo[23] && _wo[17]) {
+	} else if (_wo[12]) {
+	} else if (_wo[8]) {
+	} else if (_wo[90]) {
 		_indoorList._fwl_4F2L._frame = 7;
-	}
-	else if (_wo[45])  {
+	} else if (_wo[45])  {
 		_indoorList._fwl_4F2L._frame = 16;
-	}
-	else if (_wo[150]) {
+	} else if (_wo[150]) {
 		_indoorList._fwl_4F2L._frame = _overallFrame + 1;
-	}
-	else if (_wo[110]) {
+	} else if (_wo[110]) {
 		_indoorList._fwl_4F2L._frame = 8;
-	}
-	else if (_wo[170]) {
+	} else if (_wo[170]) {
 		_indoorList._fwl_4F2L._frame = 10;
-	}
-	else if (_wo[130]) {
+	} else if (_wo[130]) {
 		_indoorList._fwl_4F2L._frame = 9;
-	}
-	else if (_wo[1]) {
+	} else if (_wo[1]) {
 		_indoorList._fwl_4F2L._frame = 0;
-	}
-	else if (_wo[190]) {
+	} else if (_wo[190]) {
 		_indoorList._fwl_4F2L._frame = 15;
-	}
-	else if (_wo[210]) {
+	} else if (_wo[210]) {
 		_indoorList._fwl_4F2L._frame = 14;
-	}
-	else if (_wo[230]) {
+	} else if (_wo[230]) {
 		_indoorList._fwl_4F2L._frame = 6;
-	}
-	else if (_wo[250]) {
+	} else if (_wo[250]) {
 		_indoorList._fwl_4F2L._frame = 11;
-	}
-	else if (_wo[270]) {
+	} else if (_wo[270]) {
 		_indoorList._fwl_4F2L._frame = 12;
-	}
-	else if (_wo[290]) {
+	} else if (_wo[290]) {
 		_indoorList._fwl_4F2L._frame = 13;
 	}
 
 	if (_wo[15] && _wo[17]) {
-	}
-	else if (_wo[15] && _wo[12]) {
-	}
-	else if (_wo[12] && _wo[7]) {
-	}
-	else if (_wo[17] && _wo[7]) {
-	}
-	else if (_wo[91]) {
+	} else if (_wo[15] && _wo[12]) {
+	} else if (_wo[12] && _wo[7]) {
+	} else if (_wo[17] && _wo[7]) {
+	} else if (_wo[91]) {
 		_indoorList._fwl_4F1L._frame = 7;
-	}
-	else if (_wo[46]) {
+	} else if (_wo[46]) {
 		_indoorList._fwl_4F1L._frame = 16;
-	}
-	else if (_wo[151]) {
+	} else if (_wo[151]) {
 		_indoorList._fwl_4F1L._frame = _overallFrame + 1;
-	}
-	else if (_wo[111]) {
+	} else if (_wo[111]) {
 		_indoorList._fwl_4F1L._frame = 8;
-	}
-	else if (_wo[171]) {
+	} else if (_wo[171]) {
 		_indoorList._fwl_4F1L._frame = 10;
-	}
-	else if (_wo[131]) {
+	} else if (_wo[131]) {
 		_indoorList._fwl_4F1L._frame = 9;
-	}
-	else if (_wo[2]) {
+	} else if (_wo[2]) {
 		_indoorList._fwl_4F1L._frame = 0;
-	}
-	else if (_wo[191]) {
+	} else if (_wo[191]) {
 		_indoorList._fwl_4F1L._frame = 15;
-	}
-	else if (_wo[211]) {
+	} else if (_wo[211]) {
 		_indoorList._fwl_4F1L._frame = 14;
-	}
-	else if (_wo[231]) {
+	} else if (_wo[231]) {
 		_indoorList._fwl_4F1L._frame = 6;
-	}
-	else if (_wo[251]) {
+	} else if (_wo[251]) {
 		_indoorList._fwl_4F1L._frame = 11;
-	}
-	else if (_wo[271]) {
+	} else if (_wo[271]) {
 		_indoorList._fwl_4F1L._frame = 12;
-	}
-	else if (_wo[291]) {
+	} else if (_wo[291]) {
 		_indoorList._fwl_4F1L._frame = 13;
 	}
 
 	if (!_wo[27] && !_wo[21] && !_wo[14] && !_wo[24] && !_wo[10] && !_wo[31]) {
 		if (_wo[92]) {
 			_indoorList._fwl_4F3R._frame = 7;
-		}
-		else if (_wo[47]) {
+		} else if (_wo[47]) {
 			_indoorList._fwl_4F3R._frame = 16;
-		}
-		else if (_wo[152]) {
+		} else if (_wo[152]) {
 			_indoorList._fwl_4F3R._frame = _overallFrame + 1;
-		}
-		else if (_wo[112]) {
+		} else if (_wo[112]) {
 			_indoorList._fwl_4F3R._frame = 8;
-		}
-		else if (_wo[172]) {
+		} else if (_wo[172]) {
 			_indoorList._fwl_4F3R._frame = 10;
-		}
-		else if (_wo[132]) {
+		} else if (_wo[132]) {
 			_indoorList._fwl_4F3R._frame = 9;
-		}
-		else if (_wo[3]) {
+		} else if (_wo[3]) {
 			_indoorList._fwl_4F3R._frame = 0;
-		}
-		else if (_wo[192]) {
+		} else if (_wo[192]) {
 			_indoorList._fwl_4F3R._frame = 15;
-		}
-		else if (_wo[212]) {
+		} else if (_wo[212]) {
 			_indoorList._fwl_4F3R._frame = 14;
-		}
-		else if (_wo[232]) {
+		} else if (_wo[232]) {
 			_indoorList._fwl_4F3R._frame = 6;
-		}
-		else if (_wo[252]) {
+		} else if (_wo[252]) {
 			_indoorList._fwl_4F3R._frame = 11;
-		}
-		else if (_wo[272]) {
+		} else if (_wo[272]) {
 			_indoorList._fwl_4F3R._frame = 12;
-		}
-		else if (_wo[292]) {
+		} else if (_wo[292]) {
 			_indoorList._fwl_4F3R._frame = 13;
 		}
 	}
 
 	if (_wo[22] && _wo[21]) {
-	}
-	else if (_wo[22] && _wo[24]) {
-	}
-	else if (_wo[21] && _wo[19]) {
-	}
-	else if (_wo[24] && _wo[19]) {
-	}
-	else if (_wo[14] || _wo[10]) {
-	}
-	else if (_wo[94]) {
+	} else if (_wo[22] && _wo[24]) {
+	} else if (_wo[21] && _wo[19]) {
+	} else if (_wo[24] && _wo[19]) {
+	} else if (_wo[14] || _wo[10]) {
+	} else if (_wo[94]) {
 		_indoorList._fwl_4F2R._frame = 7;
-	}
-	else if (_wo[48]) {
+	} else if (_wo[48]) {
 		_indoorList._fwl_4F2R._frame = 16;
-	}
-	else if (_wo[154]) {
+	} else if (_wo[154]) {
 		_indoorList._fwl_4F2R._frame = _overallFrame + 1;
-	}
-	else if (_wo[114]) {
+	} else if (_wo[114]) {
 		_indoorList._fwl_4F2R._frame = 8;
-	}
-	else if (_wo[174]) {
+	} else if (_wo[174]) {
 		_indoorList._fwl_4F2R._frame = 10;
-	}
-	else if (_wo[134]) {
+	} else if (_wo[134]) {
 		_indoorList._fwl_4F2R._frame = 9;
-	}
-	else if (_wo[4]) {
+	} else if (_wo[4]) {
 		_indoorList._fwl_4F2R._frame = 0;
-	}
-	else if (_wo[194]) {
+	} else if (_wo[194]) {
 		_indoorList._fwl_4F2R._frame = 15;
-	}
-	else if (_wo[214]) {
+	} else if (_wo[214]) {
 		_indoorList._fwl_4F2R._frame = 14;
-	}
-	else if (_wo[234]) {
+	} else if (_wo[234]) {
 		_indoorList._fwl_4F2R._frame = 6;
-	}
-	else if (_wo[254]) {
+	} else if (_wo[254]) {
 		_indoorList._fwl_4F2R._frame = 11;
-	}
-	else if (_wo[274]) {
+	} else if (_wo[274]) {
 		_indoorList._fwl_4F2R._frame = 12;
-	}
-	else if (_wo[294]) {
+	} else if (_wo[294]) {
 		_indoorList._fwl_4F2R._frame = 13;
 	}
 
 	if (_wo[15] && _wo[19]) {
-	}
-	else if (_wo[15] && _wo[14]) {
-	}
-	else if (_wo[14] && _wo[9]) {
-	}
-	else if (_wo[19] && _wo[9]) {
-	}
-	else if (_wo[95]) {
+	} else if (_wo[15] && _wo[14]) {
+	} else if (_wo[14] && _wo[9]) {
+	} else if (_wo[19] && _wo[9]) {
+	} else if (_wo[95]) {
 		_indoorList._fwl_4F1R._frame = 7;
-	}
-	else if (_wo[49]) {
+	} else if (_wo[49]) {
 		_indoorList._fwl_4F1R._frame = 16;
-	}
-	else if (_wo[155]) {
+	} else if (_wo[155]) {
 		_indoorList._fwl_4F1R._frame = _overallFrame + 1;
-	}
-	else if (_wo[115]) {
+	} else if (_wo[115]) {
 		_indoorList._fwl_4F1R._frame = 8;
-	}
-	else if (_wo[175]) {
+	} else if (_wo[175]) {
 		_indoorList._fwl_4F1R._frame = 10;
-	}
-	else if (_wo[135]) {
+	} else if (_wo[135]) {
 		_indoorList._fwl_4F1R._frame = 9;
-	}
-	else if (_wo[5]) {
+	} else if (_wo[5]) {
 		_indoorList._fwl_4F1R._frame = 0;
-	}
-	else if (_wo[195]) {
+	} else if (_wo[195]) {
 		_indoorList._fwl_4F1R._frame = 15;
-	}
-	else if (_wo[215]) {
+	} else if (_wo[215]) {
 		_indoorList._fwl_4F1R._frame = 14;
-	}
-	else if (_wo[235]) {
+	} else if (_wo[235]) {
 		_indoorList._fwl_4F1R._frame = 6;
-	}
-	else if (_wo[255]) {
+	} else if (_wo[255]) {
 		_indoorList._fwl_4F1R._frame = 11;
-	}
-	else if (_wo[275]) {
+	} else if (_wo[275]) {
 		_indoorList._fwl_4F1R._frame = 12;
-	}
-	else if (_wo[295]) {
+	} else if (_wo[295]) {
 		_indoorList._fwl_4F1R._frame = 13;
 	}
 
 	if (_wo[27] || _wo[22] || _wo[15] || _wo[96]) {
-	}
-	else if (_wo[50]) {
+	} else if (_wo[50]) {
 		_indoorList._fwl_4F._frame = 16;
-	}
-	else if (_wo[156]) {
+	} else if (_wo[156]) {
 		_indoorList._fwl_4F._frame = _overallFrame + 1;
-	}
-	else if (_wo[116]) {
+	} else if (_wo[116]) {
 		_indoorList._fwl_4F._frame = 8;
-	}
-	else if (_wo[176]) {
+	} else if (_wo[176]) {
 		_indoorList._fwl_4F._frame = 10;
-	}
-	else if (_wo[136]) {
+	} else if (_wo[136]) {
 		_indoorList._fwl_4F._frame = 9;
-	}
-	else if (_wo[6]) {
+	} else if (_wo[6]) {
 		_indoorList._fwl_4F._frame = 0;
-	}
-	else if (_wo[196]) {
+	} else if (_wo[196]) {
 		_indoorList._fwl_4F._frame = 15;
-	}
-	else if (_wo[216]) {
+	} else if (_wo[216]) {
 		_indoorList._fwl_4F._frame = 14;
-	}
-	else if (_wo[236]) {
+	} else if (_wo[236]) {
 		_indoorList._fwl_4F._frame = 6;
-	}
-	else if (_wo[256]) {
+	} else if (_wo[256]) {
 		_indoorList._fwl_4F._frame = 11;
-	}
-	else if (_wo[276]) {
+	} else if (_wo[276]) {
 		_indoorList._fwl_4F._frame = 12;
-	}
-	else if (_wo[296]) {
+	} else if (_wo[296]) {
 		_indoorList._fwl_4F._frame = 13;
 	}
 
@@ -1114,479 +987,333 @@ void InterfaceMap::drawIndoors() {
 	}
 
 	if (_wo[22] && _wo[23]) {
-	}
-	else if (_wo[22] && _wo[20]) {
-	}
-	else if (_wo[17] && _wo[23]) {
-	}
-	else if (_wo[17] && _wo[20]) {
-	}
-	else if (_wo[8]) {
+	} else if (_wo[22] && _wo[20]) {
+	} else if (_wo[17] && _wo[23]) {
+	} else if (_wo[17] && _wo[20]) {
+	} else if (_wo[8]) {
 		_indoorList._swl_3F2L._frame = 10;
-	}
-	else if (_wo[52]) {
+	} else if (_wo[52]) {
 		_indoorList._swl_3F2L._frame = 34;
 	}
 
 	if (_wo[27] || _wo[22] || _wo[15]) {
-	}
-	else if (_wo[9]) {
+	} else if (_wo[9]) {
 		_indoorList._swl_3F4R._frame = 9;
-	}
-	else if (_wo[53]) {
+	} else if (_wo[53]) {
 		_indoorList._swl_3F4R._frame = 33;
 	}
 
 	if (_wo[22] && _wo[24]) {
-	}
-	else if (_wo[22] && _wo[21]) {
-	}
-	else if (_wo[19] && _wo[24]) {
-	}
-	else if (_wo[19] && _wo[21]) {
-	}
-	else if (_wo[14]) {
-	}
-	else if (_wo[10]) {
+	} else if (_wo[22] && _wo[21]) {
+	} else if (_wo[19] && _wo[24]) {
+	} else if (_wo[19] && _wo[21]) {
+	} else if (_wo[14]) {
+	} else if (_wo[10]) {
 		_indoorList._swl_3F3R._frame = 11;
-	}
-	else if (_wo[54]) {
+	} else if (_wo[54]) {
 		_indoorList._swl_3F3R._frame = 35;
 	}
 
 	if (_wo[25] || _wo[28] || _wo[20] || _wo[16]) {
-	}
-	else if (_wo[97]) {
+	} else if (_wo[97]) {
 		_indoorList._fwl_3F2L._frame = 24;
-	}
-	else if (_wo[55]) {
+	} else if (_wo[55]) {
 		_indoorList._fwl_3F2L._frame = 33;
-	}
-	else if (_wo[137]) {
+	} else if (_wo[137]) {
 		_indoorList._fwl_3F2L._frame = 26;
-	}
-	else if (_wo[157]) {
+	} else if (_wo[157]) {
 		_indoorList._fwl_3F2L._frame = _overallFrame + 18;
-	}
-	else if (_wo[117]) {
+	} else if (_wo[117]) {
 		_indoorList._fwl_3F2L._frame = 25;
-	}
-	else if (_wo[177]) {
+	} else if (_wo[177]) {
 		_indoorList._fwl_3F2L._frame = 27;
-	}
-	else if (_wo[11]) {
+	} else if (_wo[11]) {
 		_indoorList._fwl_3F2L._frame = 17;
-	}
-	else if (_wo[197]) {
+	} else if (_wo[197]) {
 		_indoorList._fwl_3F2L._frame = 32;
-	}
-	else if (_wo[217]) {
+	} else if (_wo[217]) {
 		_indoorList._fwl_3F2L._frame = 31;
-	}
-	else if (_wo[237]) {
+	} else if (_wo[237]) {
 		_indoorList._fwl_3F2L._frame = 23;
-	}
-	else if (_wo[257]) {
+	} else if (_wo[257]) {
 		_indoorList._fwl_3F2L._frame = 28;
-	}
-	else if (_wo[277]) {
+	} else if (_wo[277]) {
 		_indoorList._fwl_3F2L._frame = 29;
-	}
-	else if (_wo[297]) {
+	} else if (_wo[297]) {
 		_indoorList._fwl_3F2L._frame = 30;
 	}
 
 	if (_wo[22] && _wo[23]) {
-	}
-	else if (_wo[22] && _wo[20]) {
-	}
-	else if (_wo[23] && _wo[17]) {
-	}
-	else if (_wo[20] && _wo[17]) {
-	}
-	else if (_wo[98]) {
+	} else if (_wo[22] && _wo[20]) {
+	} else if (_wo[23] && _wo[17]) {
+	} else if (_wo[20] && _wo[17]) {
+	} else if (_wo[98]) {
 		_indoorList._fwl_3F1L._frame = 24;
-	}
-	else if (_wo[56]) {
+	} else if (_wo[56]) {
 		_indoorList._fwl_3F1L._frame = 33;
-	}
-	else if (_wo[178]) {
+	} else if (_wo[178]) {
 		_indoorList._fwl_3F1L._frame = 27;
-	}
-	else if (_wo[118]) {
+	} else if (_wo[118]) {
 		_indoorList._fwl_3F1L._frame = 25;
-	}
-	else if (_wo[158]) {
+	} else if (_wo[158]) {
 		_indoorList._fwl_3F1L._frame = _overallFrame + 18;
-	}
-	else if (_wo[138]) {
+	} else if (_wo[138]) {
 		_indoorList._fwl_3F1L._frame = 26;
-	}
-	else if (_wo[12]) {
+	} else if (_wo[12]) {
 		_indoorList._fwl_3F1L._frame = 17;
-	}
-	else if (_wo[198]) {
+	} else if (_wo[198]) {
 		_indoorList._fwl_3F1L._frame = 32;
-	}
-	else if (_wo[218]) {
+	} else if (_wo[218]) {
 		_indoorList._fwl_3F1L._frame = 31;
-	}
-	else if (_wo[238]) {
+	} else if (_wo[238]) {
 		_indoorList._fwl_3F1L._frame = 23;
-	}
-	else if (_wo[258]) {
+	} else if (_wo[258]) {
 		_indoorList._fwl_3F1L._frame = 28;
-	}
-	else if (_wo[278]) {
+	} else if (_wo[278]) {
 		_indoorList._fwl_3F1L._frame = 29;
-	}
-	else if (_wo[298]) {
+	} else if (_wo[298]) {
 		_indoorList._fwl_3F1L._frame = 30;
 	}
 
 	if (_wo[26] || _wo[29] || _wo[21] || _wo[18]) {
-	}
-	else if (_wo[99]) {
+	} else if (_wo[99]) {
 		_indoorList._fwl_3F2R._frame = 24;
-	}
-	else if (_wo[57]) {
+	} else if (_wo[57]) {
 		_indoorList._fwl_3F2R._frame = 33;
-	}
-	else if (_wo[139]) {
+	} else if (_wo[139]) {
 		_indoorList._fwl_3F2R._frame = 26;
-	}
-	else if (_wo[159]) {
+	} else if (_wo[159]) {
 		_indoorList._fwl_3F2R._frame = _overallFrame + 18;
-	}
-	else if (_wo[119]) {
+	} else if (_wo[119]) {
 		_indoorList._fwl_3F2R._frame = 25;
-	}
-	else if (_wo[179]) {
+	} else if (_wo[179]) {
 		_indoorList._fwl_3F2R._frame = 27;
-	}
-	else if (_wo[13]) {
+	} else if (_wo[13]) {
 		_indoorList._fwl_3F2R._frame = 17;
-	}
-	else if (_wo[199]) {
+	} else if (_wo[199]) {
 		_indoorList._fwl_3F2R._frame = 32;
-	}
-	else if (_wo[219]) {
+	} else if (_wo[219]) {
 		_indoorList._fwl_3F2R._frame = 31;
-	}
-	else if (_wo[239]) {
+	} else if (_wo[239]) {
 		_indoorList._fwl_3F2R._frame = 23;
-	}
-	else if (_wo[259]) {
+	} else if (_wo[259]) {
 		_indoorList._fwl_3F2R._frame = 28;
-	}
-	else if (_wo[279]) {
+	} else if (_wo[279]) {
 		_indoorList._fwl_3F2R._frame = 29;
-	}
-	else if (_wo[299]) {
+	} else if (_wo[299]) {
 		_indoorList._fwl_3F2R._frame = 30;
 	}
 
 	if (_wo[22] && _wo[24]) {
-	}
-	else if (_wo[22] && _wo[21]) {
-	}
-	else if (_wo[24] && _wo[19]) {
-	}
-	else if (_wo[21] && _wo[19]) {
-	}
-	else if (_wo[100]) {
+	} else if (_wo[22] && _wo[21]) {
+	} else if (_wo[24] && _wo[19]) {
+	} else if (_wo[21] && _wo[19]) {
+	} else if (_wo[100]) {
 		_indoorList._fwl_3F1R._frame = 24;
-	}
-	else if (_wo[58]) {
+	} else if (_wo[58]) {
 		_indoorList._fwl_3F1R._frame = 33;
-	}
-	else if (_wo[140]) {
+	} else if (_wo[140]) {
 		_indoorList._fwl_3F1R._frame = 26;
-	}
-	else if (_wo[160]) {
+	} else if (_wo[160]) {
 		_indoorList._fwl_3F1R._frame = _overallFrame + 18;
-	}
-	else if (_wo[120]) {
+	} else if (_wo[120]) {
 		_indoorList._fwl_3F1R._frame = 25;
-	}
-	else if (_wo[180]) {
+	} else if (_wo[180]) {
 		_indoorList._fwl_3F1R._frame = 27;
-	}
-	else if (_wo[14]) {
+	} else if (_wo[14]) {
 		_indoorList._fwl_3F1R._frame = 17;
-	}
-	else if (_wo[200]) {
+	} else if (_wo[200]) {
 		_indoorList._fwl_3F1R._frame = 32;
-	}
-	else if (_wo[220]) {
+	} else if (_wo[220]) {
 		_indoorList._fwl_3F1R._frame = 31;
-	}
-	else if (_wo[240]) {
+	} else if (_wo[240]) {
 		_indoorList._fwl_3F1R._frame = 23;
-	}
-	else if (_wo[260]) {
+	} else if (_wo[260]) {
 		_indoorList._fwl_3F1R._frame = 28;
-	}
-	else if (_wo[280]) {
+	} else if (_wo[280]) {
 		_indoorList._fwl_3F1R._frame = 29;
-	}
-	else if (_wo[300]) {
+	} else if (_wo[300]) {
 		_indoorList._fwl_3F1R._frame = 30;
 	}
 
 	if (_wo[22] || _wo[27]) {
-	}
-	else if (_wo[101]) {
+	} else if (_wo[101]) {
 		_indoorList._fwl_3F._frame = 24;
-	}
-	else if (_wo[59]) {
+	} else if (_wo[59]) {
 		_indoorList._fwl_3F._frame = 33;
-	}
-	else if (_wo[141]) {
+	} else if (_wo[141]) {
 		_indoorList._fwl_3F._frame = 26;
-	}
-	else if (_wo[161]) {
+	} else if (_wo[161]) {
 		_indoorList._fwl_3F._frame = _overallFrame + 18;
-	}
-	else if (_wo[121]) {
+	} else if (_wo[121]) {
 		_indoorList._fwl_3F._frame = 25;
-	}
-	else if (_wo[181]) {
+	} else if (_wo[181]) {
 		_indoorList._fwl_3F._frame = 27;
-	}
-	else if (_wo[15]) {
+	} else if (_wo[15]) {
 		_indoorList._fwl_3F._frame = 17;
-	}
-	else if (_wo[201]) {
+	} else if (_wo[201]) {
 		_indoorList._fwl_3F._frame = 32;
-	}
-	else if (_wo[221]) {
+	} else if (_wo[221]) {
 		_indoorList._fwl_3F._frame = 31;
-	}
-	else if (_wo[241]) {
+	} else if (_wo[241]) {
 		_indoorList._fwl_3F._frame = 23;
-	}
-	else if (_wo[261]) {
+	} else if (_wo[261]) {
 		_indoorList._fwl_3F._frame = 28;
-	}
-	else if (_wo[281]) {
+	} else if (_wo[281]) {
 		_indoorList._fwl_3F._frame = 29;
-	}
-	else if (_wo[301]) {
+	} else if (_wo[301]) {
 		_indoorList._fwl_3F._frame = 30;
 	}
 
 	if (_wo[25] || _wo[28] || _wo[20]) {
-	}
-	else if (_wo[16]) {
+	} else if (_wo[16]) {
 		_indoorList._swl_2F2L._frame = 6;
-	}
-	else if (_wo[60]) {
+	} else if (_wo[60]) {
 		_indoorList._swl_2F2L._frame = 30;
 	}
 
 	if (_wo[27] || _wo[22]) {
-	}
-	else if (_wo[17]) {
+	} else if (_wo[17]) {
 		_indoorList._swl_2F1L._frame = 4;
-	}
-	else if (_wo[61]) {
+	} else if (_wo[61]) {
 		_indoorList._swl_2F1L._frame = 28;
 	}
 
 	if (_wo[26] || _wo[29] || _wo[21]) {
-	}
-	else if (_wo[18]) {
+	} else if (_wo[18]) {
 		_indoorList._swl_2F2R._frame = 7;
-	}
-	else if (_wo[62]) {
+	} else if (_wo[62]) {
 		_indoorList._swl_2F2R._frame = 31;
 	}
 
 	if (_wo[27] || _wo[22]) {
-	}
-	else if (_wo[19]) {
+	} else if (_wo[19]) {
 		_indoorList._swl_2F1R._frame = 5;
-	}
-	else if (_wo[63]) {
+	} else if (_wo[63]) {
 		_indoorList._swl_2F1R._frame = 29;
 	}
 
 	if (_wo[27] && _wo[25]) {
-	}
-	else if (_wo[27] && _wo[28]) {
-	}
-	else if (_wo[23] & _wo[25]) {
-	}
-	else if (_wo[23] && _wo[28]) {
-	}
-	else if (_wo[102]) {
+	} else if (_wo[27] && _wo[28]) {
+	} else if (_wo[23] & _wo[25]) {
+	} else if (_wo[23] && _wo[28]) {
+	} else if (_wo[102]) {
 		_indoorList._fwl_2F1L._frame = 7;
-	}
-	else if (_wo[64]) {
+	} else if (_wo[64]) {
 		_indoorList._fwl_2F1L._frame = 16;
-	}
-	else if (_wo[182]) {
+	} else if (_wo[182]) {
 		_indoorList._fwl_2F1L._frame = 10;
-	}
-	else if (_wo[122]) {
+	} else if (_wo[122]) {
 		_indoorList._fwl_2F1L._frame = 8;
-	}
-	else if (_wo[142]) {
+	} else if (_wo[142]) {
 		_indoorList._fwl_2F1L._frame = 9;
-	}
-	else if (_wo[162]) {
+	} else if (_wo[162]) {
 		_indoorList._fwl_2F1L._frame = _overallFrame + 1;
-	}
-	else if (_wo[20]) {
+	} else if (_wo[20]) {
 		_indoorList._fwl_2F1L._frame = 0;
-	}
-	else if (_wo[202]) {
+	} else if (_wo[202]) {
 		_indoorList._fwl_2F1L._frame = 15;
-	}
-	else if (_wo[222]) {
+	} else if (_wo[222]) {
 		_indoorList._fwl_2F1L._frame = 14;
-	}
-	else if (_wo[242]) {
+	} else if (_wo[242]) {
 		_indoorList._fwl_2F1L._frame = 6;
-	}
-	else if (_wo[262]) {
+	} else if (_wo[262]) {
 		_indoorList._fwl_2F1L._frame = 11;
-	}
-	else if (_wo[282]) {
+	} else if (_wo[282]) {
 		_indoorList._fwl_2F1L._frame = 12;
-	}
-	else if (_wo[302]) {
+	} else if (_wo[302]) {
 		_indoorList._fwl_2F1L._frame = 13;
 	}
 
 	if (_wo[27] && _wo[26]) {
-	}
-	else if (_wo[27] && _wo[29]) {
-	}
-	else if (_wo[24] && _wo[26]) {
-	}
-	else if (_wo[24] && _wo[29]) {
-	}
-	else if (_wo[103]) {
+	} else if (_wo[27] && _wo[29]) {
+	} else if (_wo[24] && _wo[26]) {
+	} else if (_wo[24] && _wo[29]) {
+	} else if (_wo[103]) {
 		_indoorList._fwl_2F1R._frame = 7;
-	}
-	else if (_wo[65]) {
+	} else if (_wo[65]) {
 		_indoorList._fwl_2F1R._frame = 16;
-	}
-	else if (_wo[183]) {
+	} else if (_wo[183]) {
 		_indoorList._fwl_2F1R._frame = 10;
-	}
-	else if (_wo[123]) {
+	} else if (_wo[123]) {
 		_indoorList._fwl_2F1R._frame = 8;
-	}
-	else if (_wo[143]) {
+	} else if (_wo[143]) {
 		_indoorList._fwl_2F1R._frame = 9;
-	}
-	else if (_wo[163]) {
+	} else if (_wo[163]) {
 		_indoorList._fwl_2F1R._frame = _overallFrame + 1;
-	}
-	else if (_wo[21]) {
+	} else if (_wo[21]) {
 		_indoorList._fwl_2F1R._frame = 0;
-	}
-	else if (_wo[203]) {
+	} else if (_wo[203]) {
 		_indoorList._fwl_2F1R._frame = 15;
-	}
-	else if (_wo[223]) {
+	} else if (_wo[223]) {
 		_indoorList._fwl_2F1R._frame = 14;
-	}
-	else if (_wo[243]) {
+	} else if (_wo[243]) {
 		_indoorList._fwl_2F1R._frame = 6;
-	}
-	else if (_wo[263]) {
+	} else if (_wo[263]) {
 		_indoorList._fwl_2F1R._frame = 11;
-	}
-	else if (_wo[283]) {
+	} else if (_wo[283]) {
 		_indoorList._fwl_2F1R._frame = 12;
-	}
-	else if (_wo[303]) {
+	} else if (_wo[303]) {
 		_indoorList._fwl_2F1R._frame = 13;
 	}
 
 	if (_wo[27]) {
-
-	}
-	else if (_wo[104]) {
+	} else if (_wo[104]) {
 		_indoorList._fwl_2F._frame = 7;
-	}
-	else if (_wo[66]) {
+	} else if (_wo[66]) {
 		_indoorList._fwl_2F._frame = 16;
-	}
-	else if (_wo[184]) {
+	} else if (_wo[184]) {
 		_indoorList._fwl_2F._frame = 10;
-	}
-	else if (_wo[124]) {
+	} else if (_wo[124]) {
 		_indoorList._fwl_2F._frame = 8;
-	}
-	else if (_wo[144]) {
+	} else if (_wo[144]) {
 		_indoorList._fwl_2F._frame = 9;
-	}
-	else if (_wo[164]) {
+	} else if (_wo[164]) {
 		_indoorList._fwl_2F._frame = _overallFrame + 1;
-	}
-	else if (_wo[22]) {
+	} else if (_wo[22]) {
 		_indoorList._fwl_2F._frame = 0;
-	}
-	else if (_wo[204]) {
+	} else if (_wo[204]) {
 		_indoorList._fwl_2F._frame = 15;
-	}
-	else if (_wo[224]) {
+	} else if (_wo[224]) {
 		_indoorList._fwl_2F._frame = 14;
-	}
-	else if (_wo[244]) {
+	} else if (_wo[244]) {
 		_indoorList._fwl_2F._frame = 6;
-	}
-	else if (_wo[264]) {
+	} else if (_wo[264]) {
 		_indoorList._fwl_2F._frame = 11;
-	}
-	else if (_wo[284]) {
+	} else if (_wo[284]) {
 		_indoorList._fwl_2F._frame = 12;
-	}
-	else if (_wo[304]) {
+	} else if (_wo[304]) {
 		_indoorList._fwl_2F._frame = 13;
 	}
 
 	if (_wo[27]) {
-	}
-	else if (_wo[23]) {
+	} else if (_wo[23]) {
 		_indoorList._swl_1F1L._frame = 2;
-	}
-	else if (_wo[67]) {
+	} else if (_wo[67]) {
 		_indoorList._swl_1F1L._frame = 26;
 	}
 
 	if (_wo[27]) {
-	}
-	else if (_wo[24]) {
+	} else if (_wo[24]) {
 		_indoorList._swl_1F1R._frame = 3;
-	}
-	else if (_wo[68]) {
+	} else if (_wo[68]) {
 		_indoorList._swl_1F1R._frame = 27;
 	}
 
 	if (_wo[28]) {
-	}
-	else if (_wo[105] || _wo[25] || _wo[165] || _wo[125] || _wo[185] || _wo[145]) {
+	} else if (_wo[105] || _wo[25] || _wo[165] || _wo[125] || _wo[185] || _wo[145]) {
 		_indoorList._fwl_1F1L._frame = 0;
 		_indoorList._fwl_1F1L._sprites = &map._wallSprites._fwl1;
-	}
-	else if (_wo[69]) {
+	} else if (_wo[69]) {
 		_indoorList._fwl_1F1L._frame = 9;
 		_indoorList._fwl_1F1L._sprites = &map._wallSprites._fwl2;
 	}
 
 	if (_wo[29]) {
-	}
-	else if (_wo[106] || _wo[26] || _wo[166] || _wo[126] || _wo[186] || _wo[146]) {
+	} else if (_wo[106] || _wo[26] || _wo[166] || _wo[126] || _wo[186] || _wo[146]) {
 		_indoorList._fwl_1F._frame = 0;
 		_indoorList._fwl_1F._sprites = &map._wallSprites._fwl1;
-	}
-	else if (_wo[70]) {
+	} else if (_wo[70]) {
 		_indoorList._fwl_1F._frame = 9;
 		_indoorList._fwl_1F._sprites = &map._wallSprites._fwl2;
 	}
@@ -1597,67 +1324,53 @@ void InterfaceMap::drawIndoors() {
 			_indoorList._fwl_1F1R._frame = 0;
 		else
 			_indoorList._fwl_1F1R._frame = map.mazeData()._wallKind ? 1 : 10;
-	}
-	else if (_wo[71]) {
+	} else if (_wo[71]) {
 		_indoorList._fwl_1F1R._frame = 9;
 		_indoorList._fwl_1F1R._sprites = &map._wallSprites._fwl2;
-	}
-	else if (_wo[167]) {
+	} else if (_wo[167]) {
 		_indoorList._fwl_1F1R._frame = _overallFrame + 1;
 		_indoorList._fwl_1F1R._sprites = &map._wallSprites._fwl2;
-	}
-	else if (_wo[127]) {
+	} else if (_wo[127]) {
 		_indoorList._fwl_1F1R._frame = 1;
 		_indoorList._fwl_1F1R._sprites = &map._wallSprites._fwl2;
-	}
-	else if (_wo[147]) {
+	} else if (_wo[147]) {
 		_indoorList._fwl_1F1R._frame = 2;
 		_indoorList._fwl_1F1R._sprites = &map._wallSprites._fwl2;
-	}
-	else if (_wo[187]) {
+	} else if (_wo[187]) {
 		_indoorList._fwl_1F1R._frame = 3;
 		_indoorList._fwl_1F1R._sprites = &map._wallSprites._fwl2;
-	}
-	else if (_wo[27]) {
+	} else if (_wo[27]) {
 		_indoorList._fwl_1F1R._frame = 0;
 		_indoorList._fwl_1F1R._sprites = &map._wallSprites._fwl1;
-	}
-	else if (_wo[207]) {
+	} else if (_wo[207]) {
 		_indoorList._fwl_1F1R._frame = 8;
 		_indoorList._fwl_1F1R._sprites = &map._wallSprites._fwl2;
-	}
-	else if (_wo[227]) {
+	} else if (_wo[227]) {
 		_indoorList._fwl_1F1R._frame = 7;
 		_indoorList._fwl_1F1R._sprites = &map._wallSprites._fwl2;
-	}
-	else if (_wo[247]) {
+	} else if (_wo[247]) {
 		_indoorList._fwl_1F1R._frame = 6;
 		_indoorList._fwl_1F1R._sprites = &map._wallSprites._fwl1;
-	}
-	else if (_wo[267]) {
+	} else if (_wo[267]) {
 		_indoorList._fwl_1F1R._frame = 4;
 		_indoorList._fwl_1F1R._sprites = &map._wallSprites._fwl2;
-	}
-	else if (_wo[287]) {
+	} else if (_wo[287]) {
 		_indoorList._fwl_1F1R._frame = 5;
 		_indoorList._fwl_1F1R._sprites = &map._wallSprites._fwl2;
-	}
-	else if (_wo[307]) {
+	} else if (_wo[307]) {
 		_indoorList._fwl_1F1R._frame = 6;
 		_indoorList._fwl_1F1R._sprites = &map._wallSprites._fwl2;
 	}
 
 	if (_wo[28]) {
 		_indoorList._swl_0F1L._frame = 0;
-	}
-	else if (_wo[72]) {
+	} else if (_wo[72]) {
 		_indoorList._swl_0F1L._frame = 24;
 	}
 
 	if (_wo[29]) {
 		_indoorList._swl_0F1R._frame = 1;
-	}
-	else if (_wo[73]) {
+	} else if (_wo[73]) {
 		_indoorList._swl_0F1R._frame = 25;
 	}
 


Commit: 7bfbda627a589817022f12b739ff6cc652ccfee5
    https://github.com/scummvm/scummvm/commit/7bfbda627a589817022f12b739ff6cc652ccfee5
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-01-14T22:10:32-05:00

Commit Message:
XEEN: Initial bugfixes for map loading and fix draw list positions

Changed paths:
    engines/xeen/interface.cpp
    engines/xeen/interface.h
    engines/xeen/interface_map.cpp
    engines/xeen/map.cpp
    engines/xeen/screen.cpp



diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp
index deb8761..4550dac 100644
--- a/engines/xeen/interface.cpp
+++ b/engines/xeen/interface.cpp
@@ -542,7 +542,7 @@ void Interface::draw3d(bool updateFlag) {
 	Map &map = *_vm->_map;
 	Screen &screen = *_vm->_screen;
 
-	if (!screen._windows[11]._enabled)
+	if (screen._windows[11]._enabled)
 		return;
 
 	_flipUIFrame = (_flipUIFrame + 1) % 4;
diff --git a/engines/xeen/interface.h b/engines/xeen/interface.h
index 4667592..df06f5d 100644
--- a/engines/xeen/interface.h
+++ b/engines/xeen/interface.h
@@ -101,9 +101,6 @@ private:
 
 	void updateAutoMap();
 public:
-	OutdoorDrawList _outdoorList;
-	IndoorDrawList _indoorList;
-public:
 	Interface(XeenEngine *vm);
 
 	void setup();
diff --git a/engines/xeen/interface_map.cpp b/engines/xeen/interface_map.cpp
index af52178..cc99b3e 100644
--- a/engines/xeen/interface_map.cpp
+++ b/engines/xeen/interface_map.cpp
@@ -56,31 +56,31 @@ OutdoorDrawList::OutdoorDrawList() : _skySprite(_data[1]), _groundSprite(_data[2
 	_data[25] = DrawStruct(0, 8, 109);
 	_data[26] = DrawStruct(0, 201, 109);
 	_data[27] = DrawStruct(0, 8, 109);
-	_data[28] = DrawStruct(1, 65472, 61, 14, SPRFLAG_2000);
-	_data[29] = DrawStruct(1, 65496, 61, 14, 0);
-	_data[30] = DrawStruct(1, 65520, 61, 14, 0);
+	_data[28] = DrawStruct(1, -64, 61, 14, SPRFLAG_2000);
+	_data[29] = DrawStruct(1, -40, 61, 14, 0);
+	_data[30] = DrawStruct(1, -16, 61, 14, 0);
 	_data[31] = DrawStruct(1, 8, 61, 14, 0);
 	_data[32] = DrawStruct(1, 128, 61, 14, SPRFLAG_HORIZ_FLIPPED | SPRFLAG_2000);
 	_data[33] = DrawStruct(1, 104, 61, 14, SPRFLAG_HORIZ_FLIPPED);
 	_data[34] = DrawStruct(1, 80, 61, 14, SPRFLAG_HORIZ_FLIPPED);
 	_data[35] = DrawStruct(1, 56, 61, 14, SPRFLAG_HORIZ_FLIPPED);
 	_data[36] = DrawStruct(1, 32, 61, 14, 0);
-	_data[37] = DrawStruct(0, 65527, 61, 14, 0);
-	_data[38] = DrawStruct(0, 65478, 61, 14, 0);
+	_data[37] = DrawStruct(0, -9, 61, 14, 0);
+	_data[38] = DrawStruct(0, -58, 61, 14, 0);
 	_data[39] = DrawStruct(0, 40, 61, 14, 0);
-	_data[40] = DrawStruct(0, 65454, 61, 14, 0);
+	_data[40] = DrawStruct(0, -82, 61, 14, 0);
 	_data[41] = DrawStruct(0, 64, 61, 14, 0);
-	_data[42] = DrawStruct(0, 65495, 61, 14, 0);
-	_data[43] = DrawStruct(0, 65510, 61, 14, 0);
-	_data[44] = DrawStruct(0, 65502, 61, 14, 0);
-	_data[45] = DrawStruct(0, 65520, 61, 14, 0);
+	_data[42] = DrawStruct(0, -41, 61, 14, 0);
+	_data[43] = DrawStruct(0, -26, 61, 14, 0);
+	_data[44] = DrawStruct(0, -34, 61, 14, 0);
+	_data[45] = DrawStruct(0, -16, 61, 14, 0);
 	_data[46] = DrawStruct(0, 23, 61, 14, 0);
 	_data[47] = DrawStruct(0, 16, 61, 14, 0);
-	_data[48] = DrawStruct(0, 65478, 61, 14, 0);
+	_data[48] = DrawStruct(0, -58, 61, 14, 0);
 	_data[49] = DrawStruct(0, 40, 61, 14, 0);
-	_data[50] = DrawStruct(0, 65519, 61, 14, 0);
-	_data[51] = DrawStruct(0, 65535, 58, 14, 0);
-	_data[52] = DrawStruct(0, 65527, 58, 14, 0);
+	_data[50] = DrawStruct(0, -17, 61, 14, 0);
+	_data[51] = DrawStruct(0, -1, 58, 14, 0);
+	_data[52] = DrawStruct(0, -9, 58, 14, 0);
 	_data[53] = DrawStruct(0, 72, 58, 12, 0);
 	_data[54] = DrawStruct(0, 72, 58, 12, SPRFLAG_HORIZ_FLIPPED);
 	_data[55] = DrawStruct(0, 69, 63, 12, 0);
@@ -89,21 +89,21 @@ OutdoorDrawList::OutdoorDrawList() : _skySprite(_data[1]), _groundSprite(_data[2
 	_data[58] = DrawStruct(0, 71, 53, 12, SPRFLAG_HORIZ_FLIPPED);
 	_data[59] = DrawStruct(0, 80, 57, 12, 0);
 	_data[60] = DrawStruct(0, 64, 57, 12, SPRFLAG_HORIZ_FLIPPED);
-	_data[61] = DrawStruct(2, 65525, 54, 8, 0);
-	_data[62] = DrawStruct(1, 65515, 54, 11, 0);
+	_data[61] = DrawStruct(2, -11, 54, 8, 0);
+	_data[62] = DrawStruct(1, -21, 54, 11, 0);
 	_data[63] = DrawStruct(2, 165, 54, 8, SPRFLAG_HORIZ_FLIPPED);
 	_data[64] = DrawStruct(1, 86, 54, 11, SPRFLAG_HORIZ_FLIPPED);
 	_data[65] = DrawStruct(1, 33, 54, 11, 0);
-	_data[66] = DrawStruct(0, 65528, 54, 12, 0);
-	_data[67] = DrawStruct(0, 65463, 54, 12, 0);
+	_data[66] = DrawStruct(0, -8, 54, 12, 0);
+	_data[67] = DrawStruct(0, -73, 54, 12, 0);
 	_data[68] = DrawStruct(0, 57, 54, 12, 0);
-	_data[69] = DrawStruct(0, 65471, 54, 12, 0);
-	_data[70] = DrawStruct(0, 65455, 54, 12, 0);
+	_data[69] = DrawStruct(0, -65, 54, 12, 0);
+	_data[70] = DrawStruct(0, -81, 54, 12, 0);
 	_data[71] = DrawStruct(0, 49, 54, 12, 0);
 	_data[72] = DrawStruct(0, 65, 54, 12, 0);
-	_data[73] = DrawStruct(0, 65512, 54, 12, 0);
+	_data[73] = DrawStruct(0, -24, 54, 12, 0);
 	_data[74] = DrawStruct(0, 9, 50, 12, 0);
-	_data[75] = DrawStruct(0, 65528, 50, 12, 0);
+	_data[75] = DrawStruct(0, -8, 50, 12, 0);
 	_data[76] = DrawStruct(0, 72, 53, 8, 0);
 	_data[77] = DrawStruct(0, 72, 53, 8, SPRFLAG_HORIZ_FLIPPED);
 	_data[78] = DrawStruct(0, 77, 58, 8, 0);
@@ -115,14 +115,14 @@ OutdoorDrawList::OutdoorDrawList() : _skySprite(_data[1]), _groundSprite(_data[2
 	_data[84] = DrawStruct(2, 8, 40);
 	_data[85] = DrawStruct(2, 146, 40, 0, SPRFLAG_HORIZ_FLIPPED);
 	_data[86] = DrawStruct(1, 32, 40, 6, 0);
-	_data[87] = DrawStruct(0, 65529, 30, 7, 0);
-	_data[88] = DrawStruct(0, 65424, 30, 7, SPRFLAG_2000);
+	_data[87] = DrawStruct(0, -7, 30, 7, 0);
+	_data[88] = DrawStruct(0, -112, 30, 7, SPRFLAG_2000);
 	_data[89] = DrawStruct(0, 98, 30, 7, SPRFLAG_2000);
-	_data[90] = DrawStruct(0, 65424, 30, 8, SPRFLAG_2000);
+	_data[90] = DrawStruct(0, -112, 30, 8, SPRFLAG_2000);
 	_data[91] = DrawStruct(0, 98, 30, 8, SPRFLAG_2000);
-	_data[92] = DrawStruct(0, 65498, 30, 8, 0);
+	_data[92] = DrawStruct(0, -38, 30, 8, 0);
 	_data[93] = DrawStruct(0, 25, 30, 8, 0);
-	_data[94] = DrawStruct(0, 65529, 30, 8, 0);
+	_data[94] = DrawStruct(0, -7, 30, 8, 0);
 	_data[95] = DrawStruct(0, 72, 48, 4, 0);
 	_data[96] = DrawStruct(0, 72, 48, 4, SPRFLAG_HORIZ_FLIPPED);
 	_data[97] = DrawStruct(0, 85, 53, 4, 0);
@@ -134,22 +134,22 @@ OutdoorDrawList::OutdoorDrawList() : _skySprite(_data[1]), _groundSprite(_data[2
 	_data[103] = DrawStruct(0, 8, 24);
 	_data[104] = DrawStruct(0, 169, 24, 0, SPRFLAG_HORIZ_FLIPPED);
 	_data[105] = DrawStruct(1, 32, 24);
-	_data[106] = DrawStruct(0, 65513, 40, 0, SPRFLAG_2000);
+	_data[106] = DrawStruct(0, -23, 40, 0, SPRFLAG_2000);
 	_data[107] = DrawStruct(0, 200, 40, 0, SPRFLAG_HORIZ_FLIPPED | SPRFLAG_2000);
 	_data[108] = DrawStruct(0, 8, 47);
 	_data[109] = DrawStruct(0, 169, 47, 0, SPRFLAG_HORIZ_FLIPPED);
-	_data[110] = DrawStruct(1, 65480, 65532, 32768, SPRFLAG_4000 | SPRFLAG_2000);
-	_data[111] = DrawStruct(0, 65531, 2, 0, SPRFLAG_4000 | SPRFLAG_2000);
-	_data[112] = DrawStruct(0, 65469, 2, 0, SPRFLAG_4000 | SPRFLAG_2000);
+	_data[110] = DrawStruct(1, -56, -4, 0x8000, SPRFLAG_4000 | SPRFLAG_2000);
+	_data[111] = DrawStruct(0, -5, 2, 0, SPRFLAG_4000 | SPRFLAG_2000);
+	_data[112] = DrawStruct(0, -67, 2, 0, SPRFLAG_4000 | SPRFLAG_2000);
 	_data[113] = DrawStruct(0, 44, 73);
 	_data[114] = DrawStruct(0, 44, 73);
 	_data[115] = DrawStruct(0, 58, 14, 0, SPRFLAG_4000 | SPRFLAG_2000);
 	_data[116] = DrawStruct(0, 169, 73);
 	_data[117] = DrawStruct(0, 169, 73);
-	_data[118] = DrawStruct(0, 65531, 14, 0, SPRFLAG_4000 | SPRFLAG_2000);
+	_data[118] = DrawStruct(0, -5, 14, 0, SPRFLAG_4000 | SPRFLAG_2000);
 	_data[119] = DrawStruct(0, 110, 73);
 	_data[120] = DrawStruct(0, 110, 73);
-	_data[121] = DrawStruct(0, 65531, 14, 0, SPRFLAG_4000 | SPRFLAG_2000);
+	_data[121] = DrawStruct(0, -5, 14, 0, SPRFLAG_4000 | SPRFLAG_2000);
 	_data[122] = DrawStruct(0, 110, 73);
 	_data[123] = DrawStruct(0, 110, 73);
 	_data[124] = DrawStruct(0, 72, 43);
@@ -232,31 +232,31 @@ IndoorDrawList::IndoorDrawList() :
 	_data[43] = DrawStruct(14, 152, 60);
 	_data[44] = DrawStruct(8, 176, 60);
 	_data[45] = DrawStruct(8, 200, 60);
-	_data[46] = DrawStruct(0, 65472, 61, 14, 0);
-	_data[47] = DrawStruct(0, 65496, 61, 14, 0);
-	_data[48] = DrawStruct(0, 65520, 61, 14, 0);
+	_data[46] = DrawStruct(0, -64, 61, 14, 0);
+	_data[47] = DrawStruct(0, -40, 61, 14, 0);
+	_data[48] = DrawStruct(0, -16, 61, 14, 0);
 	_data[49] = DrawStruct(0, 8, 61, 14, 0);
 	_data[50] = DrawStruct(0, 32, 61, 14, 0);
 	_data[51] = DrawStruct(0, 56, 61, 14, 0);
 	_data[52] = DrawStruct(0, 80, 61, 14, 0);
 	_data[53] = DrawStruct(0, 104, 61, 14, 0);
 	_data[54] = DrawStruct(0, 128, 61, 14, 0);
-	_data[55] = DrawStruct(0, 65527, 58, 14, 0);
-	_data[56] = DrawStruct(0, 65502, 58, 14, 0);
+	_data[55] = DrawStruct(0, -9, 58, 14, 0);
+	_data[56] = DrawStruct(0, -34, 58, 14, 0);
 	_data[57] = DrawStruct(0, 16, 58, 14, 0);
-	_data[58] = DrawStruct(0, 65478, 58, 14, 0);
+	_data[58] = DrawStruct(0, -58, 58, 14, 0);
 	_data[59] = DrawStruct(0, 40, 58, 14, 0);
-	_data[60] = DrawStruct(0, 65495, 58, 14, 0);
-	_data[61] = DrawStruct(0, 65510, 58, 14, 0);
-	_data[62] = DrawStruct(0, 65502, 58, 14, 0);
-	_data[63] = DrawStruct(0, 65520, 58, 14, 0);
+	_data[60] = DrawStruct(0, -41, 58, 14, 0);
+	_data[61] = DrawStruct(0, -26, 58, 14, 0);
+	_data[62] = DrawStruct(0, -34, 58, 14, 0);
+	_data[63] = DrawStruct(0, -16, 58, 14, 0);
 	_data[64] = DrawStruct(0, 23, 58, 14, 0);
 	_data[65] = DrawStruct(0, 16, 58, 14, 0);
-	_data[66] = DrawStruct(0, 65478, 58, 14, 0);
+	_data[66] = DrawStruct(0, -58, 58, 14, 0);
 	_data[67] = DrawStruct(0, 40, 58, 14, 0);
-	_data[68] = DrawStruct(0, 65519, 58, 14, 0);
-	_data[69] = DrawStruct(0, 65535, 58, 14, 0);
-	_data[70] = DrawStruct(0, 65527, 58, 14, 0);
+	_data[68] = DrawStruct(0, -17, 58, 14, 0);
+	_data[69] = DrawStruct(0, -1, 58, 14, 0);
+	_data[70] = DrawStruct(0, -9, 58, 14, 0);
 	_data[71] = DrawStruct(14, 8, 58);
 	_data[72] = DrawStruct(12, 8, 55);
 	_data[73] = DrawStruct(10, 32, 52);
@@ -273,26 +273,26 @@ IndoorDrawList::IndoorDrawList() :
 	_data[84] = DrawStruct(0, 71, 53, 12, SPRFLAG_HORIZ_FLIPPED);
 	_data[85] = DrawStruct(0, 80, 57, 12, 0);
 	_data[86] = DrawStruct(0, 64, 57, 12, SPRFLAG_HORIZ_FLIPPED);
-	_data[87] = DrawStruct(7, 65512, 52, 0, SPRFLAG_2000);
+	_data[87] = DrawStruct(7, -24, 52, 0, SPRFLAG_2000);
 	_data[88] = DrawStruct(7, 32, 52);
 	_data[89] = DrawStruct(7, 88, 52);
 	_data[90] = DrawStruct(0, 144, 52);
 	_data[91] = DrawStruct(0, 200, 52, 0, SPRFLAG_2000);
-	_data[92] = DrawStruct(0, 65457, 52, 11, SPRFLAG_2000);
-	_data[93] = DrawStruct(0, 65509, 52, 11, 0);
+	_data[92] = DrawStruct(0, -79, 52, 11, SPRFLAG_2000);
+	_data[93] = DrawStruct(0, -27, 52, 11, 0);
 	_data[94] = DrawStruct(0, 32, 52, 11, 0);
 	_data[95] = DrawStruct(0, 89, 52, 11, 0);
 	_data[96] = DrawStruct(0, 145, 52, 11, SPRFLAG_2000);
-	_data[97] = DrawStruct(0, 65528, 50, 12, 0);
-	_data[98] = DrawStruct(0, 65471, 50, 12, 0);
+	_data[97] = DrawStruct(0, -8, 50, 12, 0);
+	_data[98] = DrawStruct(0, -65, 50, 12, 0);
 	_data[99] = DrawStruct(0, 49, 50, 12, 0);
-	_data[100] = DrawStruct(0, 65471, 50, 12, 0);
-	_data[101] = DrawStruct(0, 65455, 50, 12, 0);
+	_data[100] = DrawStruct(0, -65, 50, 12, 0);
+	_data[101] = DrawStruct(0, -81, 50, 12, 0);
 	_data[102] = DrawStruct(0, 49, 50, 12, 0);
 	_data[103] = DrawStruct(0, 65, 50, 12, 0);
-	_data[104] = DrawStruct(0, 65512, 50, 12, 0);
+	_data[104] = DrawStruct(0, -24, 50, 12, 0);
 	_data[105] = DrawStruct(0, 9, 50, 12, 0);
-	_data[106] = DrawStruct(0, 65528, 50, 12, 0);
+	_data[106] = DrawStruct(0, -8, 50, 12, 0);
 	_data[107] = DrawStruct(7, 8, 48);
 	_data[108] = DrawStruct(7, 64, 40);
 	_data[109] = DrawStruct(6, 144, 40, 0, SPRFLAG_HORIZ_FLIPPED);
@@ -305,20 +305,20 @@ IndoorDrawList::IndoorDrawList() :
 	_data[116] = DrawStruct(0, 63, 47, 8, SPRFLAG_HORIZ_FLIPPED);
 	_data[117] = DrawStruct(0, 94, 52, 8, 0);
 	_data[118] = DrawStruct(0, 50, 52, 8, SPRFLAG_HORIZ_FLIPPED);
-	_data[119] = DrawStruct(6, 65496, 40, 0, SPRFLAG_2000);
+	_data[119] = DrawStruct(6, -40, 40, 0, SPRFLAG_2000);
 	_data[120] = DrawStruct(6, 64, 40);
 	_data[121] = DrawStruct(0, 168, 40, 0, SPRFLAG_2000);
-	_data[122] = DrawStruct(0, 65464, 40, 6, SPRFLAG_2000);
+	_data[122] = DrawStruct(0, -72, 40, 6, SPRFLAG_2000);
 	_data[123] = DrawStruct(0, 32, 40, 6, 0);
 	_data[124] = DrawStruct(0, 137, 40, 6, SPRFLAG_2000);
-	_data[125] = DrawStruct(0, 65529, 25, 7, 0);
-	_data[126] = DrawStruct(0, 65424, 25, 7, SPRFLAG_2000);
+	_data[125] = DrawStruct(0, -7, 25, 7, 0);
+	_data[126] = DrawStruct(0, -112, 25, 7, SPRFLAG_2000);
 	_data[127] = DrawStruct(0, 98, 25, 7, SPRFLAG_2000);
-	_data[128] = DrawStruct(0, 65424, 29, 8, SPRFLAG_2000);
+	_data[128] = DrawStruct(0, -112, 29, 8, SPRFLAG_2000);
 	_data[129] = DrawStruct(0, 98, 29, 8, SPRFLAG_2000);
-	_data[130] = DrawStruct(0, 65498, 29, 8, 0);
+	_data[130] = DrawStruct(0, -38, 29, 8, 0);
 	_data[131] = DrawStruct(0, 25, 29, 8, 0);
-	_data[132] = DrawStruct(0, 65529, 29, 8, 0);
+	_data[132] = DrawStruct(0, -7, 29, 8, 0);
 	_data[133] = DrawStruct(6, 32, 24);
 	_data[134] = DrawStruct(0, 168, 24, 0, SPRFLAG_HORIZ_FLIPPED);
 	_data[135] = DrawStruct(0, 72, 48, 4, 0);
@@ -329,23 +329,23 @@ IndoorDrawList::IndoorDrawList() :
 	_data[140] = DrawStruct(0, 55, 41, 4, SPRFLAG_HORIZ_FLIPPED);
 	_data[141] = DrawStruct(0, 106, 47, 4, 0);
 	_data[142] = DrawStruct(0, 38, 47, 4, SPRFLAG_HORIZ_FLIPPED);
-	_data[143] = DrawStruct(0, 65400, 24, 0, SPRFLAG_2000);
+	_data[143] = DrawStruct(0, -136, 24, 0, SPRFLAG_2000);
 	_data[144] = DrawStruct(0, 8, 12);
 	_data[145] = DrawStruct(0, 32, 24);
 	_data[146] = DrawStruct(0, 200, 12, 0, SPRFLAG_HORIZ_FLIPPED);
 	_data[147] = DrawStruct(0, 200, 24, 0, SPRFLAG_2000);
 	_data[148] = DrawStruct(0, 32, 24);
-	_data[149] = DrawStruct(0, 65531, 2, 0, SPRFLAG_4000 | SPRFLAG_2000);
-	_data[150] = DrawStruct(0, 65469, 10, 0, SPRFLAG_4000 | SPRFLAG_2000);
+	_data[149] = DrawStruct(0, -5, 2, 0, SPRFLAG_4000 | SPRFLAG_2000);
+	_data[150] = DrawStruct(0, -67, 10, 0, SPRFLAG_4000 | SPRFLAG_2000);
 	_data[151] = DrawStruct(0, 44, 73);
 	_data[152] = DrawStruct(0, 44, 73);
 	_data[153] = DrawStruct(0, 58, 14, 0, SPRFLAG_4000 | SPRFLAG_2000);
 	_data[154] = DrawStruct(0, 169, 73);
 	_data[155] = DrawStruct(0, 169, 73);
-	_data[156] = DrawStruct(0, 65531, 14, 0, SPRFLAG_4000 | SPRFLAG_2000);
+	_data[156] = DrawStruct(0, -5, 14, 0, SPRFLAG_4000 | SPRFLAG_2000);
 	_data[157] = DrawStruct(0, 110, 73);
 	_data[158] = DrawStruct(0, 110, 73);
-	_data[159] = DrawStruct(0, 65531, 14, 0, SPRFLAG_4000 | SPRFLAG_2000);
+	_data[159] = DrawStruct(0, -5, 14, 0, SPRFLAG_4000 | SPRFLAG_2000);
 	_data[160] = DrawStruct(0, 110, 73);
 	_data[161] = DrawStruct(0, 110, 73);
 	_data[162] = DrawStruct(0, 72, 43);
@@ -576,7 +576,8 @@ void InterfaceMap::drawIndoors() {
 		map.getCell(DRAW_NUMBERS[cellIndex]);
 
 		DrawStruct &drawStruct = _indoorList[3 + cellIndex];
-		drawStruct._sprites = &map._surfaceSprites[map._currentSurfaceId];
+		if (!map._surfaceSprites[map._currentSurfaceId].empty())
+			drawStruct._sprites = &map._surfaceSprites[map._currentSurfaceId];
 
 		surfaceId = map.mazeData()._surfaceTypes[map._currentSurfaceId];
 		if (surfaceId == 5 || surfaceId == 12) {
diff --git a/engines/xeen/map.cpp b/engines/xeen/map.cpp
index e410333..507e4fc 100644
--- a/engines/xeen/map.cpp
+++ b/engines/xeen/map.cpp
@@ -1157,9 +1157,10 @@ void Map::load(int mapId) {
 
 		indoorList._fwl_1F._sprites = &_wallSprites._fwl1;
 		indoorList._fwl_1F1R._sprites = &_wallSprites._fwl1;
-		indoorList._fwl_1F1L._sprites = &_wallSprites._fwl1;
-		
-		indoorList._horizon._sprites = &_groundSprites;
+		indoorList._fwl_1F1L._sprites = &_wallSprites._fwl1;		
+		indoorList._horizon._sprites = &_wallSprites._fwl1;
+
+		indoorList._ground._sprites = &_groundSprites;
 
 		// Down show horizon for certain maps
 		if (_vm->_files->_isDarkCc) {
diff --git a/engines/xeen/screen.cpp b/engines/xeen/screen.cpp
index 783f1ff..7b6f972 100644
--- a/engines/xeen/screen.cpp
+++ b/engines/xeen/screen.cpp
@@ -275,7 +275,8 @@ void Screen::update() {
 }
 
 void Screen::addDirtyRect(const Common::Rect &r) {
-	assert(r.isValidRect() && r.width() > 0 && r.height() > 0
+	assert(r.isValidRect() && r.width() > 0 && r.height() > 0 
+		&& r.left >= 0 && r.top >= 0
 		&& r.right <= SCREEN_WIDTH && r.bottom <= SCREEN_HEIGHT);
 	_dirtyRects.push_back(r);
 }


Commit: 7e4580a2203ef63a129a9c2992c5cd1210b5bf80
    https://github.com/scummvm/scummvm/commit/7e4580a2203ef63a129a9c2992c5cd1210b5bf80
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-01-14T22:42:09-05:00

Commit Message:
XEEN: Add cropping support to sprite drawing

Changed paths:
    engines/xeen/sprites.cpp



diff --git a/engines/xeen/sprites.cpp b/engines/xeen/sprites.cpp
index 74f2b1d..df1deba 100644
--- a/engines/xeen/sprites.cpp
+++ b/engines/xeen/sprites.cpp
@@ -110,10 +110,15 @@ void SpriteResource::drawOffset(XSurface &dest, uint16 offset, const Common::Poi
 		if (lineLength == 0) {
 			// Skip the specified number of scan lines
 			yPos += f.readByte();
+		} else if ((destPos.y + yPos) < 0) {
+			// Skip over the bytes of the line
+			f.skip(lineLength);
 		} else {
 			// Skip the transparent pixels at the beginning of the scan line
 			int xPos = f.readByte() + xOffset; ++byteCount;
 			byte *destP = (byte *)dest.getBasePtr(destPos.x + xPos, destPos.y + yPos);
+			const byte *lineStartP = (const byte *)dest.getBasePtr(0, destPos.y + yPos);
+			const byte *lineEndP = (const byte *)dest.getBasePtr(dest.w, destPos.y + yPos);
 
 			while (byteCount < lineLength) {
 				// The next byte is an opcode that determines what 
@@ -128,14 +133,23 @@ void SpriteResource::drawOffset(XSurface &dest, uint16 offset, const Common::Poi
 				case 0:   // The following len + 1 bytes are stored as indexes into the color table.
 				case 1:   // The following len + 33 bytes are stored as indexes into the color table.
 					for (int i = 0; i < opcode + 1; ++i, ++xPos) {
-						*destP++ = f.readByte(); ++byteCount;
+						byte b = f.readByte();
+						if (destP < lineStartP || destP >= lineEndP)
+							++destP;
+						else
+							*destP++ = b; 
+						++byteCount;
 					}
 					break;
 
 				case 2:   // The following byte is an index into the color table, draw it len + 3 times.
 					opr1 = f.readByte(); ++byteCount;
-					for (int i = 0; i < len + 3; ++i, ++xPos)
-						*destP++ = opr1;
+					for (int i = 0; i < len + 3; ++i, ++xPos) {
+						if (destP < lineStartP || destP >= lineEndP)
+							++destP;
+						else
+							*destP++ = opr1;
+					}
 					break;
 
 				case 3:   // Stream copy command.
@@ -143,8 +157,13 @@ void SpriteResource::drawOffset(XSurface &dest, uint16 offset, const Common::Poi
 					pos = f.pos();
 					f.seek(-opr1, SEEK_CUR);
 
-					for (int i = 0; i < len + 4; ++i, ++xPos)
-						*destP++ = f.readByte();
+					for (int i = 0; i < len + 4; ++i, ++xPos) {
+						byte b = f.readByte();
+						if (destP < lineStartP || destP >= lineEndP)
+							++destP;
+						else
+							*destP++ = b;
+					}
 
 					f.seek(pos, SEEK_SET);
 					break;
@@ -153,8 +172,12 @@ void SpriteResource::drawOffset(XSurface &dest, uint16 offset, const Common::Poi
 					opr1 = f.readByte(); ++byteCount;
 					opr2 = f.readByte(); ++byteCount;
 					for (int i = 0; i < len + 2; ++i, xPos += 2) {
-						*destP++ = opr1;
-						*destP++ = opr2;
+						if (destP < lineStartP || destP >= (lineEndP - 1)) {
+							destP += 2;
+						} else {
+							*destP++ = opr1;
+							*destP++ = opr2;
+						}
 					}
 					break;
 
@@ -171,7 +194,10 @@ void SpriteResource::drawOffset(XSurface &dest, uint16 offset, const Common::Poi
 
 					opr1 = f.readByte(); ++byteCount;
 					for (int i = 0; i < len + 3; ++i, ++xPos) {
-						*destP++ = opr1;
+						if (destP < lineStartP || destP >= lineEndP)
+							++destP;
+						else
+							*destP++ = opr1;
 						opr1 += patternSteps[cmd + (i % 2)];
 					}
 					break;
@@ -183,9 +209,12 @@ void SpriteResource::drawOffset(XSurface &dest, uint16 offset, const Common::Poi
 			assert(byteCount == lineLength);
 		}
 	}
-
-	dest.addDirtyRect(Common::Rect(destPos.x + xOffset, destPos.y + yOffset,
+	
+	Common::Rect r(Common::Rect(destPos.x + xOffset, destPos.y + yOffset,
 		destPos.x + xOffset + width, destPos.y + yOffset + height));
+	r.clip(Common::Rect(0, 0, dest.w, dest.h));
+	if (!r.isEmpty())
+		dest.addDirtyRect(r);
 }
 
 void SpriteResource::draw(XSurface &dest, int frame, const Common::Point &destPos, int flags) const {


Commit: 3e7163769d1a28721dc000a9ef0a142731705ad4
    https://github.com/scummvm/scummvm/commit/3e7163769d1a28721dc000a9ef0a142731705ad4
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-01-15T08:33:43-05:00

Commit Message:
XEEN: Beginnings of setIndoorMonsters implementation

Changed paths:
    engines/xeen/combat.cpp
    engines/xeen/combat.h
    engines/xeen/interface_map.cpp
    engines/xeen/interface_map.h
    engines/xeen/map.cpp
    engines/xeen/map.h
    engines/xeen/resources.cpp
    engines/xeen/resources.h



diff --git a/engines/xeen/combat.cpp b/engines/xeen/combat.cpp
index b3ef4fd..0772053 100644
--- a/engines/xeen/combat.cpp
+++ b/engines/xeen/combat.cpp
@@ -25,8 +25,9 @@
 
 namespace Xeen {
 
-Combat::Combat(XeenEngine *vm): _vm(vm) {
-	_attackMon1 = _attackMon2 = _attackMon3 = 0;
+Combat::Combat(XeenEngine *vm): _vm(vm), _attackMon1(_attackMonsters[0]),
+		_attackMon2(_attackMonsters[1]), _attackMon3(_attackMonsters[2]) {
+	Common::fill(&_attackMonsters[0], &_attackMonsters[26], 0);
 	Common::fill(&_charsArray1[0], &_charsArray1[12], 0);
 	Common::fill(&_monPow[0], &_monPow[12], 0);
 	Common::fill(&_monsterScale[0], &_monsterScale[12], 0);
@@ -35,4 +36,8 @@ Combat::Combat(XeenEngine *vm): _vm(vm) {
 	Common::fill(&_shooting[0], &_shooting[6], 0);
 }
 
+void Combat::clear() {
+	Common::fill(&_attackMonsters[0], &_attackMonsters[26], -1);
+}
+
 } // End of namespace Xeen
diff --git a/engines/xeen/combat.h b/engines/xeen/combat.h
index 24a3587..4ead404 100644
--- a/engines/xeen/combat.h
+++ b/engines/xeen/combat.h
@@ -33,15 +33,18 @@ class Combat {
 private:
 	XeenEngine *_vm;
 public:
+	int _attackMonsters[26];
 	int _charsArray1[12];
 	bool _monPow[12];
 	int _monsterScale[12];
 	int _elemPow[12];
 	int _elemScale[12];
 	bool _shooting[6];
-	int _attackMon1, _attackMon2, _attackMon3;
+	int &_attackMon1, _attackMon2, _attackMon3;
 public:
 	Combat(XeenEngine *vm);
+
+	void clear();
 };
 
 } // End of namespace Xeen
diff --git a/engines/xeen/interface_map.cpp b/engines/xeen/interface_map.cpp
index cc99b3e..f4c0dc0 100644
--- a/engines/xeen/interface_map.cpp
+++ b/engines/xeen/interface_map.cpp
@@ -371,9 +371,80 @@ InterfaceMap::InterfaceMap(XeenEngine *vm): _vm(vm) {
 	_isShooting = false;
 	_charsShooting = false;
 	_objNumber = 0;
+	_combatFloatCounter = 0;
 }
 
 void InterfaceMap::setIndoorsMonsters() {
+	Combat &combat = *_vm->_combat;
+	Map &map = *_vm->_map;
+	Direction dir = _vm->_party._mazeDirection;
+	const int INDOOR_MONSTERS_Y[4] = { 2, 34, 53, 59 };
+
+	combat.clear();
+	for (uint monsterIdx = 0; monsterIdx < map._mobData._monsters.size(); ++monsterIdx) {
+		MazeMonster &monster = map._mobData._monsters[monsterIdx];
+		SpriteResource *sprites = monster._sprites;
+		int frame = monster._frame;
+
+		if (frame >= 8) {
+			sprites = monster._attackSprites;
+			frame -= 8;
+		}
+
+		// The following long sequence sets up monsters in the various positions
+		if (monster._position.x == SCREEN_POSITIONING_X[dir][2] &&
+				monster._position.y == SCREEN_POSITIONING_Y[dir][2]) {
+			monster._field4 = 1;
+			if (combat._attackMonsters[0] == -1) {
+				combat._attackMonsters[0] = monsterIdx;
+				setMonsterSprite(_indoorList[156], monster, sprites, frame, INDOOR_MONSTERS_Y[0]);
+			} else if (combat._attackMonsters[1] == -1) {
+				combat._attackMonsters[1] = monsterIdx;
+				setMonsterSprite(_indoorList[150], monster, sprites, frame, INDOOR_MONSTERS_Y[0]);
+			} else if (combat._attackMonsters[2] == -1) {
+				combat._attackMonsters[2] = monsterIdx;
+				setMonsterSprite(_indoorList[153], monster, sprites, frame, INDOOR_MONSTERS_Y[0]);
+			}
+		}
+
+		if (monster._position.x == SCREEN_POSITIONING_X[dir][7] &&
+				monster._position.y == SCREEN_POSITIONING_Y[dir][7]) {
+			monster._field4 = 1;
+			if (!_wo[27]) {
+				if (combat._attackMonsters[3] == -1) {
+					combat._attackMonsters[3] = monsterIdx;
+					setMonsterSprite(_indoorList[132], monster, sprites, frame, INDOOR_MONSTERS_Y[1]);
+				} else if (combat._attackMonsters[4] == -1) {
+					combat._attackMonsters[4] = monsterIdx;
+					setMonsterSprite(_indoorList[130], monster, sprites, frame, INDOOR_MONSTERS_Y[1]);
+				} else if (combat._attackMonsters[2] == -1) {
+					combat._attackMonsters[5] = monsterIdx;
+					setMonsterSprite(_indoorList[131], monster, sprites, frame, INDOOR_MONSTERS_Y[1]);
+				}
+			}
+		}
+	}
+}
+
+void InterfaceMap::setMonsterSprite(DrawStruct &drawStruct, MazeMonster &monster, SpriteResource *sprites, 
+		int frame, int defaultY) {
+	MonsterStruct &monsterData = _vm->_map->_monsterData[monster._spriteId];
+	bool flying = monsterData._flying;
+
+	_indoorList[156]._frame = frame;
+	_indoorList[156]._sprites = sprites;
+	_indoorList[156]._y = defaultY;
+
+	if (flying) {
+		_indoorList[156]._x = COMBAT_FLOAT_X[_combatFloatCounter];
+		_indoorList[156]._y = COMBAT_FLOAT_Y[_combatFloatCounter];
+	} else {
+		_indoorList[156]._x = 0;
+	}
+
+	_indoorList[156]._flags &= SPRFLAG_HORIZ_FLIPPED | SPRFLAG_4000 | SPRFLAG_2000;
+	if (monster._effect2)
+		_indoorList[156]._flags = MONSTER_EFFECT_FLAGS[monster._effect2][monster._effect3];
 
 }
 
diff --git a/engines/xeen/interface_map.h b/engines/xeen/interface_map.h
index 01cd1d2..ea40c30 100644
--- a/engines/xeen/interface_map.h
+++ b/engines/xeen/interface_map.h
@@ -24,6 +24,7 @@
 #define XEEN_INTERFACE_MAP_H
 
 #include "common/scummsys.h"
+#include "xeen/map.h"
 #include "xeen/screen.h"
 
 namespace Xeen {
@@ -81,8 +82,12 @@ public:
 class InterfaceMap {
 private:
 	XeenEngine *_vm;
+	int _combatFloatCounter;
 
 	void initDrawStructs();
+
+	void setMonsterSprite(DrawStruct &drawStruct, MazeMonster &monster, 
+		SpriteResource *sprites, int frame, int defaultY);
 protected:
 	byte _wp[20];
 	byte _wo[308];
diff --git a/engines/xeen/map.cpp b/engines/xeen/map.cpp
index 507e4fc..c136dee 100644
--- a/engines/xeen/map.cpp
+++ b/engines/xeen/map.cpp
@@ -638,6 +638,7 @@ MazeMonster::MazeMonster() {
 	_frame = 0;
 	_id = 0;
 	_spriteId = 0;
+	_field4 = 0;
 	_hp = 0;
 	_effect1 = _effect2 = 0;
 	_effect3 = 0;
diff --git a/engines/xeen/map.h b/engines/xeen/map.h
index faffe97..821922b 100644
--- a/engines/xeen/map.h
+++ b/engines/xeen/map.h
@@ -250,6 +250,7 @@ struct MazeMonster {
 	int _frame;
 	int _id;
 	int _spriteId;
+	int _field4;
 	int _hp;
 	int _effect1, _effect2;
 	int _effect3;
@@ -352,7 +353,6 @@ private:
 	XeenEngine *_vm;
 	MazeData _mazeData[9];
 	Common::String _mazeName;
-	MonsterData _monsterData;
 	SpriteResource _wallPicSprites;
 	int _townPortalSide;
 	int _sideObj;
@@ -365,6 +365,7 @@ private:
 public:
 	bool _isOutdoors;
 	MonsterObjectData _mobData;
+	MonsterData _monsterData;
 	MazeEvents _events;
 	HeadData _headData;
 	AnimationInfo _animationInfo;
diff --git a/engines/xeen/resources.cpp b/engines/xeen/resources.cpp
index e56ad16..87540b8 100644
--- a/engines/xeen/resources.cpp
+++ b/engines/xeen/resources.cpp
@@ -445,5 +445,26 @@ const int DRAW_FRAMES[25][2] = {
 	{ 1, 1 }
 };
 
+const int COMBAT_FLOAT_X[8] = { -2, -1, 0, 1, 2, 1, 0, -1 };
+
+const int COMBAT_FLOAT_Y[8] = { -2, 0, 2, 0, -1, 0, 2, 0 };
+
+const int MONSTER_EFFECT_FLAGS[15][8] = {
+	{ 0x104, 0x105, 0x106, 0x107, 0x108, 0x109, 0x10A, 0x10B },
+	{ 0x10C, 0x10D, 0x10E, 0x10F, 0x0, 0x0, 0x0, 0x0 },
+	{ 0x110, 0x111, 0x112, 0x113, 0x0, 0x0, 0x0, 0x0 },
+	{ 0x114, 0x115, 0x116, 0x117, 0x0, 0x0, 0x0, 0x0 },
+	{ 0x200, 0x201, 0x202, 0x203, 0x0, 0x0, 0x0, 0x0 },
+	{ 0x300, 0x301, 0x302, 0x303, 0x400, 0x401, 0x402, 0x403 },
+	{ 0x500, 0x501, 0x502, 0x503, 0x0, 0x0, 0x0, 0x0 },
+	{ 0x600, 0x601, 0x602, 0x603, 0x0, 0x0, 0x0, 0x0 },
+	{ 0x604, 0x605, 0x606, 0x607, 0x608, 0x609, 0x60A, 0x60B },
+	{ 0x60C, 0x60D, 0x60E, 0x60F, 0x0, 0x0, 0x0, 0x0 },
+	{ 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100 },
+	{ 0x101, 0x101, 0x101, 0x101, 0x101, 0x101, 0x101, 0x101 },
+	{ 0x102, 0x102, 0x102, 0x102, 0x102, 0x102, 0x102, 0x102 },
+	{ 0x103, 0x103, 0x103, 0x103, 0x103, 0x103, 0x103, 0x103 },
+	{ 0x108, 0x108, 0x108, 0x108, 0x108, 0x108, 0x108, 0x108 }
+};
 
 } // End of namespace Xeen
diff --git a/engines/xeen/resources.h b/engines/xeen/resources.h
index bed9569..2160d55 100644
--- a/engines/xeen/resources.h
+++ b/engines/xeen/resources.h
@@ -94,6 +94,12 @@ extern const int DRAW_NUMBERS[25];
 
 extern const int DRAW_FRAMES[25][2];
 
+extern const int COMBAT_FLOAT_X[8];
+
+extern const int COMBAT_FLOAT_Y[8];
+
+extern const int MONSTER_EFFECT_FLAGS[15][8];
+
 } // End of namespace Xeen
 
 #endif	/* XEEN_RESOURCES_H */


Commit: ce3cb6f1dbc32ca682279a9021cbbc8da1a1f30a
    https://github.com/scummvm/scummvm/commit/ce3cb6f1dbc32ca682279a9021cbbc8da1a1f30a
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-01-15T20:39:52-05:00

Commit Message:
XEEN: Finished setIndoorsMonsters

Changed paths:
    engines/xeen/combat.cpp
    engines/xeen/combat.h
    engines/xeen/interface.cpp
    engines/xeen/interface_map.cpp
    engines/xeen/map.cpp
    engines/xeen/map.h



diff --git a/engines/xeen/combat.cpp b/engines/xeen/combat.cpp
index 0772053..98dff4c 100644
--- a/engines/xeen/combat.cpp
+++ b/engines/xeen/combat.cpp
@@ -25,8 +25,7 @@
 
 namespace Xeen {
 
-Combat::Combat(XeenEngine *vm): _vm(vm), _attackMon1(_attackMonsters[0]),
-		_attackMon2(_attackMonsters[1]), _attackMon3(_attackMonsters[2]) {
+Combat::Combat(XeenEngine *vm): _vm(vm) {
 	Common::fill(&_attackMonsters[0], &_attackMonsters[26], 0);
 	Common::fill(&_charsArray1[0], &_charsArray1[12], 0);
 	Common::fill(&_monPow[0], &_monPow[12], 0);
diff --git a/engines/xeen/combat.h b/engines/xeen/combat.h
index 4ead404..c64741b 100644
--- a/engines/xeen/combat.h
+++ b/engines/xeen/combat.h
@@ -40,7 +40,6 @@ public:
 	int _elemPow[12];
 	int _elemScale[12];
 	bool _shooting[6];
-	int &_attackMon1, _attackMon2, _attackMon3;
 public:
 	Combat(XeenEngine *vm);
 
diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp
index 4550dac..eb607db 100644
--- a/engines/xeen/interface.cpp
+++ b/engines/xeen/interface.cpp
@@ -631,7 +631,7 @@ void Interface::draw3d(bool updateFlag) {
 			ds2._sprites = nullptr;
 
 			if (combat._charsArray1[idx]) {
-				int posIndex= combat._attackMon2 && !combat._attackMon3 ? 1 : 0;
+				int posIndex= combat._attackMonsters[1] && !combat._attackMonsters[2] ? 1 : 0;
 				--combat._charsArray1[idx];
 
 				if (combat._monPow[idx]) {
@@ -671,7 +671,7 @@ void Interface::draw3d(bool updateFlag) {
 
 		// Handle attacking monsters
 		int monsterIndex = 0;
-		if (combat._attackMon1 != -1 && map._mobData._monsters[combat._attackMon1]._frame >= 0) {
+		if (combat._attackMonsters[0] != -1 && map._mobData._monsters[combat._attackMonsters[0]]._frame >= 0) {
 			_indoorList[159] = _indoorList[156];
 			_indoorList[160] = _indoorList[157];
 			_indoorList[161] = _indoorList[158];
@@ -679,7 +679,7 @@ void Interface::draw3d(bool updateFlag) {
 			_indoorList[156]._sprites = nullptr;
 			_indoorList[157]._sprites = nullptr;
 			monsterIndex = 1;
-		} else if (combat._attackMon2 != -1 && map._mobData._monsters[combat._attackMon2]._frame >= 0) {
+		} else if (combat._attackMonsters[1] != -1 && map._mobData._monsters[combat._attackMonsters[1]]._frame >= 0) {
 			_indoorList[159] = _indoorList[150];
 			_indoorList[160] = _indoorList[151];
 			_indoorList[161] = _indoorList[152];
@@ -687,7 +687,7 @@ void Interface::draw3d(bool updateFlag) {
 			_indoorList[151]._sprites = nullptr;
 			_indoorList[150]._sprites = nullptr;
 			monsterIndex = 2;
-		} else if (combat._attackMon3 != -1 &&  map._mobData._monsters[combat._attackMon3]._frame >= 0) {
+		} else if (combat._attackMonsters[2] != -1 &&  map._mobData._monsters[combat._attackMonsters[2]]._frame >= 0) {
 			_indoorList[159] = _indoorList[153];
 			_indoorList[160] = _indoorList[154];
 			_indoorList[161] = _indoorList[155];
diff --git a/engines/xeen/interface_map.cpp b/engines/xeen/interface_map.cpp
index f4c0dc0..ba5cdbc 100644
--- a/engines/xeen/interface_map.cpp
+++ b/engines/xeen/interface_map.cpp
@@ -394,7 +394,7 @@ void InterfaceMap::setIndoorsMonsters() {
 		// The following long sequence sets up monsters in the various positions
 		if (monster._position.x == SCREEN_POSITIONING_X[dir][2] &&
 				monster._position.y == SCREEN_POSITIONING_Y[dir][2]) {
-			monster._field4 = 1;
+			monster._isAttacking = true;
 			if (combat._attackMonsters[0] == -1) {
 				combat._attackMonsters[0] = monsterIdx;
 				setMonsterSprite(_indoorList[156], monster, sprites, frame, INDOOR_MONSTERS_Y[0]);
@@ -409,7 +409,7 @@ void InterfaceMap::setIndoorsMonsters() {
 
 		if (monster._position.x == SCREEN_POSITIONING_X[dir][7] &&
 				monster._position.y == SCREEN_POSITIONING_Y[dir][7]) {
-			monster._field4 = 1;
+			monster._isAttacking = true;
 			if (!_wo[27]) {
 				if (combat._attackMonsters[3] == -1) {
 					combat._attackMonsters[3] = monsterIdx;
@@ -423,6 +423,201 @@ void InterfaceMap::setIndoorsMonsters() {
 				}
 			}
 		}
+
+		if (monster._position.x == SCREEN_POSITIONING_X[dir][5] &&
+			monster._position.y == SCREEN_POSITIONING_Y[dir][5]) {
+			if (_wo[27] && _wo[25]) {
+			} else if (_wo[27] && _wo[28]) {
+			} else if (_wo[23] & _wo[25]) {
+			} else if (_wo[23] && _wo[28]) {
+			} else {
+				monster._isAttacking = true;
+
+				if (combat._attackMonsters[12] == -1) {
+					combat._attackMonsters[12] = monsterIdx;
+					setMonsterSprite(_indoorList[128], monster, sprites, frame, INDOOR_MONSTERS_Y[1]);
+				}
+			}
+		}
+
+		if (monster._position.x == SCREEN_POSITIONING_X[dir][9] &&
+			monster._position.y == SCREEN_POSITIONING_Y[dir][9]) {
+			if (_wo[27] && _wo[26]) {
+			} else if (_wo[27] && _wo[29]) {
+			} else if (_wo[24] & _wo[26]) {
+			} else if (_wo[24] && _wo[29]) {
+			} else {
+				monster._isAttacking = true;
+
+				if (combat._attackMonsters[13] == -1) {
+					combat._attackMonsters[13] = monsterIdx;
+					setMonsterSprite(_indoorList[129], monster, sprites, frame, INDOOR_MONSTERS_Y[1]);
+				}
+			}
+		}
+
+		if (monster._position.x == SCREEN_POSITIONING_X[dir][14] &&
+			monster._position.y == SCREEN_POSITIONING_Y[dir][14]) {
+			monster._isAttacking = true;
+
+			if (!_wo[22] && !_wo[27]) {
+				if (combat._attackMonsters[6] == -1) {
+					combat._attackMonsters[6] = monsterIdx;
+					setMonsterSprite(_indoorList[106], monster, sprites, frame, INDOOR_MONSTERS_Y[2]);
+				} else  if (combat._attackMonsters[7] == -1) {
+					combat._attackMonsters[7] = monsterIdx;
+					setMonsterSprite(_indoorList[104], monster, sprites, frame, INDOOR_MONSTERS_Y[2]);
+				} else if (combat._attackMonsters[8] == -1) {
+					combat._attackMonsters[8] = monsterIdx;
+					setMonsterSprite(_indoorList[105], monster, sprites, frame, INDOOR_MONSTERS_Y[2]);
+				}
+			}
+		}
+
+		if (monster._position.x == SCREEN_POSITIONING_X[dir][12] &&
+			monster._position.y == SCREEN_POSITIONING_Y[dir][12]) {
+			if (_wo[27]) {
+			} else if (_wo[22] && _wo[23]) {
+			} else if (_wo[22] & _wo[20]) {
+			} else if (_wo[23] && _wo[17]) {
+			} else {
+				monster._isAttacking = true;
+
+				if (combat._attackMonsters[14] == -1) {
+					combat._attackMonsters[14] = monsterIdx;
+					setMonsterSprite(_indoorList[100], monster, sprites, frame, INDOOR_MONSTERS_Y[2]);
+				} else if (combat._attackMonsters[20] == -1) {
+					combat._attackMonsters[20] = monsterIdx;
+					setMonsterSprite(_indoorList[101], monster, sprites, frame, INDOOR_MONSTERS_Y[2]);
+				}
+			}
+		}
+
+		if (monster._position.x == SCREEN_POSITIONING_X[dir][16] &&
+			monster._position.y == SCREEN_POSITIONING_Y[dir][16]) {
+			if (_wo[27]) {
+			} else if (_wo[22] && _wo[24]) {
+			} else if (_wo[22] & _wo[21]) {
+			} else if (_wo[24] && _wo[19]) {
+			} else if (_wo[21] && _wo[19]) {
+			} else {
+				monster._isAttacking = true;
+
+				if (combat._attackMonsters[15] == -1) {
+					combat._attackMonsters[15] = monsterIdx;
+					setMonsterSprite(_indoorList[102], monster, sprites, frame, INDOOR_MONSTERS_Y[2]);
+				} else if (combat._attackMonsters[21] == -1) {
+					combat._attackMonsters[21] = monsterIdx;
+					setMonsterSprite(_indoorList[103], monster, sprites, frame, INDOOR_MONSTERS_Y[2]);
+				}
+			}
+		}
+
+		if (monster._position.x == SCREEN_POSITIONING_X[dir][27] &&
+			monster._position.y == SCREEN_POSITIONING_Y[dir][27]) {
+			if (!_wo[27] && !_wo[22] && _wo[15]) {
+				monster._isAttacking = true;
+
+				if (combat._attackMonsters[9] == -1) {
+					combat._attackMonsters[9] = monsterIdx;
+					setMonsterSprite(_indoorList[70], monster, sprites, frame, INDOOR_MONSTERS_Y[3]);
+				} else if (combat._attackMonsters[10] == -1) {
+					combat._attackMonsters[10] = monsterIdx;
+					setMonsterSprite(_indoorList[68], monster, sprites, frame, INDOOR_MONSTERS_Y[3]);
+				} else if (combat._attackMonsters[11] == -1) {
+					combat._attackMonsters[11] = monsterIdx;
+					setMonsterSprite(_indoorList[69], monster, sprites, frame, INDOOR_MONSTERS_Y[3]);
+				}
+			}
+		}
+
+		if (monster._position.x == SCREEN_POSITIONING_X[dir][25] &&
+			monster._position.y == SCREEN_POSITIONING_Y[dir][25]) {
+			if (_wo[27] || _wo[22]) {
+			} else if (_wo[15] && _wo[17]) {
+			} else if (_wo[15] && _wo[12]) {
+			} else if (_wo[12] && _wo[7]) {
+			} else if (_wo[17] && _wo[7]) {
+			} else {
+				monster._isAttacking = true;
+
+				if (combat._attackMonsters[16] == -1) {
+					combat._attackMonsters[16] = monsterIdx;
+					setMonsterSprite(_indoorList[62], monster, sprites, frame, INDOOR_MONSTERS_Y[3]);
+				} else if (combat._attackMonsters[22] == -1) {
+					combat._attackMonsters[22] = monsterIdx;
+					setMonsterSprite(_indoorList[60], monster, sprites, frame, INDOOR_MONSTERS_Y[3]);
+				} else if (combat._attackMonsters[24] == -1) {
+					combat._attackMonsters[24] = monsterIdx;
+					setMonsterSprite(_indoorList[61], monster, sprites, frame, INDOOR_MONSTERS_Y[3]);
+				}
+			}
+		}
+
+		if (monster._position.x == SCREEN_POSITIONING_X[dir][23] &&
+			monster._position.y == SCREEN_POSITIONING_Y[dir][23]) {
+			if (_wo[27]) {
+			} else if (_wo[22] && _wo[20]) {
+			} else if (_wo[22] && _wo[23]) {
+			} else if (_wo[20] && _wo[17]) {
+			} else if (_wo[23] && _wo[17]) {
+			} else if (_wo[12] || _wo[8]) {
+			} else {
+				monster._isAttacking = true;
+
+				if (combat._attackMonsters[18] == -1) {
+					combat._attackMonsters[18] = monsterIdx;
+					setMonsterSprite(_indoorList[66], monster, sprites, frame, INDOOR_MONSTERS_Y[3]);
+				}
+			}
+		}
+
+		if (monster._position.x == SCREEN_POSITIONING_X[dir][29] &&
+			monster._position.y == SCREEN_POSITIONING_Y[dir][29]) {
+			if (_wo[27] || _wo[22]) {
+			} else if (_wo[15] && _wo[19]) {
+			} else if (_wo[15] && _wo[14]) {
+			} else if (_wo[14] && _wo[9]) {
+			} else if (_wo[19] && _wo[9]) {
+			} else {
+				monster._isAttacking = true;
+
+				if (combat._attackMonsters[17] == -1) {
+					combat._attackMonsters[17] = monsterIdx;
+					setMonsterSprite(_indoorList[65], monster, sprites, frame, INDOOR_MONSTERS_Y[3]);
+				} else if (combat._attackMonsters[23] == -1) {
+					combat._attackMonsters[23] = monsterIdx;
+					setMonsterSprite(_indoorList[63], monster, sprites, frame, INDOOR_MONSTERS_Y[3]);
+				} else if (combat._attackMonsters[25] == -1) {
+					combat._attackMonsters[25] = monsterIdx;
+					setMonsterSprite(_indoorList[64], monster, sprites, frame, INDOOR_MONSTERS_Y[3]);
+				}
+			}
+		}
+
+		if (monster._position.x == SCREEN_POSITIONING_X[dir][31] &&
+			monster._position.y == SCREEN_POSITIONING_Y[dir][31]) {
+			if (_wo[27]) {
+			} else if (_wo[22] && _wo[21]) {
+			} else if (_wo[22] && _wo[24]) {
+			} else if (_wo[21] && _wo[19]) {
+			} else if (_wo[24] && _wo[19]) {
+			} else if (_wo[14] || _wo[10]) {
+			} else {
+				monster._isAttacking = true;
+
+				if (combat._attackMonsters[19] == -1) {
+					combat._attackMonsters[19] = monsterIdx;
+					setMonsterSprite(_indoorList[67], monster, sprites, frame, INDOOR_MONSTERS_Y[3]);
+				} else if (combat._attackMonsters[23] == -1) {
+					combat._attackMonsters[23] = monsterIdx;
+					setMonsterSprite(_indoorList[63], monster, sprites, frame, INDOOR_MONSTERS_Y[3]);
+				} else if (combat._attackMonsters[25] == -1) {
+					combat._attackMonsters[25] = monsterIdx;
+					setMonsterSprite(_indoorList[64], monster, sprites, frame, INDOOR_MONSTERS_Y[3]);
+				}
+			}
+		}
 	}
 }
 
@@ -431,21 +626,20 @@ void InterfaceMap::setMonsterSprite(DrawStruct &drawStruct, MazeMonster &monster
 	MonsterStruct &monsterData = _vm->_map->_monsterData[monster._spriteId];
 	bool flying = monsterData._flying;
 
-	_indoorList[156]._frame = frame;
-	_indoorList[156]._sprites = sprites;
-	_indoorList[156]._y = defaultY;
+	drawStruct._frame = frame;
+	drawStruct._sprites = sprites;
+	drawStruct._y = defaultY;
 
 	if (flying) {
-		_indoorList[156]._x = COMBAT_FLOAT_X[_combatFloatCounter];
-		_indoorList[156]._y = COMBAT_FLOAT_Y[_combatFloatCounter];
+		drawStruct._x = COMBAT_FLOAT_X[_combatFloatCounter];
+		drawStruct._y = COMBAT_FLOAT_Y[_combatFloatCounter];
 	} else {
-		_indoorList[156]._x = 0;
+		drawStruct._x = 0;
 	}
 
-	_indoorList[156]._flags &= SPRFLAG_HORIZ_FLIPPED | SPRFLAG_4000 | SPRFLAG_2000;
+	drawStruct._flags &= SPRFLAG_HORIZ_FLIPPED | SPRFLAG_4000 | SPRFLAG_2000;
 	if (monster._effect2)
-		_indoorList[156]._flags = MONSTER_EFFECT_FLAGS[monster._effect2][monster._effect3];
-
+		drawStruct._flags = MONSTER_EFFECT_FLAGS[monster._effect2][monster._effect3];
 }
 
 void InterfaceMap::setIndoorObjects() {
diff --git a/engines/xeen/map.cpp b/engines/xeen/map.cpp
index c136dee..abb2cf6 100644
--- a/engines/xeen/map.cpp
+++ b/engines/xeen/map.cpp
@@ -638,7 +638,7 @@ MazeMonster::MazeMonster() {
 	_frame = 0;
 	_id = 0;
 	_spriteId = 0;
-	_field4 = 0;
+	_isAttacking = false;
 	_hp = 0;
 	_effect1 = _effect2 = 0;
 	_effect3 = 0;
diff --git a/engines/xeen/map.h b/engines/xeen/map.h
index 821922b..6ac8b36 100644
--- a/engines/xeen/map.h
+++ b/engines/xeen/map.h
@@ -250,7 +250,7 @@ struct MazeMonster {
 	int _frame;
 	int _id;
 	int _spriteId;
-	int _field4;
+	bool _isAttacking;
 	int _hp;
 	int _effect1, _effect2;
 	int _effect3;


Commit: d6497f78f0fe9f996be3ace6c4ef320dd58ba1c7
    https://github.com/scummvm/scummvm/commit/d6497f78f0fe9f996be3ace6c4ef320dd58ba1c7
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-01-15T21:50:20-05:00

Commit Message:
XEEN: Implement setIndoorsWallPics

Changed paths:
    engines/xeen/interface.cpp
    engines/xeen/interface_map.cpp
    engines/xeen/interface_map.h
    engines/xeen/map.cpp
    engines/xeen/map.h



diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp
index eb607db..7476abf 100644
--- a/engines/xeen/interface.cpp
+++ b/engines/xeen/interface.cpp
@@ -661,9 +661,9 @@ void Interface::draw3d(bool updateFlag) {
 			}
 		}
 
-		setIndoorsMonsters();
+		setIndoorsAttackingMonsters();
 		setIndoorObjects();
-		setIndoorWallPics();
+		setIndoorsWallPics();
 
 		_indoorList[161]._sprites = nullptr;
 		_indoorList[160]._sprites = nullptr;
@@ -756,7 +756,7 @@ void Interface::startup() {
 
 	animate3d();
 	if (_vm->_map->_isOutdoors) {
-		setIndoorsMonsters();
+		setIndoorsAttackingMonsters();
 		setIndoorObjects();
 	} else {
 		setOutdoorsMonsters();
diff --git a/engines/xeen/interface_map.cpp b/engines/xeen/interface_map.cpp
index ba5cdbc..d95868d 100644
--- a/engines/xeen/interface_map.cpp
+++ b/engines/xeen/interface_map.cpp
@@ -374,7 +374,7 @@ InterfaceMap::InterfaceMap(XeenEngine *vm): _vm(vm) {
 	_combatFloatCounter = 0;
 }
 
-void InterfaceMap::setIndoorsMonsters() {
+void InterfaceMap::setIndoorsAttackingMonsters() {
 	Combat &combat = *_vm->_combat;
 	Map &map = *_vm->_map;
 	Direction dir = _vm->_party._mazeDirection;
@@ -820,8 +820,230 @@ void InterfaceMap::setIndoorObjects() {
 	}
 }
 
-void InterfaceMap::setIndoorWallPics() {
-	// TODO
+void InterfaceMap::setIndoorsWallPics() {
+	Map &map = *_vm->_map;
+	const Common::Point &mazePos = _vm->_party._mazePosition;
+	Direction dir = _vm->_party._mazeDirection;
+
+	Common::fill(&_wp[0], &_wp[20], -1);
+
+	for (uint idx = 0; idx < map._mobData._wallItems.size(); ++idx) {
+		MazeWallItem &wallItem = map._mobData._wallItems[idx];
+		if (wallItem._direction != dir)
+			continue;
+
+		if (mazePos.x == (wallItem._position.x + SCREEN_POSITIONING_X[dir][2]) &&
+				mazePos.y == (wallItem._position.y + SCREEN_POSITIONING_Y[dir][2])) {
+			if (_wp[1] == -1) {
+				_indoorList[148]._frame = wallItem._frame;
+				_indoorList[148]._sprites = wallItem._sprites;
+			}
+		}
+
+		if (mazePos.x == (wallItem._position.x + SCREEN_POSITIONING_X[dir][7]) &&
+				mazePos.y == (wallItem._position.y + SCREEN_POSITIONING_Y[dir][7])) {
+			if (!_wo[27] && _wp[1] == -1) {
+				_indoorList[123]._frame = wallItem._frame;
+				_indoorList[123]._sprites = wallItem._sprites;
+				_wp[4] = idx;
+			}
+		}
+
+		if (mazePos.x == (wallItem._position.x + SCREEN_POSITIONING_X[dir][5]) &&
+				mazePos.y == (wallItem._position.y + SCREEN_POSITIONING_Y[dir][5])) {
+			if (_wo[27] && _wo[25]) {
+			} else if (_wo[27] && _wo[28]) {
+			} else if (_wo[23] && _wo[25]) {
+			} else if (_wo[23] && _wo[28]) {
+			} else if (_wp[3] == -1) {
+				_indoorList[122]._frame = wallItem._frame;
+				_indoorList[122]._sprites = wallItem._sprites;
+				_wp[3] = idx;
+			}
+		}
+
+		if (mazePos.x == (wallItem._position.x + SCREEN_POSITIONING_X[dir][9]) &&
+				mazePos.y == (wallItem._position.y + SCREEN_POSITIONING_Y[dir][9])) {
+			if (_wo[27] && _wo[26]) {
+			} else if (_wo[27] && _wo[29]) {
+			} else if (_wo[24] && _wo[26]) {
+			} else if (_wo[24] && _wo[29]) {
+			} else if (_wp[5] == -1) {
+				_indoorList[124]._frame = wallItem._frame;
+				_indoorList[124]._sprites = wallItem._sprites;
+				_wp[5] = idx;
+			}
+		}
+
+		if (mazePos.x == (wallItem._position.x + SCREEN_POSITIONING_X[dir][14]) &&
+				mazePos.y == (wallItem._position.y + SCREEN_POSITIONING_Y[dir][14])) {
+			if (!_wo[22] && !_wo[27] && !_wp[8]) {
+				_indoorList[94]._frame = wallItem._frame;
+				_indoorList[94]._sprites = wallItem._sprites;
+				_wp[8] = idx;
+			}
+		}
+
+		if (mazePos.x == (wallItem._position.x + SCREEN_POSITIONING_X[dir][12]) &&
+				mazePos.y == (wallItem._position.y + SCREEN_POSITIONING_Y[dir][12])) {
+			if (_wo[27]) {
+			} else if (_wo[22] && _wo[23]) {
+			} else if (_wo[22] && _wo[20]) {
+			} else if (_wo[23] && _wo[17]) {
+			} else if (_wo[20] && _wo[17]) {
+			} else if (_wp[7] == -1) {
+				_indoorList[93]._frame = wallItem._frame;
+				_indoorList[93]._sprites = wallItem._sprites;
+				_wp[7] = idx;
+			}
+		}
+
+		if (mazePos.x == (wallItem._position.x + SCREEN_POSITIONING_X[dir][16]) &&
+				mazePos.y == (wallItem._position.y + SCREEN_POSITIONING_Y[dir][16])) {
+			if (_wo[27]) {
+			} else if (_wo[22] && _wo[24]) {
+			} else if (_wo[22] && _wo[21]) {
+			} else if (_wo[24] && _wo[19]) {
+			} else if (_wo[21] && _wo[19]) {
+			} else if (_wp[9] == -1) {
+				_indoorList[95]._frame = wallItem._frame;
+				_indoorList[95]._sprites = wallItem._sprites;
+				_wp[9] = idx;
+			}
+		}
+
+		if (mazePos.x == (wallItem._position.x + SCREEN_POSITIONING_X[dir][12]) &&
+				mazePos.y == (wallItem._position.y + SCREEN_POSITIONING_Y[dir][12])) {
+			if (_wo[27]) {
+			} else if (_wo[25] && _wo[28]) {
+			} else if (_wo[20] && _wo[16]) {
+			} else if (_wp[6] == -1) {
+				_indoorList[92]._frame = wallItem._frame;
+				_indoorList[92]._sprites = wallItem._sprites;
+				_wp[6] = idx;
+			}
+		}
+
+		if (mazePos.x == (wallItem._position.x + SCREEN_POSITIONING_X[dir][16]) &&
+				mazePos.y == (wallItem._position.y + SCREEN_POSITIONING_Y[dir][16])) {
+			if (!_wo[26] && !_wo[29] && !_wo[21] && !_wo[18] && _wp[10] == -1) {
+				_indoorList[96]._frame = wallItem._frame;
+				_indoorList[96]._sprites = wallItem._sprites;
+				_wp[10] = idx;
+			}
+		}
+
+		if (mazePos.x == (wallItem._position.x + SCREEN_POSITIONING_X[dir][27]) &&
+				mazePos.y == (wallItem._position.y + SCREEN_POSITIONING_Y[dir][27])) {
+			if (!_wo[27] && !_wo[22] && !_wo[15] && _wp[15] == -1) {
+				_indoorList[50]._frame = wallItem._frame;
+				_indoorList[50]._sprites = wallItem._sprites;
+				_wp[15] = idx;
+			}
+		}
+
+		if (mazePos.x == (wallItem._position.x + SCREEN_POSITIONING_X[dir][25]) &&
+				mazePos.y == (wallItem._position.y + SCREEN_POSITIONING_Y[dir][25])) {
+			if (_wo[27]) {
+			} else if (_wo[27] && _wo[22]) {
+			} else if (_wo[15] && _wo[17]) {
+			} else if (_wo[15] && _wo[12]) {
+			} else if (_wo[12] && _wo[7]) {
+			} else if (_wo[17] && _wo[7]) {
+			} else if (_wp[14] == -1) {
+				_indoorList[49]._frame = wallItem._frame;
+				_indoorList[49]._sprites = wallItem._sprites;
+				_wp[14] = idx;
+			}
+		}
+
+		if (mazePos.x == (wallItem._position.x + SCREEN_POSITIONING_X[dir][23]) &&
+				mazePos.y == (wallItem._position.y + SCREEN_POSITIONING_Y[dir][23])) {
+			if (_wo[27]) {
+			} else if (_wo[22] && _wo[20]) {
+			} else if (_wo[22] && _wo[23]) {
+			} else if (_wo[20] && _wo[17]) {
+			} else if (_wo[23] && _wo[17]) {
+			} else if (_wo[12] && _wo[8]) {
+			} else if (_wp[13] == -1) {
+				_indoorList[48]._frame = wallItem._frame;
+				_indoorList[48]._sprites = wallItem._sprites;
+				_wp[13] = idx;
+			}
+		}
+
+		if (mazePos.x == (wallItem._position.x + SCREEN_POSITIONING_X[dir][29]) &&
+				mazePos.y == (wallItem._position.y + SCREEN_POSITIONING_Y[dir][29])) {
+			if (_wo[27] || _wo[22]) {
+			} else if (_wo[15] && _wo[19]) {
+			} else if (_wo[15] && _wo[14]) {
+			} else if (_wo[14] && _wo[9]) {
+			} else if (_wo[19] && _wo[9]) {
+			} else if (_wp[16] == -1) {
+				_indoorList[51]._frame = wallItem._frame;
+				_indoorList[51]._sprites = wallItem._sprites;
+				_wp[16] = idx;
+			}
+		}
+
+		if (mazePos.x == (wallItem._position.x + SCREEN_POSITIONING_X[dir][31]) &&
+				mazePos.y == (wallItem._position.y + SCREEN_POSITIONING_Y[dir][31])) {
+			if (_wo[27]) {
+			} else if (_wo[22] && _wo[21]) {
+			} else if (_wo[22] && _wo[24]) {
+			} else if (_wo[21] && _wo[19]) {
+			} else if (_wo[24] && _wo[19]) {
+			} else if (!_wo[14] && !_wo[10] && _wp[17] == -1) {
+				_indoorList[52]._frame = wallItem._frame;
+				_indoorList[52]._sprites = wallItem._sprites;
+				_wp[17] = idx;
+			}
+		}
+
+		if (mazePos.x == (wallItem._position.x + SCREEN_POSITIONING_X[dir][23]) &&
+				mazePos.y == (wallItem._position.y + SCREEN_POSITIONING_Y[dir][23])) {
+			if (!_wo[27] && !_wo[20] && !_wo[12] && !_wo[23] && !_wo[8] && !_wo[30]) {
+				if (_wp[12] == -1) {
+					_indoorList[47]._frame = wallItem._frame;
+					_indoorList[47]._sprites = wallItem._sprites;
+					_wp[12] = idx;
+				}
+			}
+		}
+
+		if (mazePos.x == (wallItem._position.x + SCREEN_POSITIONING_X[dir][31]) &&
+				mazePos.y == (wallItem._position.y + SCREEN_POSITIONING_Y[dir][31])) {
+			if (!_wo[27] && !_wo[21] && !_wo[14] && !_wo[24] && !_wo[10] && !_wo[31]) {
+				if (_wp[18] == -1) {
+					_indoorList[53]._frame = wallItem._frame;
+					_indoorList[53]._sprites = wallItem._sprites;
+					_wp[18] = idx;
+				}
+			}
+		}
+
+		if (mazePos.x == (wallItem._position.x + SCREEN_POSITIONING_X[dir][23]) &&
+				mazePos.y == (wallItem._position.y + SCREEN_POSITIONING_Y[dir][23])) {
+			if (!_wo[25] && !_wo[28] && !_wo[20] && !_wo[11] && !_wo[16] && !_wo[30] && !_wo[32]) {
+				if (_wp[11] == -1) {
+					_indoorList[46]._frame = wallItem._frame;
+					_indoorList[46]._sprites = wallItem._sprites;
+					_wp[11] = idx;
+				}
+			}
+		}
+
+		if (mazePos.x == (wallItem._position.x + SCREEN_POSITIONING_X[dir][31]) &&
+				mazePos.y == (wallItem._position.y + SCREEN_POSITIONING_Y[dir][31])) {
+			if (!_wo[26] && !_wo[20] && !_wo[21] && !_wo[13] && !_wo[18] && !_wo[31] && !_wo[33]) {
+				if (_wp[19] == -1) {
+					_indoorList[54]._frame = wallItem._frame;
+					_indoorList[54]._sprites = wallItem._sprites;
+					_wp[19] = idx;
+				}
+			}
+		}
+	}
 }
 
 void InterfaceMap::setOutdoorsMonsters() {
@@ -835,7 +1057,6 @@ void InterfaceMap::setOutdoorsObjects() {
 void InterfaceMap::drawIndoors() {
 	Map &map = *_vm->_map;
 	int surfaceId;
-	int idx;
 
 	for (int cellIndex = 0; cellIndex < 25; ++cellIndex) {
 		map.getCell(DRAW_NUMBERS[cellIndex]);
diff --git a/engines/xeen/interface_map.h b/engines/xeen/interface_map.h
index ea40c30..ae9abd2 100644
--- a/engines/xeen/interface_map.h
+++ b/engines/xeen/interface_map.h
@@ -105,11 +105,11 @@ public:
 public:
 	InterfaceMap(XeenEngine *vm);
 
-	void setIndoorsMonsters();
+	void setIndoorsAttackingMonsters();
 
 	void setIndoorObjects();
 
-	void setIndoorWallPics();
+	void setIndoorsWallPics();
 
 	void drawIndoors();
 
diff --git a/engines/xeen/map.cpp b/engines/xeen/map.cpp
index abb2cf6..a5a40c9 100644
--- a/engines/xeen/map.cpp
+++ b/engines/xeen/map.cpp
@@ -650,6 +650,7 @@ MazeMonster::MazeMonster() {
 
 MazeWallItem::MazeWallItem() {
 	_id = 0;
+	_frame = 0;
 	_spriteId = 0;
 	_direction = DIR_NORTH;
 	_sprites = nullptr;
diff --git a/engines/xeen/map.h b/engines/xeen/map.h
index 6ac8b36..8e6fee2 100644
--- a/engines/xeen/map.h
+++ b/engines/xeen/map.h
@@ -264,6 +264,7 @@ class MazeWallItem {
 public:
 	Common::Point _position;
 	int _id;
+	int _frame;
 	int _spriteId;
 	Direction _direction;
 	SpriteResource *_sprites;


Commit: 0ceefedce5ed33f545db9ab00b881d72ddd52186
    https://github.com/scummvm/scummvm/commit/0ceefedce5ed33f545db9ab00b881d72ddd52186
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-01-15T23:20:33-05:00

Commit Message:
XEEN: Fix frame calculations for low part of _indoorList

Changed paths:
    engines/xeen/interface_map.cpp
    engines/xeen/resources.cpp



diff --git a/engines/xeen/interface_map.cpp b/engines/xeen/interface_map.cpp
index d95868d..3d9ed10 100644
--- a/engines/xeen/interface_map.cpp
+++ b/engines/xeen/interface_map.cpp
@@ -1066,12 +1066,12 @@ void InterfaceMap::drawIndoors() {
 			drawStruct._sprites = &map._surfaceSprites[map._currentSurfaceId];
 
 		surfaceId = map.mazeData()._surfaceTypes[map._currentSurfaceId];
-		if (surfaceId == 5 || surfaceId == 12) {
-			drawStruct._flags = _flipWtr;
+		if (surfaceId == 0 || surfaceId == 5 || surfaceId == 12) {
+			drawStruct._flags = _flipWtr ? 1 : 0;
 			drawStruct._frame = DRAW_FRAMES[cellIndex][_flipWtr ? 1 : 0];
 		} else {
 			drawStruct._frame = DRAW_FRAMES[cellIndex][_flipWall ? 1 : 0];
-			drawStruct._flags = _flipWall ? 0 : SPRFLAG_HORIZ_FLIPPED;
+			drawStruct._flags = _flipWall ? SPRFLAG_HORIZ_FLIPPED : 0;
 		}
 	}
 
diff --git a/engines/xeen/resources.cpp b/engines/xeen/resources.cpp
index 87540b8..21a967d 100644
--- a/engines/xeen/resources.cpp
+++ b/engines/xeen/resources.cpp
@@ -433,15 +433,17 @@ const byte WALL_NUMBERS[4][96] = {
 };
 
 const int DRAW_NUMBERS[25] = {
-	36, 37, 38, 43, 42, 41, 39, 20, 22, 24, 33, 31, 29, 26, 10, 11,
-	18, 16, 13, 5, 9, 6, 0, 4, 1
+	36, 37, 38, 43, 42, 41, 
+	39, 20, 22, 24, 33, 31, 
+	29, 26, 10, 11, 18, 16, 
+	13, 5, 9, 6, 0, 4, 1
 };
 
 const int DRAW_FRAMES[25][2] = {
-	{ 18, 24 }, { 19, 23 }, { 20, 22 }, { 10, 24 }, { 19, 23 }, { 20, 22 },
-	{ 21, 21 }, { 11, 17 }, { 12, 16 }, { 13, 15 }, { 11, 17 }, { 12, 16 },
-	{ 13, 15 }, { 14, 14 }, { 6, 10 }, { 7, 9 }, { 6, 10 }, { 7, 9 },
-	{ 8, 8 }, { 3, 5 }, { 3, 5 }, { 4, 4 }, { 0, 2 }, { 0, 2 },
+	{ 18, 24 }, { 19, 23 }, { 20, 22 }, { 24, 18 }, { 23, 19 }, { 22, 20 },
+	{ 21, 21 }, { 11, 17 }, { 12, 16 }, { 13, 15 }, { 17, 11 }, { 16, 12 },
+	{ 15, 13 }, { 14, 14 }, { 6, 10 }, { 7, 9 }, { 10, 6 }, { 9, 7 },
+	{ 8, 8 }, { 3, 5 }, { 5, 3 }, { 4, 4 }, { 0, 2 }, { 2, 0 },
 	{ 1, 1 }
 };
 


Commit: b83b63b0cf161fa27352cb40fb19d8169b882b0f
    https://github.com/scummvm/scummvm/commit/b83b63b0cf161fa27352cb40fb19d8169b882b0f
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-01-15T23:37:52-05:00

Commit Message:
XEEN: Fix _wp switch statements

Changed paths:
    engines/xeen/interface.cpp
    engines/xeen/interface_map.h



diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp
index 7476abf..72bcdd9 100644
--- a/engines/xeen/interface.cpp
+++ b/engines/xeen/interface.cpp
@@ -862,7 +862,7 @@ void Interface::setMazeBits() {
 		break;
 	}
 
-	switch (_vm->_map->getCell(1)) {
+	switch (_vm->_map->getCell(1) - 1) {
 	case 1:
 		++_wo[72];
 		break;
@@ -932,7 +932,7 @@ void Interface::setMazeBits() {
 		break;
 	}
 
-	switch (_vm->_map->getCell(3)) {
+	switch (_vm->_map->getCell(3) - 1) {
 	case 1:
 		++_wo[73];
 		break;
@@ -1044,7 +1044,7 @@ void Interface::setMazeBits() {
 		break;
 	}
 
-	switch (_vm->_map->getCell(6)) {
+	switch (_vm->_map->getCell(6) - 1) {
 	case 1:
 		++_wo[67];
 		break;
@@ -1116,7 +1116,7 @@ void Interface::setMazeBits() {
 
 	_thinWall = (_vm->_map->_currentWall._data != 0x8888) && _wo[27];
 
-	switch (_vm->_map->getCell(8)) {
+	switch (_vm->_map->getCell(8) - 1) {
 	case 1:
 		++_wo[68];
 		break;
@@ -1231,7 +1231,7 @@ void Interface::setMazeBits() {
 		break;
 	}
 
-	switch (_vm->_map->getCell(11)) {
+	switch (_vm->_map->getCell(11) - 1) {
 	case 1:
 		++_wo[60];
 		break;
@@ -1301,7 +1301,7 @@ void Interface::setMazeBits() {
 		break;
 	}
 
-	switch (_vm->_map->getCell(13)) {
+	switch (_vm->_map->getCell(13) - 1) {
 	case 1:
 		++_wo[61];
 		break;
@@ -1371,7 +1371,7 @@ void Interface::setMazeBits() {
 		break;
 	}
 
-	switch (_vm->_map->getCell(15)) {
+	switch (_vm->_map->getCell(15) - 1) {
 	case 1:
 		++_wo[63];
 		break;
@@ -1441,7 +1441,7 @@ void Interface::setMazeBits() {
 		break;
 	}
 
-	switch (_vm->_map->getCell(17)) {
+	switch (_vm->_map->getCell(17) - 1) {
 	case 1:
 		++_wo[62];
 		break;
@@ -1556,7 +1556,7 @@ void Interface::setMazeBits() {
 		break;
 	}
 
-	switch (_vm->_map->getCell(20)) {
+	switch (_vm->_map->getCell(20) - 1) {
 	case 1:
 		++_wo[76];
 		break;
@@ -1626,7 +1626,7 @@ void Interface::setMazeBits() {
 		break;
 	}
 
-	switch (_vm->_map->getCell(22)) {
+	switch (_vm->_map->getCell(22) - 1) {
 	case 1:
 		++_wo[74];
 		break;
@@ -1696,7 +1696,7 @@ void Interface::setMazeBits() {
 		break;
 	}
 
-	switch (_vm->_map->getCell(24)) {
+	switch (_vm->_map->getCell(24) - 1) {
 	case 1:
 		++_wo[52];
 		break;
@@ -1766,7 +1766,7 @@ void Interface::setMazeBits() {
 		break;
 	}
 
-	switch (_vm->_map->getCell(26)) {
+	switch (_vm->_map->getCell(26) - 1) {
 	case 1:
 		++_wo[51];
 		break;
@@ -1836,7 +1836,7 @@ void Interface::setMazeBits() {
 		break;
 	}
 
-	switch (_vm->_map->getCell(28)) {
+	switch (_vm->_map->getCell(28) - 1) {
 	case 1:
 		++_wo[53];
 		break;
@@ -1906,7 +1906,7 @@ void Interface::setMazeBits() {
 		break;
 	}
 
-	switch (_vm->_map->getCell(30)) {
+	switch (_vm->_map->getCell(30) - 1) {
 	case 1:
 		++_wo[54];
 		break;
@@ -1975,7 +1975,7 @@ void Interface::setMazeBits() {
 		break;
 	}
 
-	switch (_vm->_map->getCell(32)) {
+	switch (_vm->_map->getCell(32) - 1) {
 	case 1:
 		++_wo[75];
 		break;
@@ -2045,7 +2045,7 @@ void Interface::setMazeBits() {
 		break;
 	}
 
-	switch (_vm->_map->getCell(34)) {
+	switch (_vm->_map->getCell(34) - 1) {
 	case 1:
 		++_wo[77];
 		break;
@@ -2115,7 +2115,7 @@ void Interface::setMazeBits() {
 		break;
 	}
 
-	switch (_vm->_map->getCell(36)) {
+	switch (_vm->_map->getCell(36) - 1) {
 	case 1:
 		++_wo[83];
 		break;
@@ -2139,7 +2139,7 @@ void Interface::setMazeBits() {
 		break;
 	}
 
-	switch (_vm->_map->getCell(37)) {
+	switch (_vm->_map->getCell(37) - 1) {
 	case 1:
 		++_wo[82];
 		break;
@@ -2163,7 +2163,7 @@ void Interface::setMazeBits() {
 		break;
 	}
 
-	switch (_vm->_map->getCell(38)) {
+	switch (_vm->_map->getCell(38) - 1) {
 	case 1:
 		++_wo[81];
 		break;
@@ -2187,7 +2187,7 @@ void Interface::setMazeBits() {
 		break;
 	}
 
-	switch (_vm->_map->getCell(34)) {
+	switch (_vm->_map->getCell(34) - 1) {
 	case 1:
 		++_wo[80];
 		break;
@@ -2211,7 +2211,7 @@ void Interface::setMazeBits() {
 		break;
 	}
 
-	switch (_vm->_map->getCell(40)) {
+	switch (_vm->_map->getCell(40) - 1) {
 	case 1:
 		++_wo[84];
 		break;
@@ -2235,7 +2235,7 @@ void Interface::setMazeBits() {
 		break;
 	}
 
-	switch (_vm->_map->getCell(41)) {
+	switch (_vm->_map->getCell(41) - 1) {
 	case 1:
 		++_wo[85];
 		break;
@@ -2259,7 +2259,7 @@ void Interface::setMazeBits() {
 		break;
 	}
 
-	switch (_vm->_map->getCell(42)) {
+	switch (_vm->_map->getCell(42) - 1) {
 	case 1:
 		++_wo[86];
 		break;
@@ -2283,7 +2283,7 @@ void Interface::setMazeBits() {
 		break;
 	}
 
-	switch (_vm->_map->getCell(43)) {
+	switch (_vm->_map->getCell(43) - 1) {
 	case 1:
 		++_wo[87];
 		break;
diff --git a/engines/xeen/interface_map.h b/engines/xeen/interface_map.h
index ae9abd2..e9f32bd 100644
--- a/engines/xeen/interface_map.h
+++ b/engines/xeen/interface_map.h
@@ -89,7 +89,7 @@ private:
 	void setMonsterSprite(DrawStruct &drawStruct, MazeMonster &monster, 
 		SpriteResource *sprites, int frame, int defaultY);
 protected:
-	byte _wp[20];
+	int8 _wp[20];
 	byte _wo[308];
 	int _overallFrame;
 	bool _flipWtr;


Commit: 484901e7a299f26afa1be9ca1644fee0aef7acf1
    https://github.com/scummvm/scummvm/commit/484901e7a299f26afa1be9ca1644fee0aef7acf1
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-01-16T08:30:27-05:00

Commit Message:
XEEN: Fixes and cleanup for setIndoorsObjects

Changed paths:
    engines/xeen/interface.cpp
    engines/xeen/interface_map.cpp
    engines/xeen/interface_map.h



diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp
index 72bcdd9..9aa76f6 100644
--- a/engines/xeen/interface.cpp
+++ b/engines/xeen/interface.cpp
@@ -560,8 +560,8 @@ void Interface::draw3d(bool updateFlag) {
 
 	// Loop to update the frame numbers for each maze object, applying the animation frame
 	// limits as specified by the map's _animationInfo listing
-	for (uint i = 0; i < map._mobData._objects.size(); ++i) {
-		MazeObject &mazeObject = map._mobData._objects[i];
+	for (uint idx = 0; idx < map._mobData._objects.size(); ++idx) {
+		MazeObject &mazeObject = map._mobData._objects[idx];
 		AnimationEntry &animEntry = map._animationInfo[mazeObject._spriteId];
 		int directionIndex = DIRECTION_ANIM_POSITIONS[mazeObject._direction][partyDirection];
 
@@ -569,13 +569,13 @@ void Interface::draw3d(bool updateFlag) {
 			mazeObject._frame = animEntry._frame1._frames[directionIndex];
 		} else {
 			++mazeObject._frame;
-			if ((int)i == objNum && _animCounter > 0 && (
+			if ((int)idx == objNum && _animCounter > 0 && (
 					objObject._spriteId == (_vm->_files->_isDarkCc ? 15 : 16) ||
 					objObject._spriteId == 58 || objObject._spriteId == 73)) {
 				if (mazeObject._frame > 4 || mazeObject._spriteId == 58)
 					mazeObject._frame = 1;
-			} else if (mazeObject._frame == animEntry._frame2._frames[directionIndex]) {
-				mazeObject._frame = animEntry._frame2._frames[directionIndex];
+			} else if (mazeObject._frame >= animEntry._frame2._frames[directionIndex]) {
+				mazeObject._frame = animEntry._frame1._frames[directionIndex];
 			}
 		}
 
diff --git a/engines/xeen/interface_map.cpp b/engines/xeen/interface_map.cpp
index 3d9ed10..da9c295 100644
--- a/engines/xeen/interface_map.cpp
+++ b/engines/xeen/interface_map.cpp
@@ -644,9 +644,9 @@ void InterfaceMap::setMonsterSprite(DrawStruct &drawStruct, MazeMonster &monster
 
 void InterfaceMap::setIndoorObjects() {
 	Common::Point mazePos = _vm->_party._mazePosition;
-	_objNumber = 0;
-	const int8 *posOffset = &SCREEN_POSITIONING_X[_vm->_party._mazeDirection][0];
+	Direction dir = _vm->_party._mazeDirection;
 	Common::Point pt;
+	_objNumber = 0;
 
 	Common::Array<MazeObject> &objects = _vm->_map->_mobData._objects;
 	for (uint idx = 0; idx < objects.size(); ++idx) {
@@ -656,14 +656,14 @@ void InterfaceMap::setIndoorObjects() {
 		int listOffset;
 		if (_vm->_files->_isDarkCc) {
 			listOffset = mazeObject._spriteId == 47 ? 1 : 0;
-		}
-		else {
+		} else {
 			listOffset = mazeObject._spriteId == 113 ? 1 : 0;
 		}
 
 		// Position 1
-		pt = Common::Point(mazePos.x + posOffset[2], mazePos.y + posOffset[194]);
-		if (pt == mazeObject._position && _indoorList._objects0._frame == -1) {
+		if ((mazePos.x + SCREEN_POSITIONING_X[dir][2]) == mazeObject._position.x
+			&& (mazePos.y + SCREEN_POSITIONING_Y[dir][2]) == mazeObject._position.y
+			&& _indoorList._objects0._frame == -1) {
 			_indoorList._objects0._x = INDOOR_OBJECT_X[listOffset][0];
 			_indoorList._objects0._y = INDOOR_OBJECT_Y[listOffset][0];
 			_indoorList._objects0._frame = mazeObject._frame;
@@ -675,8 +675,9 @@ void InterfaceMap::setIndoorObjects() {
 		}
 
 		// Position 2
-		pt = Common::Point(mazePos.x + posOffset[7], mazePos.y + posOffset[199]);
-		if (pt == mazeObject._position && !_wo[27] && _indoorList._objects1._frame == -1) {
+		if ((mazePos.x + SCREEN_POSITIONING_X[dir][7]) == mazeObject._position.x
+			&& (mazePos.y + SCREEN_POSITIONING_Y[dir][7]) == mazeObject._position.y
+			&& !_wo[27] && _indoorList._objects1._frame == -1) {
 			_indoorList._objects1._x = INDOOR_OBJECT_X[listOffset][1];
 			_indoorList._objects1._y = INDOOR_OBJECT_Y[listOffset][1];
 			_indoorList._objects1._frame = mazeObject._frame;
@@ -687,135 +688,181 @@ void InterfaceMap::setIndoorObjects() {
 		}
 
 		// Position 3
-		pt = Common::Point(mazePos.x + posOffset[5], mazePos.y + posOffset[197]);
-		if (pt == mazeObject._position && (!_wo[27] || !_wo[25]) && (!_wo[27] || !_wo[28]) &&
-				(!_wo[23] || !_wo[25]) && (!_wo[23] || !_wo[28]) && 
-				_indoorList._objects2._frame == -1) {
-			_indoorList._objects2._x = INDOOR_OBJECT_X[listOffset][2];
-			_indoorList._objects2._y = INDOOR_OBJECT_Y[listOffset][2];
-			_indoorList._objects2._frame = mazeObject._frame;
-			_indoorList._objects2._sprites = mazeObject._sprites;
-			_indoorList._objects2._flags &= ~SPRFLAG_HORIZ_FLIPPED;
-			if (mazeObject._flipped)
-				_indoorList._objects2._flags |= SPRFLAG_HORIZ_FLIPPED;
+		if ((mazePos.x + SCREEN_POSITIONING_X[dir][5]) == mazeObject._position.x
+			&& (mazePos.y + SCREEN_POSITIONING_Y[dir][5]) == mazeObject._position.y) {
+			if (_wo[27] && _wo[25]) {
+			} else if (_wo[27] && _wo[28]) {
+			} else if (_wo[23] && _wo[25]) {
+			} else if (_wo[23] && _wo[28]) {
+			} else if (_indoorList._objects2._frame == -1) {
+				_indoorList._objects2._x = INDOOR_OBJECT_X[listOffset][2];
+				_indoorList._objects2._y = INDOOR_OBJECT_Y[listOffset][2];
+				_indoorList._objects2._frame = mazeObject._frame;
+				_indoorList._objects2._sprites = mazeObject._sprites;
+				_indoorList._objects2._flags &= ~SPRFLAG_HORIZ_FLIPPED;
+				if (mazeObject._flipped)
+					_indoorList._objects2._flags |= SPRFLAG_HORIZ_FLIPPED;
+			}
 		}
 
 		// Position 4
-		pt = Common::Point(mazePos.x + posOffset[9], mazePos.y + posOffset[201]);
-		if (pt == mazeObject._position && (!_wo[27] || !_wo[26]) && (!_wo[27] || !_wo[29]) &&
-				(!_wo[24] || !_wo[26]) && (!_wo[24] || !_wo[29]) && _indoorList._objects3._frame == -1) {
-			_indoorList._objects3._x = INDOOR_OBJECT_X[listOffset][3];
-			_indoorList._objects3._y = INDOOR_OBJECT_Y[listOffset][3];
-			_indoorList._objects3._frame = mazeObject._frame;
-			_indoorList._objects3._sprites = mazeObject._sprites;
-			_indoorList._objects3._flags &= ~SPRFLAG_HORIZ_FLIPPED;
-			if (mazeObject._flipped)
-				_indoorList._objects3._flags |= SPRFLAG_HORIZ_FLIPPED;
+		if ((mazePos.x + SCREEN_POSITIONING_X[dir][9]) == mazeObject._position.x
+			&& (mazePos.y + SCREEN_POSITIONING_Y[dir][9]) == mazeObject._position.y) {
+			if (_wo[27] && _wo[26]) {
+			} else if (_wo[27] && _wo[29]) {
+			} else if (_wo[24] && _wo[26]) {
+			} else if (_wo[24] && _wo[29]) {
+			} else if (_indoorList._objects3._frame == -1) {
+				_indoorList._objects3._x = INDOOR_OBJECT_X[listOffset][3];
+				_indoorList._objects3._y = INDOOR_OBJECT_Y[listOffset][3];
+				_indoorList._objects3._frame = mazeObject._frame;
+				_indoorList._objects3._sprites = mazeObject._sprites;
+				_indoorList._objects3._flags &= ~SPRFLAG_HORIZ_FLIPPED;
+				if (mazeObject._flipped)
+					_indoorList._objects3._flags |= SPRFLAG_HORIZ_FLIPPED;
+			}
 		}
 
 		// Position 5
-		pt = Common::Point(mazePos.x + posOffset[14], mazePos.y + posOffset[206]);
-		if (pt == mazeObject._position && !_wo[22] && !_wo[27] && _indoorList._objects4._frame == -1) {
-			_indoorList._objects4._x = INDOOR_OBJECT_X[listOffset][4];
-			_indoorList._objects4._y = INDOOR_OBJECT_Y[listOffset][4];
-			_indoorList._objects4._frame = mazeObject._frame;
-			_indoorList._objects4._sprites = mazeObject._sprites;
-			_indoorList._objects4._flags &= ~SPRFLAG_HORIZ_FLIPPED;
-			if (mazeObject._flipped)
-				_indoorList._objects4._flags |= SPRFLAG_HORIZ_FLIPPED;
+		if ((mazePos.x + SCREEN_POSITIONING_X[dir][14]) == mazeObject._position.x
+			&& (mazePos.y + SCREEN_POSITIONING_Y[dir][14]) == mazeObject._position.y) {
+			if (!_wo[22] && !_wo[27] && _indoorList._objects4._frame == -1) {
+				_indoorList._objects4._x = INDOOR_OBJECT_X[listOffset][4];
+				_indoorList._objects4._y = INDOOR_OBJECT_Y[listOffset][4];
+				_indoorList._objects4._frame = mazeObject._frame;
+				_indoorList._objects4._sprites = mazeObject._sprites;
+				_indoorList._objects4._flags &= ~SPRFLAG_HORIZ_FLIPPED;
+				if (mazeObject._flipped)
+					_indoorList._objects4._flags |= SPRFLAG_HORIZ_FLIPPED;
+			}
 		}
 
 		// Position 6
-		pt = Common::Point(mazePos.x + posOffset[12], mazePos.y + posOffset[204]);
-		if (pt == mazeObject._position && !_wo[27] && (!_wo[22] || !_wo[23]) && (!_wo[22] || !_wo[20]) &&
-				(!_wo[23] || !_wo[17]) && (!_wo[20] || !_wo[17]) && _indoorList._objects5._frame == -1) {
-			_indoorList._objects5._x = INDOOR_OBJECT_X[listOffset][5];
-			_indoorList._objects5._y = INDOOR_OBJECT_Y[listOffset][5];
-			_indoorList._objects5._frame = mazeObject._frame;
-			_indoorList._objects5._sprites = mazeObject._sprites;
-			_indoorList._objects5._flags &= ~SPRFLAG_HORIZ_FLIPPED;
-			if (mazeObject._flipped)
-				_indoorList._objects5._flags |= SPRFLAG_HORIZ_FLIPPED;
+		if ((mazePos.x + SCREEN_POSITIONING_X[dir][12]) == mazeObject._position.x
+			&& (mazePos.y + SCREEN_POSITIONING_Y[dir][12]) == mazeObject._position.y) {
+			if (_wo[27]) {
+			} else if (_wo[22] && _wo[23]) {
+			} else if (_wo[22] && _wo[20]) {
+			} else if (_wo[23] && _wo[17]) {
+			} else if (_wo[20] && _wo[17]) {
+			} else if (_indoorList._objects5._frame == -1) {
+				_indoorList._objects5._x = INDOOR_OBJECT_X[listOffset][5];
+				_indoorList._objects5._y = INDOOR_OBJECT_Y[listOffset][5];
+				_indoorList._objects5._frame = mazeObject._frame;
+				_indoorList._objects5._sprites = mazeObject._sprites;
+				_indoorList._objects5._flags &= ~SPRFLAG_HORIZ_FLIPPED;
+				if (mazeObject._flipped)
+					_indoorList._objects5._flags |= SPRFLAG_HORIZ_FLIPPED;
+			}
 		}
 
 		// Position 7
-		pt = Common::Point(mazePos.x + posOffset[16], mazePos.y + posOffset[208]);
-		if (pt == mazeObject._position && !_wo[27] && (!_wo[22] || !_wo[24]) && (!_wo[22] || !_wo[21]) &&
-			(!_wo[24] || !_wo[19]) && (!_wo[21] || !_wo[19]) && _indoorList._objects6._frame == -1) {
-			_indoorList._objects6._x = INDOOR_OBJECT_X[listOffset][6];
-			_indoorList._objects6._y = INDOOR_OBJECT_Y[listOffset][6];
-			_indoorList._objects6._frame = mazeObject._frame;
-			_indoorList._objects6._sprites = mazeObject._sprites;
-			_indoorList._objects6._flags &= ~SPRFLAG_HORIZ_FLIPPED;
-			if (mazeObject._flipped)
-				_indoorList._objects6._flags |= SPRFLAG_HORIZ_FLIPPED;
+		if ((mazePos.x + SCREEN_POSITIONING_X[dir][16]) == mazeObject._position.x
+			&& (mazePos.y + SCREEN_POSITIONING_Y[dir][16]) == mazeObject._position.y) {
+			if (_wo[27]) {
+			} else if (_wo[22] && _wo[24]) {
+			} else if (_wo[22] && _wo[21]) {
+			} else if (_wo[24] && _wo[19]) {
+			} else if (_wo[21] && _wo[19]) {
+			} else if (_indoorList._objects6._frame == -1) {
+				_indoorList._objects6._x = INDOOR_OBJECT_X[listOffset][6];
+				_indoorList._objects6._y = INDOOR_OBJECT_Y[listOffset][6];
+				_indoorList._objects6._frame = mazeObject._frame;
+				_indoorList._objects6._sprites = mazeObject._sprites;
+				_indoorList._objects6._flags &= ~SPRFLAG_HORIZ_FLIPPED;
+				if (mazeObject._flipped)
+					_indoorList._objects6._flags |= SPRFLAG_HORIZ_FLIPPED;
+			}
 		}
 
 		// Position 8
-		pt = Common::Point(mazePos.x + posOffset[27], mazePos.y + posOffset[219]);
-		if (pt == mazeObject._position && !_wo[27] && !_wo[22] && !_wo[15] &&  _indoorList._objects7._frame == -1) {
-			_indoorList._objects7._x = INDOOR_OBJECT_X[listOffset][7];
-			_indoorList._objects7._y = INDOOR_OBJECT_Y[listOffset][7];
-			_indoorList._objects7._frame = mazeObject._frame;
-			_indoorList._objects7._sprites = mazeObject._sprites;
-			_indoorList._objects7._flags &= ~SPRFLAG_HORIZ_FLIPPED;
-			if (mazeObject._flipped)
-				_indoorList._objects7._flags |= SPRFLAG_HORIZ_FLIPPED;
+		if ((mazePos.x + SCREEN_POSITIONING_X[dir][27]) == mazeObject._position.x
+			&& (mazePos.y + SCREEN_POSITIONING_Y[dir][27]) == mazeObject._position.y) {
+			if (!_wo[27] && !_wo[22] && !_wo[15] && _indoorList._objects7._frame == -1) {
+				_indoorList._objects7._x = INDOOR_OBJECT_X[listOffset][7];
+				_indoorList._objects7._y = INDOOR_OBJECT_Y[listOffset][7];
+				_indoorList._objects7._frame = mazeObject._frame;
+				_indoorList._objects7._sprites = mazeObject._sprites;
+				_indoorList._objects7._flags &= ~SPRFLAG_HORIZ_FLIPPED;
+				if (mazeObject._flipped)
+					_indoorList._objects7._flags |= SPRFLAG_HORIZ_FLIPPED;
+			}
 		}
 
 		// Position 9
-		pt = Common::Point(mazePos.x + posOffset[25], mazePos.y + posOffset[217]);
-		if (pt == mazeObject._position && !_wo[27] && (!_wo[15] || !_wo[17]) && (!_wo[15] || !_wo[12]) &&
-				(!_wo[12] || !_wo[7]) && (!_wo[17] || !_wo[7]) && _indoorList._objects5._frame == -1) {
-			_indoorList._objects8._x = INDOOR_OBJECT_X[listOffset][8];
-			_indoorList._objects8._y = INDOOR_OBJECT_Y[listOffset][8];
-			_indoorList._objects8._frame = mazeObject._frame;
-			_indoorList._objects8._sprites = mazeObject._sprites;
-			_indoorList._objects8._flags &= ~SPRFLAG_HORIZ_FLIPPED;
-			if (mazeObject._flipped)
-				_indoorList._objects8._flags |= SPRFLAG_HORIZ_FLIPPED;
+		if ((mazePos.x + SCREEN_POSITIONING_X[dir][25]) == mazeObject._position.x
+			&& (mazePos.y + SCREEN_POSITIONING_Y[dir][25]) == mazeObject._position.y) {
+			if (_wo[27] || _wo[22]) {
+			} else if (_wo[15] && _wo[17]) {
+			} else if (_wo[15] && _wo[12]) {
+			} else if (_wo[12] && _wo[7]) {
+			} else if (_wo[17] && _wo[7]) {
+			} else if (_indoorList._objects8._frame == -1) {
+				_indoorList._objects8._x = INDOOR_OBJECT_X[listOffset][8];
+				_indoorList._objects8._y = INDOOR_OBJECT_Y[listOffset][8];
+				_indoorList._objects8._frame = mazeObject._frame;
+				_indoorList._objects8._sprites = mazeObject._sprites;
+				_indoorList._objects8._flags &= ~SPRFLAG_HORIZ_FLIPPED;
+				if (mazeObject._flipped)
+					_indoorList._objects8._flags |= SPRFLAG_HORIZ_FLIPPED;
+			}
 		}
 
 		// Position 10
-		pt = Common::Point(mazePos.x + posOffset[23], mazePos.y + posOffset[215]);
-		if (pt == mazeObject._position && !_wo[27] && (!_wo[22] || !_wo[20]) && (!_wo[22] || !_wo[23]) &&
-				(!_wo[20] || !_wo[17]) && (!_wo[23] || !_wo[17]) && !_wo[12] && !_wo[8] &&			
-				_indoorList._objects9._frame == -1) {
-			_indoorList._objects9._x = INDOOR_OBJECT_X[listOffset][9];
-			_indoorList._objects9._y = INDOOR_OBJECT_Y[listOffset][9];
-			_indoorList._objects9._frame = mazeObject._frame;
-			_indoorList._objects9._sprites = mazeObject._sprites;
-			_indoorList._objects9._flags &= ~SPRFLAG_HORIZ_FLIPPED;
-			if (mazeObject._flipped)
-				_indoorList._objects9._flags |= SPRFLAG_HORIZ_FLIPPED;
+		if ((mazePos.x + SCREEN_POSITIONING_X[dir][23]) == mazeObject._position.x
+			&& (mazePos.y + SCREEN_POSITIONING_Y[dir][23]) == mazeObject._position.y) {
+			if (_wo[27]) {
+			} else if (_wo[22] && _wo[20]) {
+			} else if (_wo[22] && _wo[23]) {
+			} else if (_wo[20] && _wo[17]) {
+			} else if (_wo[23] && _wo[17]) {
+			} else if (!_wo[12] && !_wo[8] && _indoorList._objects9._frame == -1) {
+				_indoorList._objects9._x = INDOOR_OBJECT_X[listOffset][9];
+				_indoorList._objects9._y = INDOOR_OBJECT_Y[listOffset][9];
+				_indoorList._objects9._frame = mazeObject._frame;
+				_indoorList._objects9._sprites = mazeObject._sprites;
+				_indoorList._objects9._flags &= ~SPRFLAG_HORIZ_FLIPPED;
+				if (mazeObject._flipped)
+					_indoorList._objects9._flags |= SPRFLAG_HORIZ_FLIPPED;
+			}
 		}
 
 		// Block 11
-		pt = Common::Point(mazePos.x + posOffset[29], mazePos.y + posOffset[221]);
-		if (pt == mazeObject._position && !_wo[27] && !_wo[22] && (!_wo[15] || !_wo[19]) && 
-				(!_wo[15] || !_wo[14]) && (!_wo[14] || !_wo[9]) && (!_wo[19] || !_wo[9]) && 
-				_indoorList._objects10._frame == -1) {
-			_indoorList._objects10._x = INDOOR_OBJECT_X[listOffset][10];
-			_indoorList._objects10._y = INDOOR_OBJECT_Y[listOffset][10];
-			_indoorList._objects10._frame = mazeObject._frame;
-			_indoorList._objects10._sprites = mazeObject._sprites;
-			_indoorList._objects10._flags &= ~SPRFLAG_HORIZ_FLIPPED;
-			if (mazeObject._flipped)
-				_indoorList._objects10._flags |= SPRFLAG_HORIZ_FLIPPED;
+		if ((mazePos.x + SCREEN_POSITIONING_X[dir][29]) == mazeObject._position.x
+			&& (mazePos.y + SCREEN_POSITIONING_Y[dir][29]) == mazeObject._position.y) {
+			if (_wo[27]) {
+			} else if (_wo[15] && _wo[19]) {
+			} else if (_wo[15] && _wo[14]) {
+			} else if (_wo[14] && _wo[9]) {
+			} else if (_wo[19] && _wo[9]) {
+			} else if (_indoorList._objects10._frame == -1) {
+				_indoorList._objects10._x = INDOOR_OBJECT_X[listOffset][10];
+				_indoorList._objects10._y = INDOOR_OBJECT_Y[listOffset][10];
+				_indoorList._objects10._frame = mazeObject._frame;
+				_indoorList._objects10._sprites = mazeObject._sprites;
+				_indoorList._objects10._flags &= ~SPRFLAG_HORIZ_FLIPPED;
+				if (mazeObject._flipped)
+					_indoorList._objects10._flags |= SPRFLAG_HORIZ_FLIPPED;
+			}
 		}
 
 		// Block 12
-		pt = Common::Point(mazePos.x + posOffset[31], mazePos.y + posOffset[223]);
-		if (pt == mazeObject._position && !_wo[27] && (!_wo[22] || !_wo[21]) && (!_wo[22] || !_wo[24]) && 
-				(!_wo[21] || !_wo[19]) && (!_wo[24] || !_wo[19]) && !_wo[14] && !_wo[10] &&
-				_indoorList._objects11._frame == -1) {
-			_indoorList._objects11._x = INDOOR_OBJECT_X[listOffset][11];
-			_indoorList._objects11._y = INDOOR_OBJECT_Y[listOffset][11];
-			_indoorList._objects11._frame = mazeObject._frame;
-			_indoorList._objects11._sprites = mazeObject._sprites;
-			_indoorList._objects11._flags &= ~SPRFLAG_HORIZ_FLIPPED;
-			if (mazeObject._flipped)
-				_indoorList._objects11._flags |= SPRFLAG_HORIZ_FLIPPED;
+		if ((mazePos.x + SCREEN_POSITIONING_X[dir][31]) == mazeObject._position.x
+			&& (mazePos.y + SCREEN_POSITIONING_Y[dir][31]) == mazeObject._position.y) {
+			if (_wo[27]) {
+			} else if (_wo[22] && _wo[21]) {
+			} else if (_wo[22] && _wo[24]) {
+			} else if (_wo[21] && _wo[19]) {
+			} else if (_wo[24] && _wo[19]) {
+			} else if (!_wo[14] && !_wo[10] && !_indoorList._objects11._frame == -1) {
+				_indoorList._objects11._x = INDOOR_OBJECT_X[listOffset][11];
+				_indoorList._objects11._y = INDOOR_OBJECT_Y[listOffset][11];
+				_indoorList._objects11._frame = mazeObject._frame;
+				_indoorList._objects11._sprites = mazeObject._sprites;
+				_indoorList._objects11._flags &= ~SPRFLAG_HORIZ_FLIPPED;
+				if (mazeObject._flipped)
+					_indoorList._objects11._flags |= SPRFLAG_HORIZ_FLIPPED;
+			}
 		}
 	}
 }
diff --git a/engines/xeen/interface_map.h b/engines/xeen/interface_map.h
index e9f32bd..8013228 100644
--- a/engines/xeen/interface_map.h
+++ b/engines/xeen/interface_map.h
@@ -53,20 +53,20 @@ public:
 	DrawStruct &_sky;
 	DrawStruct &_ground;
 	DrawStruct &_horizon;
-	DrawStruct &_swl_0F1R, _swl_0F1L, _swl_1F1R, _swl_1F1L,
-		_swl_2F2R, _swl_2F1R, _swl_2F1L, _swl_2F2L,
-		_swl_3F1R, _swl_3F2R, _swl_3F3R, _swl_3F4R,
-		_swl_3F1L, _swl_3F2L, _swl_3F3L, _swl_3F4L,
-		_swl_4F4R, _swl_4F3R, _swl_4F2R, _swl_4F1R,
-		_swl_4F1L, _swl_4F2L, _swl_4F3L, _swl_4F4L;
-	DrawStruct &_fwl_4F4R, _fwl_4F3R, _fwl_4F2R, _fwl_4F1R,
-		_fwl_4F, _fwl_4F1L, _fwl_4F2L, _fwl_4F3L, _fwl_4F4L;
-	DrawStruct &_fwl_2F1R, _fwl_2F, _fwl_2F1L, _fwl_3F2R,
-		_fwl_3F1R, _fwl_3F, _fwl_3F1L, _fwl_3F2L;
-	DrawStruct &_fwl_1F, _fwl_1F1R, _fwl_1F1L;
-	DrawStruct &_objects0, _objects1, _objects2, _objects3;
-	DrawStruct &_objects4, _objects5, _objects6, _objects7;
-	DrawStruct &_objects8, _objects9, _objects10, _objects11;
+	DrawStruct &_swl_0F1R, &_swl_0F1L, &_swl_1F1R, &_swl_1F1L,
+		&_swl_2F2R, &_swl_2F1R, &_swl_2F1L, &_swl_2F2L,
+		&_swl_3F1R, &_swl_3F2R, &_swl_3F3R, &_swl_3F4R,
+		&_swl_3F1L, &_swl_3F2L, &_swl_3F3L, &_swl_3F4L,
+		&_swl_4F4R, &_swl_4F3R, &_swl_4F2R, &_swl_4F1R,
+		&_swl_4F1L, &_swl_4F2L, &_swl_4F3L, &_swl_4F4L;
+	DrawStruct &_fwl_4F4R, &_fwl_4F3R, &_fwl_4F2R, &_fwl_4F1R,
+		&_fwl_4F, &_fwl_4F1L, &_fwl_4F2L, &_fwl_4F3L, &_fwl_4F4L;
+	DrawStruct &_fwl_2F1R, &_fwl_2F, &_fwl_2F1L, &_fwl_3F2R,
+		&_fwl_3F1R, &_fwl_3F, &_fwl_3F1L, &_fwl_3F2L;
+	DrawStruct &_fwl_1F, &_fwl_1F1R, &_fwl_1F1L;
+	DrawStruct &_objects0, &_objects1, &_objects2, &_objects3;
+	DrawStruct &_objects4, &_objects5, &_objects6, &_objects7;
+	DrawStruct &_objects8, &_objects9, &_objects10, &_objects11;
 public:
 	IndoorDrawList();
 


Commit: 6bfd599535b839ce51261ff7ed82bbca92538050
    https://github.com/scummvm/scummvm/commit/6bfd599535b839ce51261ff7ed82bbca92538050
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-01-16T21:26:06-05:00

Commit Message:
XEEN: Fixes for map loading cells and indoor sprite list references

Changed paths:
    engines/xeen/interface.cpp
    engines/xeen/interface_map.cpp
    engines/xeen/interface_map.h
    engines/xeen/map.cpp



diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp
index 9aa76f6..f3060c2 100644
--- a/engines/xeen/interface.cpp
+++ b/engines/xeen/interface.cpp
@@ -662,7 +662,7 @@ void Interface::draw3d(bool updateFlag) {
 		}
 
 		setIndoorsAttackingMonsters();
-		setIndoorObjects();
+		setIndoorsObjects();
 		setIndoorsWallPics();
 
 		_indoorList[161]._sprites = nullptr;
@@ -757,7 +757,7 @@ void Interface::startup() {
 	animate3d();
 	if (_vm->_map->_isOutdoors) {
 		setIndoorsAttackingMonsters();
-		setIndoorObjects();
+		setIndoorsObjects();
 	} else {
 		setOutdoorsMonsters();
 		setOutdoorsObjects();
@@ -816,7 +816,7 @@ void Interface::setMainButtons() {
 void Interface::setMazeBits() {
 	Common::fill(&_wo[0], &_wo[308], 0);
 
-	switch (_vm->_map->getCell(0)) {
+	switch (_vm->_map->getCell(0) - 1) {
 	case 0:
 		++_wo[125];
 		break;
@@ -886,7 +886,7 @@ void Interface::setMazeBits() {
 		break;
 	}
 
-	switch (_vm->_map->getCell(2)) {
+	switch (_vm->_map->getCell(2) - 1) {
 	case 0:
 		++_wo[127];
 		break;
@@ -956,7 +956,7 @@ void Interface::setMazeBits() {
 		break;
 	}
 
-	switch (_vm->_map->getCell(4)) {
+	switch (_vm->_map->getCell(4) - 1) {
 	case 0:
 		++_wo[126];
 		break;
@@ -1002,7 +1002,7 @@ void Interface::setMazeBits() {
 		break;
 	}
 
-	switch (_vm->_map->getCell(5)) {
+	switch (_vm->_map->getCell(5) - 1) {
 	case 0:
 		++_wo[122];
 		break;
@@ -1068,7 +1068,7 @@ void Interface::setMazeBits() {
 		break;
 	}
 
-	switch (_vm->_map->getCell(7)) {
+	switch (_vm->_map->getCell(7) - 1) {
 	case 0:
 		++_wo[124];
 		break;
@@ -1140,7 +1140,7 @@ void Interface::setMazeBits() {
 		break;
 	}
 
-	switch (_vm->_map->getCell(9)) {
+	switch (_vm->_map->getCell(9) - 1) {
 	case 0:
 		++_wo[123];
 		break;
@@ -1186,7 +1186,7 @@ void Interface::setMazeBits() {
 		break;
 	}
 
-	switch (_vm->_map->getCell(10)) {
+	switch (_vm->_map->getCell(10) - 1) {
 	case 0:
 		++_wo[117];
 		break;
@@ -1255,7 +1255,7 @@ void Interface::setMazeBits() {
 		break;
 	}
 
-	switch (_vm->_map->getCell(12)) {
+	switch (_vm->_map->getCell(12) - 1) {
 	case 0:
 		++_wo[118];
 		break;
@@ -1325,7 +1325,7 @@ void Interface::setMazeBits() {
 		break;
 	}
 
-	switch (_vm->_map->getCell(14)) {
+	switch (_vm->_map->getCell(14) - 1) {
 	case 0:
 		++_wo[121];
 		break;
@@ -1395,7 +1395,7 @@ void Interface::setMazeBits() {
 		break;
 	}
 
-	switch (_vm->_map->getCell(16)) {
+	switch (_vm->_map->getCell(16) - 1) {
 	case 0:
 		++_wo[120];
 		break;
@@ -1465,7 +1465,7 @@ void Interface::setMazeBits() {
 		break;
 	}
 
-	switch (_vm->_map->getCell(18)) {
+	switch (_vm->_map->getCell(18) - 1) {
 	case 0:
 		++_wo[119];
 		break;
@@ -1511,7 +1511,7 @@ void Interface::setMazeBits() {
 		break;
 	}
 
-	switch (_vm->_map->getCell(19)) {
+	switch (_vm->_map->getCell(19) - 1) {
 	case 0:
 		++_wo[108];
 		break;
@@ -1580,7 +1580,7 @@ void Interface::setMazeBits() {
 		break;
 	}
 
-	switch (_vm->_map->getCell(21)) {
+	switch (_vm->_map->getCell(21) - 1) {
 	case 0:
 		++_wo[109];
 		break;
@@ -1650,7 +1650,7 @@ void Interface::setMazeBits() {
 		break;
 	}
 
-	switch (_vm->_map->getCell(23)) {
+	switch (_vm->_map->getCell(23) - 1) {
 	case 0:
 		++_wo[110];
 		break;
@@ -1720,7 +1720,7 @@ void Interface::setMazeBits() {
 		break;
 	}
 
-	switch (_vm->_map->getCell(25)) {
+	switch (_vm->_map->getCell(25) - 1) {
 	case 0:
 		++_wo[111];
 		break;
@@ -1790,7 +1790,7 @@ void Interface::setMazeBits() {
 		break;
 	}
 
-	switch (_vm->_map->getCell(27)) {
+	switch (_vm->_map->getCell(27) - 1) {
 	case 0:
 		++_wo[116];
 		break;
@@ -1860,7 +1860,7 @@ void Interface::setMazeBits() {
 		break;
 	}
 
-	switch (_vm->_map->getCell(29)) {
+	switch (_vm->_map->getCell(29) - 1) {
 	case 0:
 		++_wo[115];
 		break;
@@ -1930,7 +1930,7 @@ void Interface::setMazeBits() {
 		break;
 	}
 
-	switch (_vm->_map->getCell(31)) {
+	switch (_vm->_map->getCell(31) - 1) {
 	case 0:
 		++_wo[114];
 		break;
@@ -1999,7 +1999,7 @@ void Interface::setMazeBits() {
 		break;
 	}
 
-	switch (_vm->_map->getCell(33)) {
+	switch (_vm->_map->getCell(33) - 1) {
 	case 0:
 		++_wo[112];
 		break;
@@ -2069,7 +2069,7 @@ void Interface::setMazeBits() {
 		break;
 	}
 
-	switch (_vm->_map->getCell(35)) {
+	switch (_vm->_map->getCell(35) - 1) {
 	case 0:
 		++_wo[113];
 		break;
diff --git a/engines/xeen/interface_map.cpp b/engines/xeen/interface_map.cpp
index da9c295..6780a5c 100644
--- a/engines/xeen/interface_map.cpp
+++ b/engines/xeen/interface_map.cpp
@@ -166,7 +166,7 @@ OutdoorDrawList::OutdoorDrawList() : _skySprite(_data[1]), _groundSprite(_data[2
 
 IndoorDrawList::IndoorDrawList() : 
 	_sky(_data[1]), _ground(_data[2]), _horizon(_data[28]),
-	_swl_0F1R(_data[ 46]), _swl_0F1L(_data[44]),  _swl_1F1R(_data[134]), 
+	_swl_0F1R(_data[146]), _swl_0F1L(_data[144]), _swl_1F1R(_data[134]), 
 	_swl_1F1L(_data[133]), _swl_2F2R(_data[110]), _swl_2F1R(_data[109]), 
 	_swl_2F1L(_data[108]), _swl_2F2L(_data[107]), _swl_3F1R(_data[ 78]), 
 	_swl_3F2R(_data[ 77]), _swl_3F3R(_data[ 76]), _swl_3F4R(_data[ 75]),
@@ -377,6 +377,7 @@ InterfaceMap::InterfaceMap(XeenEngine *vm): _vm(vm) {
 void InterfaceMap::setIndoorsAttackingMonsters() {
 	Combat &combat = *_vm->_combat;
 	Map &map = *_vm->_map;
+	Common::Point mazePos = _vm->_party._mazePosition;
 	Direction dir = _vm->_party._mazeDirection;
 	const int INDOOR_MONSTERS_Y[4] = { 2, 34, 53, 59 };
 
@@ -392,8 +393,8 @@ void InterfaceMap::setIndoorsAttackingMonsters() {
 		}
 
 		// The following long sequence sets up monsters in the various positions
-		if (monster._position.x == SCREEN_POSITIONING_X[dir][2] &&
-				monster._position.y == SCREEN_POSITIONING_Y[dir][2]) {
+		if (monster._position.x == (mazePos.x + SCREEN_POSITIONING_X[dir][2]) &&
+				monster._position.y == (mazePos.y + SCREEN_POSITIONING_Y[dir][2])) {
 			monster._isAttacking = true;
 			if (combat._attackMonsters[0] == -1) {
 				combat._attackMonsters[0] = monsterIdx;
@@ -407,8 +408,8 @@ void InterfaceMap::setIndoorsAttackingMonsters() {
 			}
 		}
 
-		if (monster._position.x == SCREEN_POSITIONING_X[dir][7] &&
-				monster._position.y == SCREEN_POSITIONING_Y[dir][7]) {
+		if (monster._position.x == (mazePos.x + SCREEN_POSITIONING_X[dir][7]) &&
+				monster._position.y == (mazePos.y + SCREEN_POSITIONING_Y[dir][7])) {
 			monster._isAttacking = true;
 			if (!_wo[27]) {
 				if (combat._attackMonsters[3] == -1) {
@@ -424,8 +425,8 @@ void InterfaceMap::setIndoorsAttackingMonsters() {
 			}
 		}
 
-		if (monster._position.x == SCREEN_POSITIONING_X[dir][5] &&
-			monster._position.y == SCREEN_POSITIONING_Y[dir][5]) {
+		if (monster._position.x == (mazePos.x + SCREEN_POSITIONING_X[dir][5]) &&
+			monster._position.y == (mazePos.y + SCREEN_POSITIONING_Y[dir][5])) {
 			if (_wo[27] && _wo[25]) {
 			} else if (_wo[27] && _wo[28]) {
 			} else if (_wo[23] & _wo[25]) {
@@ -440,8 +441,8 @@ void InterfaceMap::setIndoorsAttackingMonsters() {
 			}
 		}
 
-		if (monster._position.x == SCREEN_POSITIONING_X[dir][9] &&
-			monster._position.y == SCREEN_POSITIONING_Y[dir][9]) {
+		if (monster._position.x == (mazePos.x + SCREEN_POSITIONING_X[dir][9]) &&
+			monster._position.y == (mazePos.y + SCREEN_POSITIONING_Y[dir][9])) {
 			if (_wo[27] && _wo[26]) {
 			} else if (_wo[27] && _wo[29]) {
 			} else if (_wo[24] & _wo[26]) {
@@ -456,8 +457,8 @@ void InterfaceMap::setIndoorsAttackingMonsters() {
 			}
 		}
 
-		if (monster._position.x == SCREEN_POSITIONING_X[dir][14] &&
-			monster._position.y == SCREEN_POSITIONING_Y[dir][14]) {
+		if (monster._position.x == (mazePos.x + SCREEN_POSITIONING_X[dir][14]) &&
+			monster._position.y == (mazePos.y + SCREEN_POSITIONING_Y[dir][14])) {
 			monster._isAttacking = true;
 
 			if (!_wo[22] && !_wo[27]) {
@@ -474,8 +475,8 @@ void InterfaceMap::setIndoorsAttackingMonsters() {
 			}
 		}
 
-		if (monster._position.x == SCREEN_POSITIONING_X[dir][12] &&
-			monster._position.y == SCREEN_POSITIONING_Y[dir][12]) {
+		if (monster._position.x == (mazePos.x + SCREEN_POSITIONING_X[dir][12]) &&
+			monster._position.y == (mazePos.y + SCREEN_POSITIONING_Y[dir][12])) {
 			if (_wo[27]) {
 			} else if (_wo[22] && _wo[23]) {
 			} else if (_wo[22] & _wo[20]) {
@@ -493,8 +494,8 @@ void InterfaceMap::setIndoorsAttackingMonsters() {
 			}
 		}
 
-		if (monster._position.x == SCREEN_POSITIONING_X[dir][16] &&
-			monster._position.y == SCREEN_POSITIONING_Y[dir][16]) {
+		if (monster._position.x == (mazePos.x + SCREEN_POSITIONING_X[dir][16]) &&
+			monster._position.y == (mazePos.y + SCREEN_POSITIONING_Y[dir][16])) {
 			if (_wo[27]) {
 			} else if (_wo[22] && _wo[24]) {
 			} else if (_wo[22] & _wo[21]) {
@@ -513,8 +514,8 @@ void InterfaceMap::setIndoorsAttackingMonsters() {
 			}
 		}
 
-		if (monster._position.x == SCREEN_POSITIONING_X[dir][27] &&
-			monster._position.y == SCREEN_POSITIONING_Y[dir][27]) {
+		if (monster._position.x == (mazePos.x + SCREEN_POSITIONING_X[dir][27]) &&
+			monster._position.y == (mazePos.y + SCREEN_POSITIONING_Y[dir][27])) {
 			if (!_wo[27] && !_wo[22] && _wo[15]) {
 				monster._isAttacking = true;
 
@@ -531,8 +532,8 @@ void InterfaceMap::setIndoorsAttackingMonsters() {
 			}
 		}
 
-		if (monster._position.x == SCREEN_POSITIONING_X[dir][25] &&
-			monster._position.y == SCREEN_POSITIONING_Y[dir][25]) {
+		if (monster._position.x == (mazePos.x + SCREEN_POSITIONING_X[dir][25]) &&
+			monster._position.y == (mazePos.y + SCREEN_POSITIONING_Y[dir][25])) {
 			if (_wo[27] || _wo[22]) {
 			} else if (_wo[15] && _wo[17]) {
 			} else if (_wo[15] && _wo[12]) {
@@ -554,8 +555,8 @@ void InterfaceMap::setIndoorsAttackingMonsters() {
 			}
 		}
 
-		if (monster._position.x == SCREEN_POSITIONING_X[dir][23] &&
-			monster._position.y == SCREEN_POSITIONING_Y[dir][23]) {
+		if (monster._position.x == (mazePos.x + SCREEN_POSITIONING_X[dir][23]) &&
+			monster._position.y == (mazePos.y + SCREEN_POSITIONING_Y[dir][23])) {
 			if (_wo[27]) {
 			} else if (_wo[22] && _wo[20]) {
 			} else if (_wo[22] && _wo[23]) {
@@ -572,8 +573,8 @@ void InterfaceMap::setIndoorsAttackingMonsters() {
 			}
 		}
 
-		if (monster._position.x == SCREEN_POSITIONING_X[dir][29] &&
-			monster._position.y == SCREEN_POSITIONING_Y[dir][29]) {
+		if (monster._position.x == (mazePos.x + SCREEN_POSITIONING_X[dir][29]) &&
+			monster._position.y == (mazePos.y + SCREEN_POSITIONING_Y[dir][29])) {
 			if (_wo[27] || _wo[22]) {
 			} else if (_wo[15] && _wo[19]) {
 			} else if (_wo[15] && _wo[14]) {
@@ -595,8 +596,8 @@ void InterfaceMap::setIndoorsAttackingMonsters() {
 			}
 		}
 
-		if (monster._position.x == SCREEN_POSITIONING_X[dir][31] &&
-			monster._position.y == SCREEN_POSITIONING_Y[dir][31]) {
+		if (monster._position.x == (mazePos.x + SCREEN_POSITIONING_X[dir][31]) &&
+			monster._position.y == (mazePos.y + SCREEN_POSITIONING_Y[dir][31])) {
 			if (_wo[27]) {
 			} else if (_wo[22] && _wo[21]) {
 			} else if (_wo[22] && _wo[24]) {
@@ -642,7 +643,7 @@ void InterfaceMap::setMonsterSprite(DrawStruct &drawStruct, MazeMonster &monster
 		drawStruct._flags = MONSTER_EFFECT_FLAGS[monster._effect2][monster._effect3];
 }
 
-void InterfaceMap::setIndoorObjects() {
+void InterfaceMap::setIndoorsObjects() {
 	Common::Point mazePos = _vm->_party._mazePosition;
 	Direction dir = _vm->_party._mazeDirection;
 	Common::Point pt;
diff --git a/engines/xeen/interface_map.h b/engines/xeen/interface_map.h
index 8013228..a77d29e 100644
--- a/engines/xeen/interface_map.h
+++ b/engines/xeen/interface_map.h
@@ -107,7 +107,7 @@ public:
 
 	void setIndoorsAttackingMonsters();
 
-	void setIndoorObjects();
+	void setIndoorsObjects();
 
 	void setIndoorsWallPics();
 
diff --git a/engines/xeen/map.cpp b/engines/xeen/map.cpp
index a5a40c9..6bd1ed0 100644
--- a/engines/xeen/map.cpp
+++ b/engines/xeen/map.cpp
@@ -950,7 +950,7 @@ void Map::load(int mapId) {
 		if (mapId != 0) {
 			// Load in the maze's data file
 			Common::String datName = Common::String::format("maze%c%03d.dat",
-				(_vm->_party._mazeId >= 100) ? 'x' : '0', _vm->_party._mazeId);
+				(mapId >= 100) ? 'x' : '0', mapId);
 			File datFile(datName);
 			mazeData->synchronize(datFile);
 			datFile.close();
@@ -1435,11 +1435,11 @@ int Map::getCell(int idx) {
 				_currentWall._data = 0x8888;
 				return 0x8888;
 			}
-
-			_mazeDataIndex = 0;
-			while (_mazeData[_mazeDataIndex]._mazeId != mapId)
-				++_mazeDataIndex;
 		}
+
+		_mazeDataIndex = 0;
+		while (_mazeData[_mazeDataIndex]._mazeId != mapId)
+			++_mazeDataIndex;
 	}
 
 	MazeWallLayers &wallLayers = _mazeData[_mazeDataIndex]._wallData[pt.y][pt.x];


Commit: d37e3d6e747877187fe6c1179070f666f9bbb778
    https://github.com/scummvm/scummvm/commit/d37e3d6e747877187fe6c1179070f666f9bbb778
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-01-16T22:19:36-05:00

Commit Message:
XEEN: Minor cleanup and renamings

Changed paths:
    engines/xeen/interface.cpp
    engines/xeen/interface_map.cpp
    engines/xeen/interface_map.h



diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp
index f3060c2..87259d8 100644
--- a/engines/xeen/interface.cpp
+++ b/engines/xeen/interface.cpp
@@ -661,7 +661,7 @@ void Interface::draw3d(bool updateFlag) {
 			}
 		}
 
-		setIndoorsAttackingMonsters();
+		setIndoorsMonsters();
 		setIndoorsObjects();
 		setIndoorsWallPics();
 
@@ -756,7 +756,7 @@ void Interface::startup() {
 
 	animate3d();
 	if (_vm->_map->_isOutdoors) {
-		setIndoorsAttackingMonsters();
+		setIndoorsMonsters();
 		setIndoorsObjects();
 	} else {
 		setOutdoorsMonsters();
diff --git a/engines/xeen/interface_map.cpp b/engines/xeen/interface_map.cpp
index 6780a5c..45751f8 100644
--- a/engines/xeen/interface_map.cpp
+++ b/engines/xeen/interface_map.cpp
@@ -374,7 +374,7 @@ InterfaceMap::InterfaceMap(XeenEngine *vm): _vm(vm) {
 	_combatFloatCounter = 0;
 }
 
-void InterfaceMap::setIndoorsAttackingMonsters() {
+void InterfaceMap::setIndoorsMonsters() {
 	Combat &combat = *_vm->_combat;
 	Map &map = *_vm->_map;
 	Common::Point mazePos = _vm->_party._mazePosition;
@@ -426,7 +426,7 @@ void InterfaceMap::setIndoorsAttackingMonsters() {
 		}
 
 		if (monster._position.x == (mazePos.x + SCREEN_POSITIONING_X[dir][5]) &&
-			monster._position.y == (mazePos.y + SCREEN_POSITIONING_Y[dir][5])) {
+				monster._position.y == (mazePos.y + SCREEN_POSITIONING_Y[dir][5])) {
 			if (_wo[27] && _wo[25]) {
 			} else if (_wo[27] && _wo[28]) {
 			} else if (_wo[23] & _wo[25]) {
@@ -442,7 +442,7 @@ void InterfaceMap::setIndoorsAttackingMonsters() {
 		}
 
 		if (monster._position.x == (mazePos.x + SCREEN_POSITIONING_X[dir][9]) &&
-			monster._position.y == (mazePos.y + SCREEN_POSITIONING_Y[dir][9])) {
+				monster._position.y == (mazePos.y + SCREEN_POSITIONING_Y[dir][9])) {
 			if (_wo[27] && _wo[26]) {
 			} else if (_wo[27] && _wo[29]) {
 			} else if (_wo[24] & _wo[26]) {
@@ -458,7 +458,7 @@ void InterfaceMap::setIndoorsAttackingMonsters() {
 		}
 
 		if (monster._position.x == (mazePos.x + SCREEN_POSITIONING_X[dir][14]) &&
-			monster._position.y == (mazePos.y + SCREEN_POSITIONING_Y[dir][14])) {
+				monster._position.y == (mazePos.y + SCREEN_POSITIONING_Y[dir][14])) {
 			monster._isAttacking = true;
 
 			if (!_wo[22] && !_wo[27]) {
@@ -476,7 +476,7 @@ void InterfaceMap::setIndoorsAttackingMonsters() {
 		}
 
 		if (monster._position.x == (mazePos.x + SCREEN_POSITIONING_X[dir][12]) &&
-			monster._position.y == (mazePos.y + SCREEN_POSITIONING_Y[dir][12])) {
+				monster._position.y == (mazePos.y + SCREEN_POSITIONING_Y[dir][12])) {
 			if (_wo[27]) {
 			} else if (_wo[22] && _wo[23]) {
 			} else if (_wo[22] & _wo[20]) {
@@ -495,7 +495,7 @@ void InterfaceMap::setIndoorsAttackingMonsters() {
 		}
 
 		if (monster._position.x == (mazePos.x + SCREEN_POSITIONING_X[dir][16]) &&
-			monster._position.y == (mazePos.y + SCREEN_POSITIONING_Y[dir][16])) {
+				monster._position.y == (mazePos.y + SCREEN_POSITIONING_Y[dir][16])) {
 			if (_wo[27]) {
 			} else if (_wo[22] && _wo[24]) {
 			} else if (_wo[22] & _wo[21]) {
@@ -515,8 +515,8 @@ void InterfaceMap::setIndoorsAttackingMonsters() {
 		}
 
 		if (monster._position.x == (mazePos.x + SCREEN_POSITIONING_X[dir][27]) &&
-			monster._position.y == (mazePos.y + SCREEN_POSITIONING_Y[dir][27])) {
-			if (!_wo[27] && !_wo[22] && _wo[15]) {
+				monster._position.y == (mazePos.y + SCREEN_POSITIONING_Y[dir][27])) {
+			if (!_wo[27] && !_wo[22] && !_wo[15]) {
 				monster._isAttacking = true;
 
 				if (combat._attackMonsters[9] == -1) {
@@ -533,7 +533,7 @@ void InterfaceMap::setIndoorsAttackingMonsters() {
 		}
 
 		if (monster._position.x == (mazePos.x + SCREEN_POSITIONING_X[dir][25]) &&
-			monster._position.y == (mazePos.y + SCREEN_POSITIONING_Y[dir][25])) {
+				monster._position.y == (mazePos.y + SCREEN_POSITIONING_Y[dir][25])) {
 			if (_wo[27] || _wo[22]) {
 			} else if (_wo[15] && _wo[17]) {
 			} else if (_wo[15] && _wo[12]) {
@@ -556,7 +556,7 @@ void InterfaceMap::setIndoorsAttackingMonsters() {
 		}
 
 		if (monster._position.x == (mazePos.x + SCREEN_POSITIONING_X[dir][23]) &&
-			monster._position.y == (mazePos.y + SCREEN_POSITIONING_Y[dir][23])) {
+				monster._position.y == (mazePos.y + SCREEN_POSITIONING_Y[dir][23])) {
 			if (_wo[27]) {
 			} else if (_wo[22] && _wo[20]) {
 			} else if (_wo[22] && _wo[23]) {
@@ -574,7 +574,7 @@ void InterfaceMap::setIndoorsAttackingMonsters() {
 		}
 
 		if (monster._position.x == (mazePos.x + SCREEN_POSITIONING_X[dir][29]) &&
-			monster._position.y == (mazePos.y + SCREEN_POSITIONING_Y[dir][29])) {
+				monster._position.y == (mazePos.y + SCREEN_POSITIONING_Y[dir][29])) {
 			if (_wo[27] || _wo[22]) {
 			} else if (_wo[15] && _wo[19]) {
 			} else if (_wo[15] && _wo[14]) {
@@ -597,7 +597,7 @@ void InterfaceMap::setIndoorsAttackingMonsters() {
 		}
 
 		if (monster._position.x == (mazePos.x + SCREEN_POSITIONING_X[dir][31]) &&
-			monster._position.y == (mazePos.y + SCREEN_POSITIONING_Y[dir][31])) {
+				monster._position.y == (mazePos.y + SCREEN_POSITIONING_Y[dir][31])) {
 			if (_wo[27]) {
 			} else if (_wo[22] && _wo[21]) {
 			} else if (_wo[22] && _wo[24]) {
diff --git a/engines/xeen/interface_map.h b/engines/xeen/interface_map.h
index a77d29e..2376f8f 100644
--- a/engines/xeen/interface_map.h
+++ b/engines/xeen/interface_map.h
@@ -105,7 +105,7 @@ public:
 public:
 	InterfaceMap(XeenEngine *vm);
 
-	void setIndoorsAttackingMonsters();
+	void setIndoorsMonsters();
 
 	void setIndoorsObjects();
 


Commit: e0305aa9d94b44aa7d1061e0782f071181f7f7e7
    https://github.com/scummvm/scummvm/commit/e0305aa9d94b44aa7d1061e0782f071181f7f7e7
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-01-16T22:31:27-05:00

Commit Message:
XEEN: Fix loading correct monster sprites

Changed paths:
    engines/xeen/map.cpp



diff --git a/engines/xeen/map.cpp b/engines/xeen/map.cpp
index 6bd1ed0..3e41396 100644
--- a/engines/xeen/map.cpp
+++ b/engines/xeen/map.cpp
@@ -1045,10 +1045,10 @@ void Map::load(int mapId) {
 
 	// Load sprites for the monsters
 	for (uint i = 0; i < _mobData._monsterSprites.size(); ++i) {
-		filename = Common::String::format("%03d.mon", _mobData._objectSprites[i]._spriteId);
+		filename = Common::String::format("%03d.mon", _mobData._monsterSprites[i]._spriteId);
 		_mobData._monsterSprites[i]._sprites.load(filename);
 
-		filename = Common::String::format("%03d.att", _mobData._objectSprites[i]._spriteId);
+		filename = Common::String::format("%03d.att", _mobData._monsterSprites[i]._spriteId);
 		_mobData._monsterSprites[i]._attackSprites.load(filename);
 	}
 


Commit: b860745a8e1a89bfd34e1c3f263597bef59126ca
    https://github.com/scummvm/scummvm/commit/b860745a8e1a89bfd34e1c3f263597bef59126ca
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-01-17T09:11:05-05:00

Commit Message:
XEEN: Add support for horizontally flipped sprites

Changed paths:
    engines/xeen/interface_map.cpp
    engines/xeen/map.cpp
    engines/xeen/screen.cpp
    engines/xeen/sprites.cpp
    engines/xeen/sprites.h



diff --git a/engines/xeen/interface_map.cpp b/engines/xeen/interface_map.cpp
index 45751f8..ba6288e 100644
--- a/engines/xeen/interface_map.cpp
+++ b/engines/xeen/interface_map.cpp
@@ -1913,6 +1913,7 @@ void InterfaceMap::drawIndoors() {
 
 	// WORKAROUND: Original did an array lookup on _skySprites.
 	// Was this a feature for multiple skys that was abandoned?
+	assert(!map._currentSky);
 	_indoorList[0]._sprites = &map._skySprites;
 	_indoorList[0]._flags = _flipSky ? SPRFLAG_HORIZ_FLIPPED : 0;
 
diff --git a/engines/xeen/map.cpp b/engines/xeen/map.cpp
index 3e41396..86f6085 100644
--- a/engines/xeen/map.cpp
+++ b/engines/xeen/map.cpp
@@ -1062,7 +1062,7 @@ void Map::load(int mapId) {
 	if (_isOutdoors) {
 		warning("TODO");	// Sound loading
 
-		_skySprites.load(isDarkCc ? "sky.sky" : "night.sky");
+		_skySprites.load(isDarkCc ? "night.sky" : "sky.sky");
 		_groundSprites.load("water.out");
 		_tileSprites.load("outdoor.til");
 		outdoorList._skySprite._sprites = &_skySprites;
@@ -1082,7 +1082,7 @@ void Map::load(int mapId) {
 	} else {
 		warning("TODO");	// Sound loading
 
-		_skySprites.load(isDarkCc ? "sky.sky" : "night.sky");
+		_skySprites.load(isDarkCc ? "night.sky" : "sky.sky");
 		_mazeSkySprites.load(Common::String::format("%s.sky",
 			TERRAIN_TYPES[_mazeData[0]._wallKind]));
 		_groundSprites.load(Common::String::format("%s.gnd",
diff --git a/engines/xeen/screen.cpp b/engines/xeen/screen.cpp
index 7b6f972..b1b42ac 100644
--- a/engines/xeen/screen.cpp
+++ b/engines/xeen/screen.cpp
@@ -178,7 +178,7 @@ void Window::drawList(DrawStruct *items, int count) {
 
 		// TODO: There are two sprite calls in this method. Figure out why
 		items->_sprites->draw(screen, items->_frame,
-			Common::Point(items->_x, items->_y));
+			Common::Point(items->_x, items->_y), items->_flags);
 	}
 }
 
diff --git a/engines/xeen/sprites.cpp b/engines/xeen/sprites.cpp
index df1deba..85ca91b 100644
--- a/engines/xeen/sprites.cpp
+++ b/engines/xeen/sprites.cpp
@@ -85,7 +85,7 @@ void SpriteResource::clear() {
 	_filesize = 0;
 }
 
-void SpriteResource::drawOffset(XSurface &dest, uint16 offset, const Common::Point &destPos) const {
+void SpriteResource::drawOffset(XSurface &dest, uint16 offset, const Common::Point &destPos, int flags) const {
 	// Get cell header
 	Common::MemoryReadStream f(_data, _filesize);
 	f.seek(offset);
@@ -94,6 +94,9 @@ void SpriteResource::drawOffset(XSurface &dest, uint16 offset, const Common::Poi
 	int yOffset = f.readUint16LE();
 	int height = f.readUint16LE();
 
+	bool flipped = (flags & SPRFLAG_HORIZ_FLIPPED) != 0;
+	int xInc = flipped ? -1 : 1;
+
 	if (dest.w < (xOffset + width) || dest.h < (yOffset + height))
 		dest.create(xOffset + width, yOffset + height);
 
@@ -116,9 +119,11 @@ void SpriteResource::drawOffset(XSurface &dest, uint16 offset, const Common::Poi
 		} else {
 			// Skip the transparent pixels at the beginning of the scan line
 			int xPos = f.readByte() + xOffset; ++byteCount;
-			byte *destP = (byte *)dest.getBasePtr(destPos.x + xPos, destPos.y + yPos);
 			const byte *lineStartP = (const byte *)dest.getBasePtr(0, destPos.y + yPos);
 			const byte *lineEndP = (const byte *)dest.getBasePtr(dest.w, destPos.y + yPos);
+			byte *destP = !flipped ?
+				(byte *)dest.getBasePtr(destPos.x + xPos, destPos.y + yPos) :
+				(byte *)dest.getBasePtr(destPos.x + width - xPos, destPos.y + yPos);
 
 			while (byteCount < lineLength) {
 				// The next byte is an opcode that determines what 
@@ -134,21 +139,20 @@ void SpriteResource::drawOffset(XSurface &dest, uint16 offset, const Common::Poi
 				case 1:   // The following len + 33 bytes are stored as indexes into the color table.
 					for (int i = 0; i < opcode + 1; ++i, ++xPos) {
 						byte b = f.readByte();
-						if (destP < lineStartP || destP >= lineEndP)
-							++destP;
-						else
-							*destP++ = b; 
 						++byteCount;
+
+						if (destP >= lineStartP && destP < lineEndP)
+							*destP = b;
+						destP += xInc;
 					}
 					break;
 
 				case 2:   // The following byte is an index into the color table, draw it len + 3 times.
 					opr1 = f.readByte(); ++byteCount;
 					for (int i = 0; i < len + 3; ++i, ++xPos) {
-						if (destP < lineStartP || destP >= lineEndP)
-							++destP;
-						else
-							*destP++ = opr1;
+						if (destP >= lineStartP && destP < lineEndP)
+							*destP = opr1;
+						destP += xInc;
 					}
 					break;
 
@@ -159,10 +163,9 @@ void SpriteResource::drawOffset(XSurface &dest, uint16 offset, const Common::Poi
 
 					for (int i = 0; i < len + 4; ++i, ++xPos) {
 						byte b = f.readByte();
-						if (destP < lineStartP || destP >= lineEndP)
-							++destP;
-						else
-							*destP++ = b;
+						if (destP >= lineStartP && destP < lineEndP)
+							*destP = b;
+						destP += xInc;
 					}
 
 					f.seek(pos, SEEK_SET);
@@ -173,17 +176,19 @@ void SpriteResource::drawOffset(XSurface &dest, uint16 offset, const Common::Poi
 					opr2 = f.readByte(); ++byteCount;
 					for (int i = 0; i < len + 2; ++i, xPos += 2) {
 						if (destP < lineStartP || destP >= (lineEndP - 1)) {
-							destP += 2;
+							destP += 2 * xInc;
 						} else {
-							*destP++ = opr1;
-							*destP++ = opr2;
+							*destP = opr1;
+							destP += xInc;
+							*destP = opr2;
+							destP += xInc;
 						}
 					}
 					break;
 
 				case 5:   // Skip len + 1 pixels filling them with the transparent color.
 					xPos += len + 1;
-					destP += len + 1;
+					destP += (len + 1) * xInc;
 					break;
 
 				case 6:   // Pattern command.
@@ -194,10 +199,9 @@ void SpriteResource::drawOffset(XSurface &dest, uint16 offset, const Common::Poi
 
 					opr1 = f.readByte(); ++byteCount;
 					for (int i = 0; i < len + 3; ++i, ++xPos) {
-						if (destP < lineStartP || destP >= lineEndP)
-							++destP;
-						else
-							*destP++ = opr1;
+						if (destP >= lineStartP && destP < lineEndP)
+							*destP = opr1;
+						destP += xInc;
 						opr1 += patternSteps[cmd + (i % 2)];
 					}
 					break;
@@ -219,11 +223,9 @@ void SpriteResource::drawOffset(XSurface &dest, uint16 offset, const Common::Poi
 
 void SpriteResource::draw(XSurface &dest, int frame, const Common::Point &destPos, int flags) const {
 	// TODO: Support the different flags
-	assert(!flags);
-
-	drawOffset(dest, _index[frame]._offset1, destPos);
+	drawOffset(dest, _index[frame]._offset1, destPos, flags);
 	if (_index[frame]._offset2)
-		drawOffset(dest, _index[frame]._offset2, destPos);
+		drawOffset(dest, _index[frame]._offset2, destPos, flags);
 }
 
 void SpriteResource::draw(XSurface &dest, int frame) const {
diff --git a/engines/xeen/sprites.h b/engines/xeen/sprites.h
index 59c1ed1..c240059 100644
--- a/engines/xeen/sprites.h
+++ b/engines/xeen/sprites.h
@@ -45,7 +45,7 @@ private:
 	int32 _filesize;
 	byte *_data;
 
-	void drawOffset(XSurface &dest, uint16 offset, const Common::Point &destPos) const;
+	void drawOffset(XSurface &dest, uint16 offset, const Common::Point &destPos, int flags) const;
 public:
 	SpriteResource();
 	SpriteResource(const Common::String &filename);


Commit: 258ab0209679a84e0e8ef96718fe442dd47e2d7d
    https://github.com/scummvm/scummvm/commit/258ab0209679a84e0e8ef96718fe442dd47e2d7d
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-01-18T08:57:23-05:00

Commit Message:
XEEN: Load sprites from the correct archive

Changed paths:
    engines/xeen/files.cpp
    engines/xeen/files.h
    engines/xeen/interface_map.cpp
    engines/xeen/map.cpp
    engines/xeen/map.h
    engines/xeen/sprites.cpp
    engines/xeen/sprites.h



diff --git a/engines/xeen/files.cpp b/engines/xeen/files.cpp
index 8ab1f35..f15a08b 100644
--- a/engines/xeen/files.cpp
+++ b/engines/xeen/files.cpp
@@ -198,11 +198,22 @@ Common::SeekableReadStream *CCArchive::createReadStreamForMember(const Common::S
  */
 FileManager::FileManager(XeenEngine *vm) {
 	Common::File f;
+	int sideNum = 0;
 
 	_isDarkCc = vm->getGameID() != GType_Clouds;
-	if (_isDarkCc)
-		SearchMan.add("dark", new CCArchive("dark.cc", "dark", true));
-	SearchMan.add("xeen", new CCArchive("xeen.cc", "xeen", true));
+	_sideArchives[0] = _sideArchives[1] = nullptr;
+
+	if (vm->getGameID() != GType_DarkSide) {
+		_sideArchives[0] = new CCArchive("xeen.cc", "xeen", true);
+		SearchMan.add("xeen", _sideArchives[0]);
+		sideNum = 1;
+	}
+
+	if (vm->getGameID() == GType_DarkSide || vm->getGameID() == GType_WorldOfXeen) {
+		_sideArchives[sideNum] = new CCArchive("dark.cc", "dark", true);
+		SearchMan.add("dark", _sideArchives[sideNum]);
+	}
+
 	SearchMan.add("intro", new CCArchive("intro.cc", "intro", true));
 }
 
diff --git a/engines/xeen/files.h b/engines/xeen/files.h
index a8343c1..f350e34 100644
--- a/engines/xeen/files.h
+++ b/engines/xeen/files.h
@@ -33,6 +33,7 @@
 namespace Xeen {
 
 class XeenEngine;
+class CCArchive;
 
 #define SYNC_AS(SUFFIX,STREAM,TYPE,SIZE) \
 	template<typename T> \
@@ -53,6 +54,7 @@ class XeenEngine;
 class FileManager {
 public:
 	bool _isDarkCc;
+	CCArchive *_sideArchives[2];
 public:
 	FileManager(XeenEngine *vm);
 
diff --git a/engines/xeen/interface_map.cpp b/engines/xeen/interface_map.cpp
index ba6288e..1310e19 100644
--- a/engines/xeen/interface_map.cpp
+++ b/engines/xeen/interface_map.cpp
@@ -855,7 +855,7 @@ void InterfaceMap::setIndoorsObjects() {
 			} else if (_wo[22] && _wo[24]) {
 			} else if (_wo[21] && _wo[19]) {
 			} else if (_wo[24] && _wo[19]) {
-			} else if (!_wo[14] && !_wo[10] && !_indoorList._objects11._frame == -1) {
+			} else if (!_wo[14] && !_wo[10] && _indoorList._objects11._frame == -1) {
 				_indoorList._objects11._x = INDOOR_OBJECT_X[listOffset][11];
 				_indoorList._objects11._y = INDOOR_OBJECT_Y[listOffset][11];
 				_indoorList._objects11._frame = mazeObject._frame;
@@ -1948,6 +1948,8 @@ void InterfaceMap::drawIndoors() {
 	_charsShooting = _isShooting;
 
 	// TODO
+	SpriteResource *spr = _vm->_map->_mobData._objects[41]._sprites;
+	spr->draw(*_vm->_screen, 0);
 }
 
 } // End of namespace Xeen
diff --git a/engines/xeen/map.cpp b/engines/xeen/map.cpp
index 86f6085..10143ed 100644
--- a/engines/xeen/map.cpp
+++ b/engines/xeen/map.cpp
@@ -850,8 +850,9 @@ void AnimationInfo::load(const Common::String &name) {
 
 Map::Map(XeenEngine *vm) : _vm(vm), _mobData(vm) {
 	_townPortalSide = 0;
-	_sideObj = 0;
-	_sideMon = 0;
+	_sideObjects = 0;
+	_sideMonsters = 0;
+	_sidePictures = 0;
 	_isOutdoors = false;
 	_stepped = false;
 	_mazeDataIndex = 0;
@@ -871,6 +872,7 @@ void Map::load(int mapId) {
 	Screen &screen = *_vm->_screen;
 	IndoorDrawList &indoorList = _vm->_interface->_indoorList;
 	OutdoorDrawList &outdoorList = _vm->_interface->_outdoorList;
+	int sideNumber = 0;
 
 	if (_vm->_falling) {
 		Window &w = screen._windows[9];
@@ -884,7 +886,9 @@ void Map::load(int mapId) {
 	_vm->_party._mazeId = mapId;
 	_vm->_events->clearEvents();
 
-
+	_sideObjects = 1;
+	_sideMonsters = 1;
+	_sidePictures = 1;
 	if (mapId >= 113 && mapId <= 127) {
 		_townPortalSide = 0;
 	} else {
@@ -896,6 +900,9 @@ void Map::load(int mapId) {
 			_animationInfo.load("clouds.dat");
 			_monsterData.load("xeen.mon");
 			_wallPicSprites.load("xeenpic.dat");
+			_sidePictures = 0;
+			_sideMonsters = 0;
+			_sideObjects = 0;
 		} else {
 			switch (mapId) {
 			case 113:
@@ -906,7 +913,7 @@ void Map::load(int mapId) {
 				_animationInfo.load("clouds.dat");
 				_monsterData.load("dark.mon");
 				_wallPicSprites.load("darkpic.dat");
-				_sideObj = 0;
+				_sideObjects = 0;
 				break;
 			case 117:
 			case 118:
@@ -916,8 +923,8 @@ void Map::load(int mapId) {
 				_animationInfo.load("clouds.dat");
 				_monsterData.load("xeen.mon");
 				_wallPicSprites.load("darkpic.dat");
-				_sideObj = 0;
-				_sideMon = 0;
+				_sideObjects = 0;
+				_sideMonsters = 0;
 				break;
 			case 125:
 			case 126:
@@ -925,6 +932,8 @@ void Map::load(int mapId) {
 				_animationInfo.load("clouds.dat");
 				_monsterData.load("dark.mon");
 				_wallPicSprites.load("xeenpic.dat");
+				_sideObjects = 0;
+				_sidePictures = 0;
 				break;
 			default:
 				_animationInfo.load("dark.dat");
@@ -1034,28 +1043,34 @@ void Map::load(int mapId) {
 			filename = "085.obj";
 			_mobData._objectSprites[0]._spriteId = 85;
 		} else {
-			filename = Common::String::format("%03d.%cbj", 
+			filename = Common::String::format("xeen|%03d.%cbj", 
 				_mobData._objectSprites[i]._spriteId,
 				_mobData._objectSprites[i]._spriteId >= 100 ? '0' : 'o');
 		}
 
 		// Read in the object sprites
-		_mobData._objectSprites[i]._sprites.load(filename);
+		_mobData._objectSprites[i]._sprites.load(filename,
+			*_vm->_files->_sideArchives[_sideObjects]);
 	}
 
 	// Load sprites for the monsters
 	for (uint i = 0; i < _mobData._monsterSprites.size(); ++i) {
+		CCArchive *archive = _vm->_files->_sideArchives[
+			_mobData._monsterSprites[i]._spriteId == 91 && _vm->getGameID() == GType_WorldOfXeen ?
+			0 : _sideMonsters];
+
 		filename = Common::String::format("%03d.mon", _mobData._monsterSprites[i]._spriteId);
-		_mobData._monsterSprites[i]._sprites.load(filename);
+		_mobData._monsterSprites[i]._sprites.load(filename, *archive);
 
 		filename = Common::String::format("%03d.att", _mobData._monsterSprites[i]._spriteId);
-		_mobData._monsterSprites[i]._attackSprites.load(filename);
+		_mobData._monsterSprites[i]._attackSprites.load(filename, *archive);
 	}
 
 	// Load wall picture sprite resources
 	for (uint i = 0; i < _mobData._wallItemSprites.size(); ++i) {
 		filename = Common::String::format("%03d.pic", _mobData._wallItems[i]._spriteId);
-		_mobData._wallItemSprites[i]._sprites.load(filename);
+		_mobData._wallItemSprites[i]._sprites.load(filename,
+			*_vm->_files->_sideArchives[_sidePictures]);
 	}
 
 	// Handle loading miscellaneous sprites for the map
diff --git a/engines/xeen/map.h b/engines/xeen/map.h
index 8e6fee2..5c3e5a3 100644
--- a/engines/xeen/map.h
+++ b/engines/xeen/map.h
@@ -356,8 +356,9 @@ private:
 	Common::String _mazeName;
 	SpriteResource _wallPicSprites;
 	int _townPortalSide;
-	int _sideObj;
-	int _sideMon;
+	int _sidePictures;
+	int _sideObjects;
+	int _sideMonsters;
 	bool _stepped;
 	int _mazeDataIndex;
 	bool _currentSteppedOn;
diff --git a/engines/xeen/sprites.cpp b/engines/xeen/sprites.cpp
index 85ca91b..8a14ec0 100644
--- a/engines/xeen/sprites.cpp
+++ b/engines/xeen/sprites.cpp
@@ -59,9 +59,16 @@ SpriteResource &SpriteResource::operator=(const SpriteResource &src) {
 }
 
 void SpriteResource::load(const Common::String &filename) {
-	// Open the resource
 	File f(filename);
+	load(f);
+}
+
+void SpriteResource::load(const Common::String &filename, Common::Archive &archive) {
+	File f(filename, archive);
+	load(f);
+}
 
+void SpriteResource::load(Common::SeekableReadStream &f) {
 	// Read in a copy of the file
 	_filesize = f.size();
 	delete[] _data;
diff --git a/engines/xeen/sprites.h b/engines/xeen/sprites.h
index c240059..973875c 100644
--- a/engines/xeen/sprites.h
+++ b/engines/xeen/sprites.h
@@ -45,6 +45,8 @@ private:
 	int32 _filesize;
 	byte *_data;
 
+	void load(Common::SeekableReadStream &f);
+
 	void drawOffset(XSurface &dest, uint16 offset, const Common::Point &destPos, int flags) const;
 public:
 	SpriteResource();
@@ -56,6 +58,8 @@ public:
 
 	void load(const Common::String &filename);
 
+	void load(const Common::String &filename, Common::Archive &archive);
+
 	void clear();
 
 	void draw(XSurface &dest, int frame, const Common::Point &destPos, int flags = 0) const;


Commit: ceeda17ab1fae75e28c4d15e3e829a02615ffc81
    https://github.com/scummvm/scummvm/commit/ceeda17ab1fae75e28c4d15e3e829a02615ffc81
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-01-18T15:59:07-05:00

Commit Message:
XEEN: Remove old test sprite from being displayed

Changed paths:
    engines/xeen/interface_map.cpp



diff --git a/engines/xeen/interface_map.cpp b/engines/xeen/interface_map.cpp
index 1310e19..d34373e 100644
--- a/engines/xeen/interface_map.cpp
+++ b/engines/xeen/interface_map.cpp
@@ -1946,10 +1946,6 @@ void InterfaceMap::drawIndoors() {
 	}
 	
 	_charsShooting = _isShooting;
-
-	// TODO
-	SpriteResource *spr = _vm->_map->_mobData._objects[41]._sprites;
-	spr->draw(*_vm->_screen, 0);
 }
 
 } // End of namespace Xeen


Commit: 9925453774c803921f5ed3503bbd448b1888f011
    https://github.com/scummvm/scummvm/commit/9925453774c803921f5ed3503bbd448b1888f011
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-01-18T17:17:55-05:00

Commit Message:
XEEN: Fix loading of MonsterData array

Changed paths:
    engines/xeen/map.cpp
    engines/xeen/map.h



diff --git a/engines/xeen/map.cpp b/engines/xeen/map.cpp
index 10143ed..36232ae 100644
--- a/engines/xeen/map.cpp
+++ b/engines/xeen/map.cpp
@@ -94,13 +94,18 @@ MonsterStruct::MonsterStruct(Common::String name, int experience, int hp, int ac
 
 
 void MonsterStruct::synchronize(Common::SeekableReadStream &s) {
-	_experience = s.readByte();
-	_hp = s.readByte();
+	char name[16];
+	s.read(name, 16);
+	name[15] = '\0';
+	_name = Common::String(name);
+
+	_experience = s.readUint32LE();
+	_hp = s.readUint16LE();
 	_accuracy = s.readByte();
 	_speed = s.readByte();
 	_numberOfAttacks = s.readByte();
-	_hatesClass = CLASS_KNIGHT;
-	_strikes = s.readByte();
+	_hatesClass = (CharacterClass)s.readByte();
+	_strikes = s.readUint16LE();
 	_dmgPerStrike = s.readByte();
 	_attackType = (DamageType)s.readByte();
 	_specialAttack = (SpecialAttack)s.readByte();
@@ -115,18 +120,18 @@ void MonsterStruct::synchronize(Common::SeekableReadStream &s) {
 	_magicResistence = s.readByte();
 	_phsyicalResistence = s.readByte();
 	_field29 = s.readByte();
-	_gold = s.readByte();
+	_gold = s.readUint16LE();
 	_gems = s.readByte();
 	_itemDrop = s.readByte();
-	_flying = s.readByte();
+	_flying = s.readByte() != 0;
 	_imageNumber = s.readByte();
 	_loopAnimation = s.readByte();
 	_animationEffect = s.readByte();
 	_field32 = s.readByte();
 	
-	char attackVoc[9];
+	char attackVoc[10];
 	s.read(attackVoc, 9);
-	attackVoc[8] = '\0';
+	attackVoc[9] = '\0';
 	_attackVoc = Common::String(attackVoc);
 }
 
diff --git a/engines/xeen/map.h b/engines/xeen/map.h
index 5c3e5a3..ec9604c 100644
--- a/engines/xeen/map.h
+++ b/engines/xeen/map.h
@@ -89,7 +89,7 @@ public:
 	int _gold;
 	int _gems;
 	int _itemDrop;
-	int _flying;
+	bool _flying;
 	int _imageNumber;
 	int _loopAnimation;
 	int _animationEffect;


Commit: f18a8c364b2b2f608081bb79cad54de3abacd111
    https://github.com/scummvm/scummvm/commit/f18a8c364b2b2f608081bb79cad54de3abacd111
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-01-18T17:35:17-05:00

Commit Message:
XEEN: Convert default values for monsters flying flags from int to bool

Changed paths:
    engines/xeen/map.cpp
    engines/xeen/map.h



diff --git a/engines/xeen/map.cpp b/engines/xeen/map.cpp
index 36232ae..0623772 100644
--- a/engines/xeen/map.cpp
+++ b/engines/xeen/map.cpp
@@ -77,7 +77,7 @@ MonsterStruct::MonsterStruct(Common::String name, int experience, int hp, int ac
 		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,
+		bool 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), 
@@ -138,339 +138,339 @@ void MonsterStruct::synchronize(Common::SeekableReadStream &s) {
 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"));
+				   0, false, 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,
+				   100, 100, 100, 0, 0, 100, 0, 0, 0, 0, false, 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"));
+				   100, 0, 0, 80, 0, 0, 0, 0, false, 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"));
+				   100, 0, 0, 50, 0, 0, 0, 0, true, 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,
+				   0, 50, 50, 0, 0, 0, 0, 0, 0, 0, false, 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,
+				   50, 0, 80, 80, 50, 0, 50, 0, 0, 0, 0, false, 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,
+				   0, 0, 0, 0, 0, 0, 100, 0, 3, false, 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"));
+				   false, 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,
+				   10, 100, 10, 10, 10, 10, 0, 0, 0, 10, 0, false, 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,
+				   20, 20, 20, 30, 0, 0, 0, 25, 4, false, 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,
+				   0, 100, 0, 0, 30, 0, 0, 0, 0, false, 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,
+				   100, 100, 50, 25, 50, 0, 0, 10, 0, false, 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,
+				   100, 100, 80, 50, 50, 0, 0, 20, 0, false, 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,
+				   50, 0, 100, 50, 25, 50, 0, 0, 10, 0, false, 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,
+				   80, 60, 100, 100, 30, 50, 0, 0, 20, 0, false, 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"));
+				   0, false, 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,
+				   100, 100, 0, 10, 90, 0, 0, 0, 0, false, 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,
+				   90, 100, 0, 0, 90, 0, 0, 0, 0, false, 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"));
+				   0, 0, 0, 0, 0, true, 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"));
+				   100, 50, 0, 50, 0, 0, 0, 0, false, 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,
+				   50, 50, 100, 50, 0, 50, 0, 0, 0, 0, true, 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"));
+				   20, 0, 0, 0, 0, 0, false, 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,
+				   0, 0, 0, 0, 0, 0, 1000, 0, 5, false, 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"));
+				   0, 0, 0, 0, 0, 0, false, 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, 100, 100, 100, 50, 0, 0, 100, 0, true, 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"));
+				   0, 0, 0, 0, 0, 0, false, 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"));
+				   0, 0, 0, 0, 0, 0, false, 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"));
+				   0, 0, 80, 0, 0, 0, 0, 0, false, 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"));
+				   100, 100, 0, 60, 0, 0, 0, 0, false, 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,
+				   50, 50, 50, 50, 0, 20, 0, 0, 0, 0, false, 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,
+				   50, 50, 50, 50, 50, 0, 0, 0, 50, 0, 5, false, 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,
+				   50, 50, 50, 50, 50, 10, 0, 0, 100, 0, 6, false, 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"));
+				   100, 50, 0, 50, 0, 0, 0, 0, false, 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"));
+				   100, 0, 0, 0, 0, 0, 0, 0, false, 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"));
+				   0, 80, 70, 0, 0, 0, 0, true, 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,
+				   50, 50, 50, 30, 0, 0, 0, 50, 0, true, 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,
+				   50, 50, 50, 0, 0, 0, 75, 0, true, 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"));
+				   0, 50, 60, 0, 0, 0, 0, false, 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"));
+				   0, 60, 70, 0, 0, 0, 0, false, 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"));
+				   false, 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"));
+				   0, 0, 0, 0, 0, 0, 50, 0, 2, false, 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"));
+				   100, 0, 0, 0, 0, 0, 0, 0, true, 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"));
+				   0, 0, 0, 100, 0, 0, false, 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"));
+				   0, 10, 0, 0, 75, 10, 2, false, 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"));
+				   0, 0, 0, 0, 0, 0, 0, 0, false, 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"));
+				   0, 50, 50, 0, 0, 0, 0, false, 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,
+				   0, 0, 100, 0, 50, 0, 0, 0, 0, 0, false, 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"));
+				   0, 0, 0, 0, 0, 0, 0, 0, false, 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"));
+				   100, 0, 0, 0, 0, 0, 0, 0, false, 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"));
+				   0, false, 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,
+				   10, 100, 10, 10, 10, 20, 0, 0, 0, 20, 0, false, 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"));
+				   10, 80, 0, 0, 0, 50, 5, false, 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"));
+				   100, 0, 0, 0, 0, 0, 0, 0, false, 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"));
+				   0, 0, 0, 0, 0, 0, 0, 0, true, 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"));
+				   0, 0, 0, 0, 0, 0, 70, 0, 0, false, 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,
+				   0, 0, 0, 0, 0, 0, 200, 0, 0, false, 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"));
+				   50, 0, 0, 0, 0, 0, 0, 0, false, 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,
+				   50, 50, 50, 50, 50, 50, 0, 0, 0, 0, false, 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,
+				   50, 50, 50, 50, 50, 50, 70, 0, 0, 0, 0, false, 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"));
+				   0, 0, 0, 0, 0, 0, 0, 0, 0, true, 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,
+				   0, 100, 0, 100, 0, 20, 0, 0, 0, 10, 0, false, 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,
+				   100, 50, 0, 100, 0, 0, 0, 0, true, 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,
+				   0, 20, 0, 20, 0, 0, 0, 10, 0, false, 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,
+				   100, 0, 50, 100, 50, 0, 0, 0, 20, 6, false, 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,
+				   50, 50, 50, 50, 50, 0, 0, 0, 50, 0, false, 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"));
+				   30, 30, 30, 0, 0, 0, 20, 0, false, 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"));
+				   0, 0, 0, 0, 0, 0, 0, 0, false, 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"));
+				   0, 60, 0, 0, 0, 0, false, 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,
+				   50, 50, 100, 50, 0, 0, 0, 100, 6, false, 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,
+				   100, 100, 100, 100, 100, 100, 90, 0, 0, 232, 0, false, 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"));
+				   0, 0, 0, 2000, 0, 5, false, 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"));
+				   0, 7, false, 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"));
+				   90, 80, 0, 0, 100, 7, true, 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,
+				   80, 80, 80, 0, 0, 0, 100, 6, true, 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"));
+				   0, 0, 0, 0, 0, 0, 100, 0, 3, false, 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"));
+				   0, 20, 0, 0, 1000, 50, 5, false, 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"));
+				   0, 0, 0, 0, 0, 0, 0, 10, 4, false, 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,
+				   50, 50, 100, 80, 0, 0, 0, 100, 6, false, 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,
+				   0, 0, 0, 0, 0, 0, 0, 250, 20, 4, false, 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"));
+				   false, 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"));
+				   false, 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"));
+				   50, 0, 0, 0, 0, 0, 0, 0, false, 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"));
+				   50, 0, 0, 0, 0, 0, 0, 0, false, 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"));
+				   50, 0, 0, 0, 0, 1000, 0, 4, false, 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"));
+				   0, 0, 0, 1000, 0, 5, false, 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"));
+				   0, false, 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"));
+				   40, 30, 0, 0, 0, 0, 0, false, 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,
+				   100, 50, 50, 50, 50, 0, 0, 0, 0, true, 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,
+				   0, 0, 0, 0, 0, 0, 5000, 0, 6, false, 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,
+				   0, 0, 0, 0, 0, 0, 200, 0, 4, false, 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"));
+				   0, 0, 0, 0, 0, 0, true, 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,
+				   0, 60, 80, 80, 80, 50, 80, 0, 0, 0, 0, false, 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"));
+				   false, 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,
+				   50, 100, 50, 0, 0, 0, 100, 6, false, 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"));
+				   0, 0, 0, 0, 0, 0, 6, false, 19, 0, 11, 100, "fire"));
 }
 
 void MonsterData::load(const Common::String &name) {
diff --git a/engines/xeen/map.h b/engines/xeen/map.h
index ec9604c..3ade915 100644
--- a/engines/xeen/map.h
+++ b/engines/xeen/map.h
@@ -104,7 +104,7 @@ public:
 		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,
+		bool flying, int imageNumber, int loopAnimation, int animationEffect,
 		int field32, Common::String attackVoc);
 
 	void synchronize(Common::SeekableReadStream &s);


Commit: 07a10855be2f60ae253623c26c8bb0ac38e58af4
    https://github.com/scummvm/scummvm/commit/07a10855be2f60ae253623c26c8bb0ac38e58af4
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-01-18T19:12:10-05:00

Commit Message:
XEEN: In progress work on sprite scaling

Changed paths:
    engines/xeen/screen.cpp
    engines/xeen/sprites.cpp
    engines/xeen/sprites.h
    engines/xeen/xsurface.cpp
    engines/xeen/xsurface.h



diff --git a/engines/xeen/screen.cpp b/engines/xeen/screen.cpp
index b1b42ac..de591d3 100644
--- a/engines/xeen/screen.cpp
+++ b/engines/xeen/screen.cpp
@@ -178,7 +178,7 @@ void Window::drawList(DrawStruct *items, int count) {
 
 		// TODO: There are two sprite calls in this method. Figure out why
 		items->_sprites->draw(screen, items->_frame,
-			Common::Point(items->_x, items->_y), items->_flags);
+			Common::Point(items->_x, items->_y), items->_flags, items->_scale);
 	}
 }
 
diff --git a/engines/xeen/sprites.cpp b/engines/xeen/sprites.cpp
index 8a14ec0..8ddf4ed 100644
--- a/engines/xeen/sprites.cpp
+++ b/engines/xeen/sprites.cpp
@@ -228,11 +228,35 @@ void SpriteResource::drawOffset(XSurface &dest, uint16 offset, const Common::Poi
 		dest.addDirtyRect(r);
 }
 
-void SpriteResource::draw(XSurface &dest, int frame, const Common::Point &destPos, int flags) const {
-	// TODO: Support the different flags
-	drawOffset(dest, _index[frame]._offset1, destPos, flags);
-	if (_index[frame]._offset2)
-		drawOffset(dest, _index[frame]._offset2, destPos, flags);
+void SpriteResource::draw(XSurface &dest, int frame, const Common::Point &destPos, 
+		int flags, int scale) const {
+	if (scale == 0) {
+		drawOffset(dest, _index[frame]._offset1, destPos, flags);
+		if (_index[frame]._offset2)
+			drawOffset(dest, _index[frame]._offset2, destPos, flags);
+	} else {
+		// Get the bounds for the surface and create a temporary one
+		Common::MemoryReadStream f(_data, _filesize);
+		f.seek(_index[frame]._offset1);
+		int xOffset = f.readUint16LE();
+		int width = f.readUint16LE();
+		int yOffset = f.readUint16LE();
+		int height = f.readUint16LE();
+		XSurface tempSurface(xOffset + width, yOffset + height);
+
+		// Draw sprite into temporary surface
+		tempSurface.fillRect(Common::Rect(0, 0, width, height), 0);
+		drawOffset(tempSurface, _index[frame]._offset1, Common::Point(), flags);
+		if (_index[frame]._offset2)
+			drawOffset(tempSurface, _index[frame]._offset2, Common::Point(), flags);
+
+		// TODO: I don't currently know the algorithm the original used for scaling.
+		// This is a best fit estimate that every increment of the scale field
+		// reduces the size of a sprite by approximately 6.6%
+		int newScale = MAX(100.0 - 6.6 * scale, 0.0);
+		if (newScale > 0)
+			tempSurface.transBlitTo(dest, Common::Point(), newScale, 0);
+	}
 }
 
 void SpriteResource::draw(XSurface &dest, int frame) const {
diff --git a/engines/xeen/sprites.h b/engines/xeen/sprites.h
index 973875c..d1a801e 100644
--- a/engines/xeen/sprites.h
+++ b/engines/xeen/sprites.h
@@ -62,7 +62,8 @@ public:
 
 	void clear();
 
-	void draw(XSurface &dest, int frame, const Common::Point &destPos, int flags = 0) const;
+	void draw(XSurface &dest, int frame, const Common::Point &destPos, 
+		int flags = 0, int scale = 0) const;
 
 	void draw(XSurface &dest, int frame) const;
 
diff --git a/engines/xeen/xsurface.cpp b/engines/xeen/xsurface.cpp
index 698e478..b01ade1 100644
--- a/engines/xeen/xsurface.cpp
+++ b/engines/xeen/xsurface.cpp
@@ -24,6 +24,7 @@
 #include "common/util.h"
 #include "xeen/xsurface.h"
 #include "xeen/resources.h"
+#include "xeen/screen.h"
 
 namespace Xeen {
 
@@ -80,6 +81,126 @@ void XSurface::transBlitTo(XSurface &dest, const Common::Point &destPos) const {
 	dest.addDirtyRect(Common::Rect(destPos.x, destPos.y, destPos.x + w, destPos.y));
 }
 
+void XSurface::transBlitTo(XSurface &dest, const Common::Point &destPos, 
+		int scale, int transparentColor) {
+	int destX = destPos.x, destY = destPos.y;
+	int frameWidth = this->w;
+	int frameHeight = this->h;
+	int direction = 1;
+
+	int highestDim = MAX(frameWidth, frameHeight);
+	bool lineDist[SCREEN_WIDTH];
+	int distXCount = 0, distYCount = 0;
+
+	if (scale != 0) {
+		int distCtr = 0;
+		int distIndex = 0;
+		do {
+			distCtr += scale;
+			if (distCtr < 100) {
+				lineDist[distIndex] = false;
+			}
+			else {
+				lineDist[distIndex] = true;
+				distCtr -= 100;
+
+				if (distIndex < frameWidth)
+					++distXCount;
+
+				if (distIndex < frameHeight)
+					++distYCount;
+			}
+		} while (++distIndex < highestDim);
+
+		destX -= distXCount / 2;
+		destY -= distYCount - 1;
+	}
+
+	// Start of draw logic for scaled sprites
+	const byte *srcPixelsP = (const byte *)getPixels();
+
+	int destRight = dest.w - 1;
+	int destBottom = dest.h - 1;
+
+	// Check x bounding area
+	int spriteLeft = 0;
+	int spriteWidth = distXCount;
+	int widthAmount = destX + distXCount - 1;
+
+	if (destX < 0) {
+		spriteWidth += destX;
+		spriteLeft -= destX;
+	}
+	widthAmount -= destRight;
+	if (widthAmount > 0)
+		spriteWidth -= widthAmount;
+
+	if (spriteWidth <= 0)
+		return;
+
+	// Check y bounding area
+	int spriteTop = 0;
+	int spriteHeight = distYCount;
+	int heightAmount = destY + distYCount - 1;
+
+	if (destY < 0) {
+		spriteHeight += destY;
+		spriteTop -= destY;
+	}
+	heightAmount -= destBottom;
+	if (heightAmount > 0)
+		spriteHeight -= heightAmount;
+	int spriteBottom = spriteTop + spriteHeight;
+
+	if (spriteHeight <= 0)
+		return;
+
+	byte *destPixelsP = (byte *)dest.getBasePtr(destX + spriteLeft, destY + spriteTop);
+	int destWidth = 0, destHeight = 0;
+
+	spriteLeft = spriteLeft * direction;
+
+	// Loop through the lines of the sprite
+	for (int yp = 0, sprY = -1; yp < frameHeight; ++yp, srcPixelsP += this->pitch) {
+		if (!lineDist[yp])
+			// Not a display line, so skip it
+			continue;
+		// Check whether the sprite line is in the display range
+		++sprY;
+		if ((sprY >= spriteBottom) || (sprY < spriteTop))
+			continue;
+
+		// Found a line to display. Loop through the pixels
+		const byte *srcP = srcPixelsP;
+		byte *destP = destPixelsP;
+		++destHeight;
+
+		for (int xp = 0, sprX = 0; xp < frameWidth; ++xp, ++srcP) {
+			if (xp < spriteLeft)
+				// Not yet reached start of display area
+				continue;
+			if (!lineDist[sprX++])
+				// Not a display pixel
+				continue;
+
+			if (*srcP != transparentColor)
+				*destP = *srcP;
+
+			destP += direction;
+		}
+
+		// Keep track of widest line drawn
+		destWidth = MAX(destP - destPixelsP, destWidth);
+
+		// Move to the next destination line
+		destPixelsP += dest.pitch;
+	}
+
+	// Add a dirty rect for the affected area
+	dest.addDirtyRect(Common::Rect(destX + spriteLeft, destY + spriteTop,
+		destX + spriteLeft + destWidth, destY + spriteTop + destHeight));
+}
+
 void XSurface::blitTo(XSurface &dest, const Common::Point &destPos) const {
 	if (dest.getPixels() == nullptr)
 		dest.create(w, h);
diff --git a/engines/xeen/xsurface.h b/engines/xeen/xsurface.h
index 263ea53..61f4f96 100644
--- a/engines/xeen/xsurface.h
+++ b/engines/xeen/xsurface.h
@@ -48,6 +48,9 @@ public:
 
 	void transBlitTo(XSurface &dest, const Common::Point &destPos) const;
 
+	void transBlitTo(XSurface &dest, const Common::Point &destPos,
+		int scale, int transparentColor);
+
 	void blitTo(XSurface &dest, const Common::Point &destPos) const;
 
 	void blitTo(XSurface &dest) const;


Commit: ecdf6412a6d74853ff20cbb7ea5abbdeaa789b63
    https://github.com/scummvm/scummvm/commit/ecdf6412a6d74853ff20cbb7ea5abbdeaa789b63
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-01-18T19:18:00-05:00

Commit Message:
XEEN: Fix drawing the game window border

Changed paths:
    engines/xeen/interface.cpp



diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp
index 87259d8..8d8b4ab 100644
--- a/engines/xeen/interface.cpp
+++ b/engines/xeen/interface.cpp
@@ -313,10 +313,11 @@ void Interface::assembleBorder() {
 	Window &gameWindow = screen._windows[28];
 
 	// Draw the outer frame
-	_globalSprites.draw(gameWindow, 0);
+	_globalSprites.draw(screen._windows[0], 0, Common::Point(8, 8));
 
 	// Draw the animating bat character used to show when levitate is active
-	_borderSprites.draw(screen, _vm->_party._levitateActive ? _batUIFrame + 16 : 16);
+	_borderSprites.draw(screen._windows[0], _vm->_party._levitateActive ? _batUIFrame + 16 : 16,
+		Common::Point(0, 82));
 	_batUIFrame = (_batUIFrame + 1) % 12;
 
 	// Draw UI element to indicate whether can spot hidden doors


Commit: e4c473630655bd9b68d925b338559706ea927497
    https://github.com/scummvm/scummvm/commit/e4c473630655bd9b68d925b338559706ea927497
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-01-18T20:11:31-05:00

Commit Message:
XEEN: Renaming of flags and surface display

Changed paths:
    engines/xeen/interface.cpp
    engines/xeen/interface_map.cpp
    engines/xeen/interface_map.h
    engines/xeen/map.cpp
    engines/xeen/map.h
    engines/xeen/resources.cpp
    engines/xeen/resources.h



diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp
index 8d8b4ab..a2c42a7 100644
--- a/engines/xeen/interface.cpp
+++ b/engines/xeen/interface.cpp
@@ -310,7 +310,6 @@ void Interface::setupBackground() {
 
 void Interface::assembleBorder() {
 	Screen &screen = *_vm->_screen;
-	Window &gameWindow = screen._windows[28];
 
 	// Draw the outer frame
 	_globalSprites.draw(screen._windows[0], 0, Common::Point(8, 8));
@@ -548,7 +547,7 @@ void Interface::draw3d(bool updateFlag) {
 
 	_flipUIFrame = (_flipUIFrame + 1) % 4;
 	if (_flipUIFrame == 0)
-		_flipWtr = !_flipWtr;
+		_flipWater = !_flipWater;
 	if (_tillMove && (_vm->_mode == MODE_1 || _vm->_mode == MODE_2) &&
 			!_flag1 && _vm->_moveMonsters) {
 		if (--_tillMove == 0)
diff --git a/engines/xeen/interface_map.cpp b/engines/xeen/interface_map.cpp
index d34373e..ddc311b 100644
--- a/engines/xeen/interface_map.cpp
+++ b/engines/xeen/interface_map.cpp
@@ -181,6 +181,7 @@ IndoorDrawList::IndoorDrawList() :
 	_fwl_3F2R(_data[ 91]), _fwl_3F1R(_data[ 90]), _fwl_3F(  _data[ 89]), 
 	_fwl_3F1L(_data[ 88]), _fwl_3F2L(_data[ 87]), _fwl_1F(  _data[147]),
 	_fwl_1F1R(_data[145]), _fwl_1F1L(_data[143]),
+	_groundTiles(&_data[3]),
 	_objects0(_data[149]), _objects1(_data[125]), _objects2(_data[126]),
 	_objects3(_data[127]), _objects4(_data[97]), _objects5(_data[98]),
 	_objects6(_data[99]), _objects7(_data[55]), _objects8(_data[56]),
@@ -364,10 +365,10 @@ InterfaceMap::InterfaceMap(XeenEngine *vm): _vm(vm) {
 	Common::fill(&_wp[0], &_wp[20], 0);
 	Common::fill(&_wo[0], &_wo[308], 0);
 	_overallFrame = 0;
-	_flipWtr = false;
-	_flipWall = false;
-	_flipSky = false;
+	_flipWater = false;
 	_flipGround = false;
+	_flipSky = false;
+	_flipDefaultGround = false;
 	_isShooting = false;
 	_charsShooting = false;
 	_objNumber = 0;
@@ -1106,20 +1107,22 @@ void InterfaceMap::drawIndoors() {
 	Map &map = *_vm->_map;
 	int surfaceId;
 
+	// Draw any surface tiles on top of the default ground
 	for (int cellIndex = 0; cellIndex < 25; ++cellIndex) {
 		map.getCell(DRAW_NUMBERS[cellIndex]);
 
-		DrawStruct &drawStruct = _indoorList[3 + cellIndex];
+		DrawStruct &drawStruct = _indoorList._groundTiles[cellIndex];
 		if (!map._surfaceSprites[map._currentSurfaceId].empty())
 			drawStruct._sprites = &map._surfaceSprites[map._currentSurfaceId];
 
 		surfaceId = map.mazeData()._surfaceTypes[map._currentSurfaceId];
-		if (surfaceId == 0 || surfaceId == 5 || surfaceId == 12) {
-			drawStruct._flags = _flipWtr ? 1 : 0;
-			drawStruct._frame = DRAW_FRAMES[cellIndex][_flipWtr ? 1 : 0];
+		if (surfaceId == SURFTYPE_WATER || surfaceId == SURFTYPE_LAVA || 
+				surfaceId == SURFTYPE_SEWER) {
+			drawStruct._flags = _flipWater ? 1 : 0;
+			drawStruct._frame = DRAW_FRAMES[cellIndex][_flipWater ? 1 : 0];
 		} else {
-			drawStruct._frame = DRAW_FRAMES[cellIndex][_flipWall ? 1 : 0];
-			drawStruct._flags = _flipWall ? SPRFLAG_HORIZ_FLIPPED : 0;
+			drawStruct._frame = DRAW_FRAMES[cellIndex][_flipGround ? 1 : 0];
+			drawStruct._flags = _flipGround ? SPRFLAG_HORIZ_FLIPPED : 0;
 		}
 	}
 
@@ -1932,7 +1935,7 @@ void InterfaceMap::drawIndoors() {
 	}
 
 	_indoorList._sky._flags = _flipSky ? SPRFLAG_HORIZ_FLIPPED : 0;
-	_indoorList._ground._flags = _flipGround ? SPRFLAG_HORIZ_FLIPPED : 0;
+	_indoorList._ground._flags = _flipDefaultGround ? SPRFLAG_HORIZ_FLIPPED : 0;
 	_indoorList._horizon._frame = 7;
 
 	// Finally draw the darn indoor scene
diff --git a/engines/xeen/interface_map.h b/engines/xeen/interface_map.h
index 2376f8f..fd807a0 100644
--- a/engines/xeen/interface_map.h
+++ b/engines/xeen/interface_map.h
@@ -53,6 +53,7 @@ public:
 	DrawStruct &_sky;
 	DrawStruct &_ground;
 	DrawStruct &_horizon;
+	DrawStruct * const _groundTiles;
 	DrawStruct &_swl_0F1R, &_swl_0F1L, &_swl_1F1R, &_swl_1F1L,
 		&_swl_2F2R, &_swl_2F1R, &_swl_2F1L, &_swl_2F2L,
 		&_swl_3F1R, &_swl_3F2R, &_swl_3F3R, &_swl_3F4R,
@@ -92,10 +93,10 @@ protected:
 	int8 _wp[20];
 	byte _wo[308];
 	int _overallFrame;
-	bool _flipWtr;
-	bool _flipWall;
-	bool _flipSky;
+	bool _flipWater;
 	bool _flipGround;
+	bool _flipSky;
+	bool _flipDefaultGround;
 	bool _isShooting;
 	bool _charsShooting;
 	int _objNumber;
diff --git a/engines/xeen/map.cpp b/engines/xeen/map.cpp
index 0623772..d39b8f5 100644
--- a/engines/xeen/map.cpp
+++ b/engines/xeen/map.cpp
@@ -877,7 +877,6 @@ void Map::load(int mapId) {
 	Screen &screen = *_vm->_screen;
 	IndoorDrawList &indoorList = _vm->_interface->_indoorList;
 	OutdoorDrawList &outdoorList = _vm->_interface->_outdoorList;
-	int sideNumber = 0;
 
 	if (_vm->_falling) {
 		Window &w = screen._windows[9];
@@ -1097,7 +1096,7 @@ void Map::load(int mapId) {
 
 			_surfaceSprites[i].clear();
 			if (i != 0 && _mazeData[0]._wallTypes[i] != 0)
-				_surfaceSprites[i].load(OUTDOOR_SURFACES[_mazeData[0]._surfaceTypes[i]]);
+				_surfaceSprites[i].load(SURFACE_NAMES[_mazeData[0]._surfaceTypes[i]]);
 		}
 	} else {
 		warning("TODO");	// Sound loading
@@ -1114,7 +1113,7 @@ void Map::load(int mapId) {
 			_surfaceSprites[i].clear();
 
 			if (_mazeData[0]._surfaceTypes[i] != 0 || i == 4)
-				_surfaceSprites[i].load(OUTDOOR_SURFACES[i]);
+				_surfaceSprites[i].load(SURFACE_NAMES[i]);
 		}
 
 		for (int i = 0; i < TOTAL_SURFACES; ++i)
diff --git a/engines/xeen/map.h b/engines/xeen/map.h
index 3ade915..c97de72 100644
--- a/engines/xeen/map.h
+++ b/engines/xeen/map.h
@@ -159,9 +159,10 @@ enum MazeFlags {
 enum MazeFlags2 { FLAG_IS_OUTDOORS = 0x8000, FLAG_IS_DARK = 0x4000 };
 
 enum SurfaceType {
-	SURFTYPE_DEFAULT = 0, SURFTYPE_DIRT = 1, SURFTYPE_GRASS = 2,
+	SURFTYPE_DEFAULT = 0, 
+	SURFTYPE_WATER = 0, SURFTYPE_DIRT = 1, SURFTYPE_GRASS = 2,
 	SURFTYPE_SNOW = 3, SURFTYPE_SWAMP = 4, SURFTYPE_LAVA = 5,
-	SURFTYPE_DESERT = 6, SURFTYPE_ROAD = 7, SURFTYPE_WATER = 8,
+	SURFTYPE_DESERT = 6, SURFTYPE_ROAD = 7, SURFTYPE_DWATER = 8,
 	SURFTYPE_TFLR = 9, SURFTYPE_SKY = 10, SURFTYPE_CROAD = 11,
 	SURFTYPE_SEWER = 12, SURFTYPE_CLOUD = 13, SURFTYPE_SCORCH = 14,
 	SURFTYPE_SPACE = 15
diff --git a/engines/xeen/resources.cpp b/engines/xeen/resources.cpp
index 21a967d..51f26fe 100644
--- a/engines/xeen/resources.cpp
+++ b/engines/xeen/resources.cpp
@@ -76,7 +76,7 @@ const char *const SURFACE_TYPE_NAMES[15] = {
 	"dedltree", "dedltree"
 };
 
-const char *const OUTDOOR_SURFACES[16] = {
+const char *const SURFACE_NAMES[16] = {
 	"water.srf", "dirt.srf", "grass.srf", "snow.srf", "swamp.srf",
 	"lava.srf", "desert.srf", "road.srf", "dwater.srf", "tflr.srf",
 	"sky.srf", "croad.srf", "sewer.srf", "cloud.srf", "scortch.srf",
diff --git a/engines/xeen/resources.h b/engines/xeen/resources.h
index 2160d55..0ef9211 100644
--- a/engines/xeen/resources.h
+++ b/engines/xeen/resources.h
@@ -36,7 +36,7 @@ extern const char *const TERRAIN_TYPES[6];
 
 extern const char *const SURFACE_TYPE_NAMES[15];
 
-extern const char *const OUTDOOR_SURFACES[16];
+extern const char *const SURFACE_NAMES[16];
 
 extern const byte SYMBOLS[20][64];
 


Commit: 130bd58e2c8ffdac6de86364d45d772ffe6a8d1b
    https://github.com/scummvm/scummvm/commit/130bd58e2c8ffdac6de86364d45d772ffe6a8d1b
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-01-18T20:54:58-05:00

Commit Message:
XEEN: Load correct surface sprites for the maze

Changed paths:
    engines/xeen/interface_map.cpp
    engines/xeen/map.cpp



diff --git a/engines/xeen/interface_map.cpp b/engines/xeen/interface_map.cpp
index ddc311b..93c3d9a 100644
--- a/engines/xeen/interface_map.cpp
+++ b/engines/xeen/interface_map.cpp
@@ -1118,8 +1118,8 @@ void InterfaceMap::drawIndoors() {
 		surfaceId = map.mazeData()._surfaceTypes[map._currentSurfaceId];
 		if (surfaceId == SURFTYPE_WATER || surfaceId == SURFTYPE_LAVA || 
 				surfaceId == SURFTYPE_SEWER) {
-			drawStruct._flags = _flipWater ? 1 : 0;
 			drawStruct._frame = DRAW_FRAMES[cellIndex][_flipWater ? 1 : 0];
+			drawStruct._flags = _flipWater ? SPRFLAG_HORIZ_FLIPPED : 0;
 		} else {
 			drawStruct._frame = DRAW_FRAMES[cellIndex][_flipGround ? 1 : 0];
 			drawStruct._flags = _flipGround ? SPRFLAG_HORIZ_FLIPPED : 0;
diff --git a/engines/xeen/map.cpp b/engines/xeen/map.cpp
index d39b8f5..9c69106 100644
--- a/engines/xeen/map.cpp
+++ b/engines/xeen/map.cpp
@@ -1089,13 +1089,14 @@ void Map::load(int mapId) {
 		
 		for (int i = 0; i < TOTAL_SURFACES; ++i) {
 			_wallSprites._surfaces[i].clear();
+
 			if (_mazeData[0]._wallTypes[i] != 0) {
 				_wallSprites._surfaces[i].load(Common::String::format("%s.wal",
-					SURFACE_TYPE_NAMES[i]));
+					SURFACE_TYPE_NAMES[_mazeData[0]._wallTypes[i]]));
 			}
 
 			_surfaceSprites[i].clear();
-			if (i != 0 && _mazeData[0]._wallTypes[i] != 0)
+			if (i != 0 && _mazeData[0]._surfaceTypes[i] != 0)
 				_surfaceSprites[i].load(SURFACE_NAMES[_mazeData[0]._surfaceTypes[i]]);
 		}
 	} else {
@@ -1113,7 +1114,7 @@ void Map::load(int mapId) {
 			_surfaceSprites[i].clear();
 
 			if (_mazeData[0]._surfaceTypes[i] != 0 || i == 4)
-				_surfaceSprites[i].load(SURFACE_NAMES[i]);
+				_surfaceSprites[i].load(SURFACE_NAMES[_mazeData[0]._surfaceTypes[i]]);
 		}
 
 		for (int i = 0; i < TOTAL_SURFACES; ++i)


Commit: b12e26836aacfd414abb5967f7475435a4fd55a5
    https://github.com/scummvm/scummvm/commit/b12e26836aacfd414abb5967f7475435a4fd55a5
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-01-18T20:56:35-05:00

Commit Message:
XEEN: Disable initial fade out for now

Changed paths:
    engines/xeen/xeen.cpp



diff --git a/engines/xeen/xeen.cpp b/engines/xeen/xeen.cpp
index b3758b5..6b73de6 100644
--- a/engines/xeen/xeen.cpp
+++ b/engines/xeen/xeen.cpp
@@ -291,7 +291,7 @@ void XeenEngine::play() {
 
 	_interface->startup();
 	if (_mode == MODE_0) {
-		_screen->fadeOut(4);
+//		_screen->fadeOut(4);
 	}
 
 	_screen->_windows[0].update();


Commit: f46b9d77dd1427aacb095f834f10f3fb45502637
    https://github.com/scummvm/scummvm/commit/f46b9d77dd1427aacb095f834f10f3fb45502637
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-01-19T10:28:48-05:00

Commit Message:
XEEN: Compilation fixes for gcc

Changed paths:
    engines/xeen/darkside/darkside_game.cpp
    engines/xeen/dialogs.cpp
    engines/xeen/dialogs.h
    engines/xeen/dialogs_error.cpp
    engines/xeen/dialogs_options.h
    engines/xeen/font.cpp
    engines/xeen/font.h
    engines/xeen/interface.cpp
    engines/xeen/module.mk
    engines/xeen/sound.cpp
    engines/xeen/sound.h



diff --git a/engines/xeen/darkside/darkside_game.cpp b/engines/xeen/darkside/darkside_game.cpp
index 60cb693..fe8c161 100644
--- a/engines/xeen/darkside/darkside_game.cpp
+++ b/engines/xeen/darkside/darkside_game.cpp
@@ -66,9 +66,10 @@ void DarkSideEngine::showTitle1() {
 		SpriteResource("nwc1.int"), SpriteResource("nwc2.int"),
 		SpriteResource("nwc3.int"), SpriteResource("nwc4.int")
 	};
-	File voc[3] = {
-		File("dragon1.voc"), File("dragon2.voc"), File("dragon3.voc")
-	};
+	Common::File voc[3];
+	voc[0].open("dragon1.voc");
+	voc[1].open("dragon2.voc");
+	voc[2].open("dragon3.voc");
 
 	// Load backgrounds
 	_screen->loadBackground("nwc1.raw");
@@ -168,9 +169,9 @@ void DarkSideEngine::showStartSequence() {
 	SpriteResource sprites[3] = {
 		SpriteResource("title.int"), SpriteResource("pyratop.int"), SpriteResource("pyramid.int")
 	};
-	File voc[2] = {
-		File("pharoh1a.voc"), File("pharoh1b.voc")
-	};
+	Common::File voc[2];
+	voc[0].open("pharoh1a.voc");
+	voc[1].open("pharoh1b.voc");
 
 	_screen->vertMerge(SCREEN_HEIGHT);
 	_screen->loadPage(0);
diff --git a/engines/xeen/dialogs.cpp b/engines/xeen/dialogs.cpp
index c677fc8..824e824 100644
--- a/engines/xeen/dialogs.cpp
+++ b/engines/xeen/dialogs.cpp
@@ -102,14 +102,14 @@ void ButtonContainer::doScroll(XeenEngine *vm, bool drawFlag, bool doFade) {
 	// Load hand vga files
 	SpriteResource *hand[16];
 	for (int i = 0; i < 16; ++i) {
-		Common::String name = Common::String::format("hand%02u.vga", i);
+		Common::String name = Common::String::format("hand%02d.vga", i);
 		hand[i] = new SpriteResource(name);
 	}
 
 	// Load marb vga files
 	SpriteResource *marb[5];
 	for (int i = 1; i < 5; ++i) {
-		Common::String name = Common::String::format("marb%02u.vga");
+		Common::String name = Common::String::format("marb%02d.vga", i);
 		marb[i] = new SpriteResource(name);
 	}
 
diff --git a/engines/xeen/dialogs.h b/engines/xeen/dialogs.h
index 229c40a..d8a9123 100644
--- a/engines/xeen/dialogs.h
+++ b/engines/xeen/dialogs.h
@@ -76,6 +76,8 @@ protected:
 	virtual void showContents(SpriteResource &title1, bool mode);
 public:
 	SettingsBaseDialog(XeenEngine *vm) : ButtonContainer(), _vm(vm) {}
+
+	virtual ~SettingsBaseDialog() {}
 };
 
 class CreditsScreen: public ButtonContainer {
diff --git a/engines/xeen/dialogs_error.cpp b/engines/xeen/dialogs_error.cpp
index c0c0723..e851221 100644
--- a/engines/xeen/dialogs_error.cpp
+++ b/engines/xeen/dialogs_error.cpp
@@ -38,7 +38,7 @@ void ErrorScroll::execute(const Common::String &msg, ErrorWaitType waitType) {
 	EventsManager &events = *_vm->_events;
 	Window &w = screen._windows[6];
 
-	Common::String s = Common::String::format("\x03c\v010\t000%s", msg);
+	Common::String s = Common::String::format("\x03c\v010\t000%s", msg.c_str());
 	w.open();
 	w.writeString(s);
 	w.update();
diff --git a/engines/xeen/dialogs_options.h b/engines/xeen/dialogs_options.h
index 7a933fd..bb4aea9 100644
--- a/engines/xeen/dialogs_options.h
+++ b/engines/xeen/dialogs_options.h
@@ -46,6 +46,8 @@ protected:
 
 	virtual void openWindow() {}
 public:
+	virtual ~OptionsMenu() {}
+
 	static void show(XeenEngine *vm);
 };
 
@@ -54,6 +56,8 @@ protected:
 	virtual void startup(Common::String &title1, Common::String &title2);
 public:
 	CloudsOptionsMenu(XeenEngine *vm) : OptionsMenu(vm) {}
+
+	virtual ~CloudsOptionsMenu() {}
 };
 
 class DarkSideOptionsMenu : public OptionsMenu {
@@ -61,6 +65,8 @@ protected:
 	virtual void startup(Common::String &title1, Common::String &title2);
 public:
 	DarkSideOptionsMenu(XeenEngine *vm) : OptionsMenu(vm) {}
+
+	virtual ~DarkSideOptionsMenu() {}
 };
 
 class WorldOptionsMenu : public DarkSideOptionsMenu {
@@ -80,6 +86,8 @@ protected:
 	virtual void showContents(SpriteResource &title1, bool mode);
 public:
 	WorldOptionsMenu(XeenEngine *vm) : DarkSideOptionsMenu(vm), _bgFrame(0) {}
+	
+	virtual ~WorldOptionsMenu() {}
 };
 
 } // End of namespace Xeen
diff --git a/engines/xeen/font.cpp b/engines/xeen/font.cpp
index b5608d4..aee05f9 100644
--- a/engines/xeen/font.cpp
+++ b/engines/xeen/font.cpp
@@ -34,7 +34,7 @@ FontSurface::FontSurface() : XSurface(), _fontData(nullptr), _bgColor(DEFAULT_BG
 	_textColors[3] = 0x20;
 }
 
-FontSurface::FontSurface(int w, int h) : XSurface(), _fontData(nullptr), _msgWraps(false),
+FontSurface::FontSurface(int wv, int hv) : XSurface(wv, hv), _fontData(nullptr), _msgWraps(false),
 		_bgColor(DEFAULT_BG_COLOR), _fontReduced(false), _fontJustify(JUSTIFY_NONE) {
 	create(w, h);
 	_textColors[0] = 0;
@@ -173,12 +173,12 @@ Common::String FontSurface::writeString(const Common::String &s, const Common::R
 					_fontJustify = JUSTIFY_NONE;
 			} else if (c == 4) {
 				// Draw an empty box of a given width
-				int w = fontAtoi();
+				int wv = fontAtoi();
 				Common::Point pt = _writePos;
 				if (_fontJustify == JUSTIFY_RIGHT)
-					pt.x -= w;
+					pt.x -= wv;
 
-				Common::Rect r(pt.x, pt.y, pt.x + w, pt.y + (_fontReduced ? 9 : 10));
+				Common::Rect r(pt.x, pt.y, pt.x + wv, pt.y + (_fontReduced ? 9 : 10));
 				fillRect(r, _bgColor);
 			} else if (c == 5) {
 				continue;
@@ -187,8 +187,8 @@ Common::String FontSurface::writeString(const Common::String &s, const Common::R
 				writeChar(' ');
 			} else if (c == 7) {
 				// Set text background color
-				int c = fontAtoi();
-				_bgColor = (c < 0 || c > 255) ? DEFAULT_BG_COLOR : c;
+				int bgColor = fontAtoi();
+				_bgColor = (bgColor < 0 || bgColor > 255) ? DEFAULT_BG_COLOR : bgColor;
 			} else if (c == 8) {
 				// Draw a character outline
 				c = getNextChar();
@@ -218,8 +218,8 @@ Common::String FontSurface::writeString(const Common::String &s, const Common::R
 				}
 			} else if (c == 9) {
 				// Skip x position
-				int xp = fontAtoi();
-				_writePos.x = MIN(bounds.left + xp, (int)bounds.right);
+				int xAmount = fontAtoi();
+				_writePos.x = MIN(bounds.left + xAmount, (int)bounds.right);
 			} else if (c == 10) {
 				// Newline
 				if (newLine(bounds))
@@ -304,10 +304,10 @@ bool FontSurface::newLine(const Common::Rect &bounds) {
 	_msgWraps = false;
 	_writePos.x = bounds.left;
 	
-	int h = _fontReduced ? 9 : 10;
-	_writePos.y += h;
+	int hv = _fontReduced ? 9 : 10;
+	_writePos.y += hv;
 
-	return ((_writePos.y + h - 1) > bounds.bottom);
+	return ((_writePos.y + hv - 1) > bounds.bottom);
 }
 
 /**
diff --git a/engines/xeen/font.h b/engines/xeen/font.h
index 0f53d5e..6b362d7 100644
--- a/engines/xeen/font.h
+++ b/engines/xeen/font.h
@@ -58,7 +58,7 @@ public:
 	Justify _fontJustify;
 public:
 	FontSurface();
-	FontSurface(int w, int h);
+	FontSurface(int wv, int hv);
 	virtual ~FontSurface() {}
 
 	void writeSymbol(int symbolId);
diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp
index a2c42a7..50f3ede 100644
--- a/engines/xeen/interface.cpp
+++ b/engines/xeen/interface.cpp
@@ -28,7 +28,7 @@
 namespace Xeen {
 
 Interface::Interface(XeenEngine *vm) : ButtonContainer(), InterfaceMap(vm), _vm(vm) {
-	Common::fill(&_partyFaces[0], &_partyFaces[MAX_ACTIVE_PARTY], nullptr);
+	Common::fill(&_partyFaces[0], &_partyFaces[MAX_ACTIVE_PARTY], (SpriteResource *)nullptr);
 	_batUIFrame = 0;
 	_spotDoorsUIFrame = 0;
 	_dangerSenseUIFrame = 0;
@@ -425,7 +425,7 @@ void Interface::setupFaces(int charIndex, Common::Array<int> xeenSideChars, bool
 	int charId;
 
 	for (posIndex = 0; posIndex < 4; ++posIndex) {
-		int charId = xeenSideChars[charIndex];
+		charId = xeenSideChars[charIndex];
 		bool isInParty = _vm->_party.isInParty(charId);
 
 		if (charId == 0xff) {
@@ -902,7 +902,7 @@ void Interface::setMazeBits() {
 		break;
 	case 4:
 	case 7:
-		_wo[27];
+		++_wo[27];
 		break;
 	case 5:
 		++_wo[227];
diff --git a/engines/xeen/module.mk b/engines/xeen/module.mk
index d6b8097..6362ffe 100644
--- a/engines/xeen/module.mk
+++ b/engines/xeen/module.mk
@@ -18,7 +18,6 @@ MODULE_OBJS := \
 	items.o \
 	map.o \
 	party.o \
-	resdata.o \
 	resources.o \
 	saves.o \
 	screen.o \
diff --git a/engines/xeen/sound.cpp b/engines/xeen/sound.cpp
index 9495b25..7c7524a 100644
--- a/engines/xeen/sound.cpp
+++ b/engines/xeen/sound.cpp
@@ -27,7 +27,7 @@ namespace Xeen {
 SoundManager::SoundManager(XeenEngine *vm): _vm(vm) {
 }
 
-void SoundManager::proc2(File &f) {
+void SoundManager::proc2(Common::SeekableReadStream &f) {
 
 }
 
diff --git a/engines/xeen/sound.h b/engines/xeen/sound.h
index da6548b..553b1c6 100644
--- a/engines/xeen/sound.h
+++ b/engines/xeen/sound.h
@@ -35,11 +35,11 @@ private:
 public:
 	SoundManager(XeenEngine *vm);
 
-	void proc2(File &f);
+	void proc2(Common::SeekableReadStream &f);
 
 	void startMusic(int v1);
 
-	void playSong(const File &f) {}
+	void playSong(Common::SeekableReadStream &f) {}
 
 	void playSample(const Common::SeekableReadStream *stream, int v2) {}
 };


Commit: 83442b9586e3992ab8ee0f0d06e534781f9b448b
    https://github.com/scummvm/scummvm/commit/83442b9586e3992ab8ee0f0d06e534781f9b448b
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-01-19T10:51:05-05:00

Commit Message:
XEEN: Fix Valgrind warnings

Changed paths:
    engines/xeen/files.cpp
    engines/xeen/map.cpp
    engines/xeen/sprites.cpp



diff --git a/engines/xeen/files.cpp b/engines/xeen/files.cpp
index f15a08b..f8e7a3f 100644
--- a/engines/xeen/files.cpp
+++ b/engines/xeen/files.cpp
@@ -175,7 +175,7 @@ Common::SeekableReadStream *CCArchive::createReadStreamForMember(const Common::S
 
 		// Read in the data for the specific resource
 		f.seek(ccEntry._offset);
-		byte *data = new byte[ccEntry._size];
+		byte *data = (byte *)malloc(ccEntry._size);
 		f.read(data, ccEntry._size);
 
 		if (_encoded) {
diff --git a/engines/xeen/map.cpp b/engines/xeen/map.cpp
index 9c69106..99fe5ad 100644
--- a/engines/xeen/map.cpp
+++ b/engines/xeen/map.cpp
@@ -954,28 +954,28 @@ void Map::load(int mapId) {
 	// Iterate through loading the given maze as well as the two successive
 	// mazes in each of the four cardinal directions
 	bool isDarkCc = _vm->getGameID() == GType_DarkSide;
-	MazeData *mazeData = &_mazeData[0];
+	MazeData *mazeDataP = &_mazeData[0];
 	bool textLoaded = false;
 
-	for (int idx = 0; idx < 9; ++idx, ++mazeData) {
-		mazeData->_mazeId = mapId;
+	for (int idx = 0; idx < 9; ++idx, ++mazeDataP) {
+		mazeDataP->_mazeId = mapId;
 
 		if (mapId != 0) {
 			// Load in the maze's data file
 			Common::String datName = Common::String::format("maze%c%03d.dat",
 				(mapId >= 100) ? 'x' : '0', mapId);
 			File datFile(datName);
-			mazeData->synchronize(datFile);
+			mazeDataP->synchronize(datFile);
 			datFile.close();
 
 			if (isDarkCc && mapId == 50)
-				mazeData->setAllTilesStepped();
+				mazeDataP->setAllTilesStepped();
 			if (!isDarkCc && _vm->_party._gameFlags[25] &&
 					(mapId == 42 || mapId == 43 || mapId == 4)) {
-				mazeData->clearCellSurfaces();
+				mazeDataP->clearCellSurfaces();
 			}
 
-			_isOutdoors = (mazeData->_mazeFlags2 & FLAG_IS_OUTDOORS) != 0;
+			_isOutdoors = (mazeDataP->_mazeFlags2 & FLAG_IS_OUTDOORS) != 0;
 
 			// Handle loading text data
 			if (!textLoaded) {
diff --git a/engines/xeen/sprites.cpp b/engines/xeen/sprites.cpp
index 8ddf4ed..448ec0e 100644
--- a/engines/xeen/sprites.cpp
+++ b/engines/xeen/sprites.cpp
@@ -120,7 +120,7 @@ void SpriteResource::drawOffset(XSurface &dest, uint16 offset, const Common::Poi
 		if (lineLength == 0) {
 			// Skip the specified number of scan lines
 			yPos += f.readByte();
-		} else if ((destPos.y + yPos) < 0) {
+		} else if ((destPos.y + yPos) < 0 || (destPos.y + yPos) >= dest.h) {
 			// Skip over the bytes of the line
 			f.skip(lineLength);
 		} else {


Commit: 687423b3612d61a18a9854010af56f7a98e5563d
    https://github.com/scummvm/scummvm/commit/687423b3612d61a18a9854010af56f7a98e5563d
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-01-19T11:32:57-05:00

Commit Message:
XEEN: Beginnings of main game loop and waiting

Changed paths:
    engines/xeen/interface.cpp
    engines/xeen/interface.h
    engines/xeen/interface_map.cpp
    engines/xeen/interface_map.h
    engines/xeen/map.cpp
    engines/xeen/map.h
    engines/xeen/party.cpp
    engines/xeen/party.h
    engines/xeen/resources.cpp
    engines/xeen/resources.h
    engines/xeen/scripts.cpp
    engines/xeen/scripts.h
    engines/xeen/sprites.cpp
    engines/xeen/xeen.cpp
    engines/xeen/xeen.h



diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp
index 50f3ede..e15c057 100644
--- a/engines/xeen/interface.cpp
+++ b/engines/xeen/interface.cpp
@@ -39,7 +39,6 @@ Interface::Interface(XeenEngine *vm) : ButtonContainer(), InterfaceMap(vm), _vm(
 	_holyBonusUIFrame = 0;
 	_heroismUIFrame = 0;
 	_flipUIFrame = 0;
-	_newDay = false;
 	_buttonsLoaded = false;
 	_hiliteChar = -1;
 	_intrIndex1 = 0;
@@ -49,6 +48,7 @@ Interface::Interface(XeenEngine *vm) : ButtonContainer(), InterfaceMap(vm), _vm(
 	_tillMove = 0;
 	_thinWall = false;
 	_overallFrame = 0;
+	_upDoorText = false;
 
 	Common::fill(&_combatCharIds[0], &_combatCharIds[8], 0);
 	initDrawStructs();
@@ -91,12 +91,12 @@ void Interface::setup() {
 	_charPowSprites.load("charpow.icn");
 
 	// 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.resize(_vm->_party->_partyCount);
+	for (int i = 0; i < _vm->_party->_partyCount; ++i) {
+		_vm->_party->_activeParty[i] = _vm->_roster[_vm->_party->_partyMembers[i]];
 	}
 
-	_newDay = _vm->_party._minutes >= 300;
+	_vm->_party->_newDay = _vm->_party->_minutes >= 300;
 }
 
 void Interface::manageCharacters(bool soundPlayed) {
@@ -105,7 +105,7 @@ void Interface::manageCharacters(bool soundPlayed) {
 	bool flag = false;
 
 start:
-	if (_vm->_party._mazeId != 0) {
+	if (_vm->_party->_mazeId != 0) {
 		_vm->_mode = MODE_0;
 		_buttonsLoaded = true;
 	} else {
@@ -117,8 +117,8 @@ start:
 			// Xeen only uses 24 of possible 30 character slots
 			loadCharIcons();
 
-			for (int i = 0; i < _vm->_party._partyCount; ++i)
-				_partyFaces[i] = &_charFaces[_vm->_party._partyMembers[i]];
+			for (int i = 0; i < _vm->_party->_partyCount; ++i)
+				_partyFaces[i] = &_charFaces[_vm->_party->_partyMembers[i]];
 		}
 
 		_vm->_mode = MODE_1;
@@ -193,7 +193,7 @@ start:
 			case Common::KEYCODE_SPACE:
 			case Common::KEYCODE_e:
 			case Common::KEYCODE_x:
-				if (_vm->_party._partyCount == 0) {
+				if (_vm->_party->_partyCount == 0) {
 					ErrorScroll::show(_vm, NO_ONE_TO_ADVENTURE_WITH);
 				} else {
 					if (_vm->_mode != MODE_0) {
@@ -208,10 +208,10 @@ start:
 					}
 
 					w.close();
-					_vm->_party._realPartyCount = _vm->_party._partyCount;
-					_vm->_party._mazeId = _vm->_party._priorMazeId;
+					_vm->_party->_realPartyCount = _vm->_party->_partyCount;
+					_vm->_party->_mazeId = _vm->_party->_priorMazeId;
 
-					_vm->_party.copyPartyToRoster(_vm->_roster);
+					_vm->_party->copyPartyToRoster(_vm->_roster);
 					_vm->_saves->writeCharFile();
 					breakFlag = true;
 					break;
@@ -242,7 +242,7 @@ start:
 			case Common::KEYCODE_d:
 				break;
 			case Common::KEYCODE_r:
-				if (_vm->_party._partyCount > 0) {
+				if (_vm->_party->_partyCount > 0) {
 					// TODO
 				}
 				break;
@@ -299,8 +299,8 @@ void Interface::loadCharIcons() {
 }
 
 void Interface::loadPartyIcons() {
-	for (int i = 0; i < _vm->_party._partyCount; ++i)
-		_partyFaces[i] = &_charFaces[_vm->_party._partyMembers[i]];
+	for (int i = 0; i < _vm->_party->_partyCount; ++i)
+		_partyFaces[i] = &_charFaces[_vm->_party->_partyMembers[i]];
 }
 
 void Interface::setupBackground() {
@@ -315,19 +315,19 @@ void Interface::assembleBorder() {
 	_globalSprites.draw(screen._windows[0], 0, Common::Point(8, 8));
 
 	// Draw the animating bat character used to show when levitate is active
-	_borderSprites.draw(screen._windows[0], _vm->_party._levitateActive ? _batUIFrame + 16 : 16,
+	_borderSprites.draw(screen._windows[0], _vm->_party->_levitateActive ? _batUIFrame + 16 : 16,
 		Common::Point(0, 82));
 	_batUIFrame = (_batUIFrame + 1) % 12;
 
 	// Draw UI element to indicate whether can spot hidden doors
 	_borderSprites.draw(screen,
-		(_thinWall && _vm->_party.checkSkill(SPOT_DOORS)) ? _spotDoorsUIFrame + 28 : 28,
+		(_thinWall && _vm->_party->checkSkill(SPOT_DOORS)) ? _spotDoorsUIFrame + 28 : 28,
 		Common::Point(194, 91));
 	_spotDoorsUIFrame = (_spotDoorsUIFrame + 1) % 12;
 
 	// Draw UI element to indicate whether can sense danger
 	_borderSprites.draw(screen,
-		(_vm->_dangerSenseAllowed && _vm->_party.checkSkill(DANGER_SENSE)) ? _spotDoorsUIFrame + 40 : 40,
+		(_vm->_dangerSenseAllowed && _vm->_party->checkSkill(DANGER_SENSE)) ? _spotDoorsUIFrame + 40 : 40,
 		Common::Point(107, 9));
 	_dangerSenseUIFrame = (_dangerSenseUIFrame + 1) % 12;
 
@@ -344,7 +344,7 @@ void Interface::assembleBorder() {
 	else if (_vm->_face2State == 2)
 		_face2UIFrame = 0;
 
-	if (!_vm->_party._clairvoyanceActive) {
+	if (!_vm->_party->_clairvoyanceActive) {
 		_face1UIFrame = 0;
 		_face2UIFrame = 8;
 	}
@@ -358,54 +358,54 @@ void Interface::assembleBorder() {
 	// Draw resistence indicators
 	if (!screen._windows[10]._enabled && !screen._windows[2]._enabled
 		&& screen._windows[38]._enabled) {
-		_fecpSprites.draw(screen, _vm->_party._fireResistence ? 1 : 0,
+		_fecpSprites.draw(screen, _vm->_party->_fireResistence ? 1 : 0,
 			Common::Point(2, 2));
-		_fecpSprites.draw(screen, _vm->_party._electricityResistence ? 3 : 2,
+		_fecpSprites.draw(screen, _vm->_party->_electricityResistence ? 3 : 2,
 			Common::Point(219, 2));
-		_fecpSprites.draw(screen, _vm->_party._coldResistence ? 5 : 4,
+		_fecpSprites.draw(screen, _vm->_party->_coldResistence ? 5 : 4,
 			Common::Point(2, 134));
-		_fecpSprites.draw(screen, _vm->_party._poisonResistence ? 7 : 6,
+		_fecpSprites.draw(screen, _vm->_party->_poisonResistence ? 7 : 6,
 			Common::Point(219, 134));
 	} else {
-		_fecpSprites.draw(screen, _vm->_party._fireResistence ? 9 : 8,
+		_fecpSprites.draw(screen, _vm->_party->_fireResistence ? 9 : 8,
 			Common::Point(8, 8));
-		_fecpSprites.draw(screen, _vm->_party._electricityResistence ? 10 : 11,
+		_fecpSprites.draw(screen, _vm->_party->_electricityResistence ? 10 : 11,
 			Common::Point(219, 8));
-		_fecpSprites.draw(screen, _vm->_party._coldResistence ? 12 : 13,
+		_fecpSprites.draw(screen, _vm->_party->_coldResistence ? 12 : 13,
 			Common::Point(8, 134));
-		_fecpSprites.draw(screen, _vm->_party._poisonResistence ? 14 : 15,
+		_fecpSprites.draw(screen, _vm->_party->_poisonResistence ? 14 : 15,
 			Common::Point(219, 134));
 	}
 
 	// Draw UI element for blessed
 	_blessSprites.draw(screen, 16, Common::Point(33, 137));
-	if (_vm->_party._blessedActive) {
+	if (_vm->_party->_blessedActive) {
 		_blessedUIFrame = (_blessedUIFrame + 1) % 4;
 		_blessSprites.draw(screen, _blessedUIFrame, Common::Point(33, 137));
 	}
 
 	// Draw UI element for power shield
-	if (_vm->_party._powerShieldActive) {
+	if (_vm->_party->_powerShieldActive) {
 		_powerShieldUIFrame = (_powerShieldUIFrame + 1) % 4;
 		_blessSprites.draw(screen, _powerShieldUIFrame + 4,
 			Common::Point(55, 137));
 	}
 
 	// Draw UI element for holy bonus
-	if (_vm->_party._holyBonusActive) {
+	if (_vm->_party->_holyBonusActive) {
 		_holyBonusUIFrame = (_holyBonusUIFrame + 1) % 4;
 		_blessSprites.draw(screen, _holyBonusUIFrame + 8, Common::Point(160, 137));
 	}
 
 	// Draw UI element for heroism
-	if (_vm->_party._heroismActive) {
+	if (_vm->_party->_heroismActive) {
 		_heroismUIFrame = (_heroismUIFrame + 1) % 4;
 		_blessSprites.draw(screen, _heroismUIFrame + 12, Common::Point(182, 137));
 	}
 
 	// Draw direction character if direction sense is active
-	if (_vm->_party.checkSkill(DIRECTION_SENSE) && !_vm->_noDirectionSense) {
-		const char *dirText = DIRECTION_TEXT[_vm->_party._mazeDirection];
+	if (_vm->_party->checkSkill(DIRECTION_SENSE) && !_vm->_noDirectionSense) {
+		const char *dirText = DIRECTION_TEXT[_vm->_party->_mazeDirection];
 		Common::String msg = Common::String::format(
 			"\002""08\003""c\013""139\011""116%c\014""d\001", *dirText);
 		screen._windows[0].writeString(msg);
@@ -426,7 +426,7 @@ void Interface::setupFaces(int charIndex, Common::Array<int> xeenSideChars, bool
 
 	for (posIndex = 0; posIndex < 4; ++posIndex) {
 		charId = xeenSideChars[charIndex];
-		bool isInParty = _vm->_party.isInParty(charId);
+		bool isInParty = _vm->_party->isInParty(charId);
 
 		if (charId == 0xff) {
 			while ((int)_buttons.size() > (7 + posIndex))
@@ -469,10 +469,10 @@ void Interface::charIconsPrint(bool updateFlag) {
 	_restoreSprites.draw(screen, 0, Common::Point(8, 149));
 
 	// Handle drawing the party faces
-	for (int idx = 0; idx < (stateFlag ? _vm->_party._combatPartyCount : 
-			_vm->_party._partyCount); ++idx) {
+	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.worstCondition();
 		int charFrame = FACE_CONDITION_FRAMES[charCondition];
 		
@@ -485,10 +485,10 @@ void Interface::charIconsPrint(bool updateFlag) {
 	}
 
 	if (!_hpSprites.empty()) {
-		for (int idx = 0; idx < (stateFlag ? _vm->_party._combatPartyCount :
-			_vm->_party._partyCount); ++idx) {
+		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();
@@ -555,7 +555,7 @@ void Interface::draw3d(bool updateFlag) {
 	}
 
 	MazeObject &objObject = map._mobData._objects[_objNumber];
-	Direction partyDirection = _vm->_party._mazeDirection;
+	Direction partyDirection = _vm->_party->_mazeDirection;
 	int objNum = _objNumber - 1;
 
 	// Loop to update the frame numbers for each maze object, applying the animation frame
@@ -2312,4 +2312,102 @@ void Interface::updateAutoMap() {
 	// TODO
 }
 
+/**
+ * Waits for a keypress or click, whilst still allowing the game scene to
+ * be animated.
+ */
+void Interface::wait() {
+	EventsManager &events = *_vm->_events;
+	Map &map = *_vm->_map;
+	Party &party = *_vm->_party;
+	Scripts &scripts = *_vm->_scripts;
+	const Common::Rect waitBounds(8, 8, 224, 140);
+
+	while (!_vm->shouldQuit()) {
+		events.updateGameCounter();
+		draw3d(true);
+
+		// Wait for a frame
+		while (!_vm->shouldQuit()) {
+			events.pollEventsAndWait();
+			checkEvents(_vm);
+		} while (!_buttonValue && events.timeElapsed() < 1 && !_vm->_party->_partyDead);
+
+		if (!_buttonValue && !_vm->_party->_partyDead)
+			continue;
+
+		if (_buttonValue == Common::KEYCODE_SPACE ||
+				(events._leftButton && waitBounds.contains(events._mousePos))) {
+			int lookupId = map.mazeLookup(party._mazePosition, 
+				WALL_NUMBERS[party._mazeDirection][2]);
+
+			bool eventsFlag = true;
+			switch (lookupId) {
+			case 1:
+				if (!map._isOutdoors) {
+					scripts.openGrate(13, 1);
+					eventsFlag = _buttonValue != 0;
+				}
+
+			case 6:
+				if (!map._isOutdoors) {
+					scripts.openGrate(9, 0);
+					eventsFlag = _buttonValue != 0;
+				}
+				break;
+			case 9:
+				if (!map._isOutdoors) {
+					scripts.openGrate(6, 0);
+					eventsFlag = _buttonValue != 0;
+				}
+				break;
+			case 13:
+				if (!map._isOutdoors) {
+					scripts.openGrate(1, 1);
+					eventsFlag = _buttonValue != 0;
+				}
+				break;
+			default:
+				break;
+			}
+			if (eventsFlag) {
+				scripts.checkEvents();
+				if (_vm->shouldQuit())
+					return;
+			}
+		}
+
+		switch (_buttonValue) {
+		case Common::KEYCODE_TAB:
+			// Stop mosters doing any movement
+			_vm->_moveMonsters = false;
+			warning("TODO: showControlPanel");
+			break;
+
+		case Common::KEYCODE_SPACE:
+		case Common::KEYCODE_w:
+			// Wait one turn
+			chargeStep();
+			moveMonsters();
+			_upDoorText = false;
+			_flipDefaultGround = !_flipDefaultGround;
+			_flipGround = !_flipGround;
+			break;
+		default:
+			break;
+		}
+	}
+}
+
+void Interface::chargeStep() {
+	if (_vm->_party->_partyDead) {
+		_vm->_party->changeTime(_vm->_map->_isOutdoors ? 10 : 1);
+		if (!_tillMove) {
+			moveMonsters();
+		}
+
+		_tillMove = 3;
+	}
+}
+
 } // End of namespace Xeen
diff --git a/engines/xeen/interface.h b/engines/xeen/interface.h
index df06f5d..c6fee9e 100644
--- a/engines/xeen/interface.h
+++ b/engines/xeen/interface.h
@@ -63,7 +63,6 @@ private:
 	int _holyBonusUIFrame;
 	int _heroismUIFrame;
 	int _flipUIFrame;
-	bool _newDay;
 	bool _buttonsLoaded;
 	Common::String _interfaceText;
 	int _hiliteChar;
@@ -74,6 +73,7 @@ private:
 	byte _tillMove;
 	bool _thinWall;
 	int _overallFrame;
+	bool _upDoorText;
 
 	void initDrawStructs();
 
@@ -85,8 +85,6 @@ private:
 
 	void setupFaces(int charIndex, Common::Array<int> xeenSideChars, bool updateFlag);
 
-	void charIconsPrint(bool updateFlag);
-
 	void drawViewBackground(int bgType);
 
 	void moveCharacterToRoster();
@@ -100,6 +98,8 @@ private:
 	void setMazeBits();
 
 	void updateAutoMap();
+
+	void chargeStep();
 public:
 	Interface(XeenEngine *vm);
 
@@ -116,6 +116,10 @@ public:
 	void startup();
 
 	void mainIconsPrint();
+
+	void charIconsPrint(bool updateFlag);
+
+	void wait();
 };
 
 } // End of namespace Xeen
diff --git a/engines/xeen/interface_map.cpp b/engines/xeen/interface_map.cpp
index 93c3d9a..1f92711 100644
--- a/engines/xeen/interface_map.cpp
+++ b/engines/xeen/interface_map.cpp
@@ -165,7 +165,7 @@ OutdoorDrawList::OutdoorDrawList() : _skySprite(_data[1]), _groundSprite(_data[2
 /*------------------------------------------------------------------------*/
 
 IndoorDrawList::IndoorDrawList() : 
-	_sky(_data[1]), _ground(_data[2]), _horizon(_data[28]),
+	_sky1(_data[0]), _sky2(_data[1]), _ground(_data[2]), _horizon(_data[28]),
 	_swl_0F1R(_data[146]), _swl_0F1L(_data[144]), _swl_1F1R(_data[134]), 
 	_swl_1F1L(_data[133]), _swl_2F2R(_data[110]), _swl_2F1R(_data[109]), 
 	_swl_2F1L(_data[108]), _swl_2F2L(_data[107]), _swl_3F1R(_data[ 78]), 
@@ -378,8 +378,8 @@ InterfaceMap::InterfaceMap(XeenEngine *vm): _vm(vm) {
 void InterfaceMap::setIndoorsMonsters() {
 	Combat &combat = *_vm->_combat;
 	Map &map = *_vm->_map;
-	Common::Point mazePos = _vm->_party._mazePosition;
-	Direction dir = _vm->_party._mazeDirection;
+	Common::Point mazePos = _vm->_party->_mazePosition;
+	Direction dir = _vm->_party->_mazeDirection;
 	const int INDOOR_MONSTERS_Y[4] = { 2, 34, 53, 59 };
 
 	combat.clear();
@@ -645,8 +645,8 @@ void InterfaceMap::setMonsterSprite(DrawStruct &drawStruct, MazeMonster &monster
 }
 
 void InterfaceMap::setIndoorsObjects() {
-	Common::Point mazePos = _vm->_party._mazePosition;
-	Direction dir = _vm->_party._mazeDirection;
+	Common::Point mazePos = _vm->_party->_mazePosition;
+	Direction dir = _vm->_party->_mazeDirection;
 	Common::Point pt;
 	_objNumber = 0;
 
@@ -871,8 +871,8 @@ void InterfaceMap::setIndoorsObjects() {
 
 void InterfaceMap::setIndoorsWallPics() {
 	Map &map = *_vm->_map;
-	const Common::Point &mazePos = _vm->_party._mazePosition;
-	Direction dir = _vm->_party._mazeDirection;
+	const Common::Point &mazePos = _vm->_party->_mazePosition;
+	Direction dir = _vm->_party->_mazeDirection;
 
 	Common::fill(&_wp[0], &_wp[20], -1);
 
@@ -1912,7 +1912,7 @@ void InterfaceMap::drawIndoors() {
 		_indoorList._swl_0F1R._frame = 25;
 	}
 
-	map.cellFlagLookup(_vm->_party._mazePosition);
+	map.cellFlagLookup(_vm->_party->_mazePosition);
 
 	// WORKAROUND: Original did an array lookup on _skySprites.
 	// Was this a feature for multiple skys that was abandoned?
@@ -1922,19 +1922,19 @@ void InterfaceMap::drawIndoors() {
 
 	if (_vm->_openDoor) {
 		Common::Point pt(
-			_vm->_party._mazePosition.x + SCREEN_POSITIONING_X[
-				_vm->_party._mazeDirection][_vm->_party._mazePosition.x],
-			_vm->_party._mazePosition.y + SCREEN_POSITIONING_Y[
-				_vm->_party._mazeDirection][_vm->_party._mazePosition.y]
+			_vm->_party->_mazePosition.x + SCREEN_POSITIONING_X[
+				_vm->_party->_mazeDirection][_vm->_party->_mazePosition.x],
+			_vm->_party->_mazePosition.y + SCREEN_POSITIONING_Y[
+				_vm->_party->_mazeDirection][_vm->_party->_mazePosition.y]
 			);
 		map.cellFlagLookup(pt);
 		
-		_indoorList._sky._sprites = &map._skySprites;
+		_indoorList._sky2._sprites = &map._skySprites;
 	} else {
-		_indoorList._sky._sprites = _indoorList[0]._sprites;
+		_indoorList._sky2._sprites = _indoorList[0]._sprites;
 	}
 
-	_indoorList._sky._flags = _flipSky ? SPRFLAG_HORIZ_FLIPPED : 0;
+	_indoorList._sky2._flags = _flipSky ? SPRFLAG_HORIZ_FLIPPED : 0;
 	_indoorList._ground._flags = _flipDefaultGround ? SPRFLAG_HORIZ_FLIPPED : 0;
 	_indoorList._horizon._frame = 7;
 
@@ -1943,7 +1943,7 @@ void InterfaceMap::drawIndoors() {
 
 	// Check for any character shooting
 	_isShooting = false;
-	for (int i = 0; i < _vm->_party._partyCount; ++i) {
+	for (int i = 0; i < _vm->_party->_partyCount; ++i) {
 		if (_vm->_combat->_shooting[i])
 			_isShooting = true;
 	}
diff --git a/engines/xeen/interface_map.h b/engines/xeen/interface_map.h
index fd807a0..be17ef0 100644
--- a/engines/xeen/interface_map.h
+++ b/engines/xeen/interface_map.h
@@ -50,7 +50,7 @@ public:
 class IndoorDrawList {
 public:
 	DrawStruct _data[170];
-	DrawStruct &_sky;
+	DrawStruct &_sky1, &_sky2;
 	DrawStruct &_ground;
 	DrawStruct &_horizon;
 	DrawStruct * const _groundTiles;
diff --git a/engines/xeen/map.cpp b/engines/xeen/map.cpp
index 99fe5ad..bef0511 100644
--- a/engines/xeen/map.cpp
+++ b/engines/xeen/map.cpp
@@ -887,7 +887,7 @@ void Map::load(int mapId) {
 	}
 
 	_stepped = true;
-	_vm->_party._mazeId = mapId;
+	_vm->_party->_mazeId = mapId;
 	_vm->_events->clearEvents();
 
 	_sideObjects = 1;
@@ -970,7 +970,7 @@ void Map::load(int mapId) {
 
 			if (isDarkCc && mapId == 50)
 				mazeDataP->setAllTilesStepped();
-			if (!isDarkCc && _vm->_party._gameFlags[25] &&
+			if (!isDarkCc && _vm->_party->_gameFlags[25] &&
 					(mapId == 42 || mapId == 43 || mapId == 4)) {
 				mazeDataP->clearCellSurfaces();
 			}
@@ -1004,14 +1004,14 @@ void Map::load(int mapId) {
 				_headData.synchronize(headFile);
 				headFile.close();
 
-				if (!isDarkCc && _vm->_party._mazeId)
+				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;
+						_vm->_party->_gameFlags[56] = true;
 					}
 				}
 			}
@@ -1029,7 +1029,7 @@ void Map::load(int mapId) {
 	// TODO: Switch setting flags that don't seem to ever be used
  
 	// Reload the monster data for the main maze that we're loading
-	mapId = _vm->_party._mazeId;
+	mapId = _vm->_party->_mazeId;
 	Common::String filename = Common::String::format("maze%c%03d.mob",
 		(mapId >= 100) ? 'x' : '0', mapId);
 	File mobFile(filename, *_vm->_saves);
@@ -1039,10 +1039,10 @@ void Map::load(int mapId) {
 
 	// Load sprites for the objects
 	for (uint i = 0; i < _mobData._objectSprites.size(); ++i) {
-		if (_vm->_party._cloudsEnd && _mobData._objectSprites[i]._spriteId == 85 &&
+		if (_vm->_party->_cloudsEnd && _mobData._objectSprites[i]._spriteId == 85 &&
 				mapId == 27 && isDarkCc) {
 			// TODO: Flags set that don't seem to be used
-		} else if (mapId == 12 && _vm->_party._gameFlags[43] &&
+		} else if (mapId == 12 && _vm->_party->_gameFlags[43] &&
 			_mobData._objectSprites[i]._spriteId == 118 && !isDarkCc) {
 			filename = "085.obj";
 			_mobData._objectSprites[0]._spriteId = 85;
@@ -1081,7 +1081,6 @@ void Map::load(int mapId) {
 	if (_isOutdoors) {
 		warning("TODO");	// Sound loading
 
-		_skySprites.load(isDarkCc ? "night.sky" : "sky.sky");
 		_groundSprites.load("water.out");
 		_tileSprites.load("outdoor.til");
 		outdoorList._skySprite._sprites = &_skySprites;
@@ -1102,7 +1101,6 @@ void Map::load(int mapId) {
 	} else {
 		warning("TODO");	// Sound loading
 
-		_skySprites.load(isDarkCc ? "night.sky" : "sky.sky");
 		_mazeSkySprites.load(Common::String::format("%s.sky",
 			TERRAIN_TYPES[_mazeData[0]._wallKind]));
 		_groundSprites.load(Common::String::format("%s.gnd",
@@ -1193,18 +1191,20 @@ void Map::load(int mapId) {
 				indoorList._horizon._sprites = nullptr;
 		}
 	}
+
+	loadSky();
 }
 
-int Map::mazeLookup(const Common::Point &pt, int directionLayerIndex) {
+int Map::mazeLookup(const Common::Point &pt, int layerShift) {
 	Common::Point pos = pt;
-	int mapId = _vm->_party._mazeId;
+	int mapId = _vm->_party->_mazeId;
 
 	if (pt.x < -16 || pt.y < -16 || pt.x >= 32 || pt.y >= 32)
 		error("Invalid coordinate");
 
 	// Find the correct maze data out of the set to use
 	_mazeDataIndex = 0;
-	while (_mazeData[_mazeDataIndex]._mazeId != _vm->_party._mazeId)
+	while (_mazeData[_mazeDataIndex]._mazeId != _vm->_party->_mazeId)
 		++_mazeDataIndex;
 
 	// Handle map changing to the north or south as necessary
@@ -1259,7 +1259,7 @@ int Map::mazeLookup(const Common::Point &pt, int directionLayerIndex) {
 			_currentSteppedOn = _mazeData[_mazeDataIndex]._steppedOnTiles[pos.y][pos.x];
 		}
 
-		return (_mazeData[_mazeDataIndex]._wallData[pos.y][pos.x]._data >> (directionLayerIndex * 4)) & 0xF;
+		return (_mazeData[_mazeDataIndex]._wallData[pos.y][pos.x]._data >> layerShift) & 0xF;
 
 	} else {
 		_currentSteppedOn = _isOutdoors;
@@ -1312,7 +1312,7 @@ void Map::saveMaze() {
 
 void Map::cellFlagLookup(const Common::Point &pt) {
 	Common::Point pos = pt;
-	int mapId = _vm->_party._mazeId;
+	int mapId = _vm->_party->_mazeId;
 	_mazeDataIndex = 0;
 	while (_mazeData[_mazeDataIndex]._mazeId != mapId)
 		++_mazeDataIndex;
@@ -1364,11 +1364,11 @@ void Map::setCellSurfaceFlags(const Common::Point &pt, int bits) {
 
 
 int Map::getCell(int idx) {
-	int mapId = _vm->_party._mazeId;
-	Direction dir = _vm->_party._mazeDirection;
+	int mapId = _vm->_party->_mazeId;
+	Direction dir = _vm->_party->_mazeDirection;
 	Common::Point pt(
-		_vm->_party._mazePosition.x + SCREEN_POSITIONING_X[_vm->_party._mazeDirection][idx],
-		_vm->_party._mazePosition.y + SCREEN_POSITIONING_Y[_vm->_party._mazeDirection][idx]
+		_vm->_party->_mazePosition.x + SCREEN_POSITIONING_X[_vm->_party->_mazeDirection][idx],
+		_vm->_party->_mazePosition.y + SCREEN_POSITIONING_Y[_vm->_party->_mazeDirection][idx]
 	);
 
 	if (pt.x > 31 || pt.y > 31) {
@@ -1484,10 +1484,19 @@ int Map::getCell(int idx) {
 			_currentSurfaceId = _mazeData[_mazeDataIndex]._cells[pt.y][pt.x]._surfaceId;
 
 		_currentWall = wallLayers;
-		return (_currentWall._data >> (WALL_NUMBERS[dir][idx * 2] * 4)) & 0xF;
+		return (_currentWall._data >> WALL_NUMBERS[dir][idx]) & 0xF;
 	}
 
 	return _currentWall._data;
 }
 
+void Map::loadSky() {
+	Party &party = *_vm->_party;
+
+	party._isNight = party._minutes < (5 * 60) || party._minutes >= (21 * 60);
+	_skySprites.load(((party._mazeId >= 89 && party._mazeId <= 112) ||
+		party._mazeId == 128 || party._mazeId == 129) || !party._isNight 
+		? "sky.sky" : "night.sky");
+}
+
 } // End of namespace Xeen
diff --git a/engines/xeen/map.h b/engines/xeen/map.h
index c97de72..ae8ad28 100644
--- a/engines/xeen/map.h
+++ b/engines/xeen/map.h
@@ -392,7 +392,7 @@ public:
 
 	void load(int mapId);
 
-	int mazeLookup(const Common::Point &pt, int directionLayerIndex);
+	int mazeLookup(const Common::Point &pt, int layerShift);
 
 	void cellFlagLookup(const Common::Point &pt);
 
@@ -404,6 +404,7 @@ public:
 
 	MazeData mazeData() { return _mazeData[0]; }
 
+	void loadSky();
 };
 
 } // End of namespace Xeen
diff --git a/engines/xeen/party.cpp b/engines/xeen/party.cpp
index ad6d214..6d5cc22 100644
--- a/engines/xeen/party.cpp
+++ b/engines/xeen/party.cpp
@@ -23,9 +23,11 @@
 #include "common/scummsys.h"
 #include "common/algorithm.h"
 #include "xeen/party.h"
+#include "xeen/dialogs_error.h"
 #include "xeen/files.h"
-#include "xeen/xeen.h"
+#include "xeen/resources.h"
 #include "xeen/saves.h"
+#include "xeen/xeen.h"
 
 namespace Xeen {
 
@@ -155,6 +157,16 @@ int PlayerStruct::getMaxHp() {
 	return 20;
 }
 
+int PlayerStruct::getStat(int statNum, int v2) {
+	// TODO
+	return 10;
+}
+
+bool PlayerStruct::charSavingThrow() {
+	// TODO
+	return false;
+}
+
 /*------------------------------------------------------------------------*/
 
 void Roster::synchronize(Common::Serializer &s) {
@@ -167,7 +179,7 @@ void Roster::synchronize(Common::Serializer &s) {
 
 /*------------------------------------------------------------------------*/
 
-Party::Party() {
+Party::Party(XeenEngine *vm): _vm(vm) {
 	_partyCount = 0;
 	_realPartyCount = 0;
 	Common::fill(&_partyMembers[0], &_partyMembers[8], 0);
@@ -216,6 +228,9 @@ Party::Party() {
 		Common::fill(&_characterFlags[i][0], &_characterFlags[i][24], false);
 
 	_combatPartyCount = 0;
+	_partyDead = false;
+	_newDay = false;
+	_isNight = false;
 }
 
 void Party::synchronize(Common::Serializer &s) {
@@ -343,4 +358,190 @@ void Party::copyPartyToRoster(Roster &r) {
 	}
 }
 
+/**
+ * Adds time to the party's playtime, taking into account the effect of any
+ * stat modifier changes
+ */
+void Party::changeTime(int numMinutes) {
+	bool killed = false;
+
+	if (((_minutes + numMinutes) / 480) != (_minutes / 480)) {
+		for (int idx = 0; idx < _partyCount; ++idx) {
+			PlayerStruct &player = _activeParty[idx];
+
+			if (!player._conditions[DEAD] && !player._conditions[STONED] &&
+					!player._conditions[ERADICATED]) {
+				for (int statNum = 0; statNum < TOTAL_STATS; ++statNum) {
+					int statVal = player.getStat(statNum, 0);
+					if (statVal < 1)
+						player._conditions[DEAD] = 1;
+				}
+			}
+
+			// Handle heart broken condition becoming depression
+			if (player._conditions[HEART_BROKEN]) {
+				if (++player._conditions[HEART_BROKEN] > 10) {
+					player._conditions[HEART_BROKEN] = 0;
+					player._conditions[DEPRESSED] = 1;
+				}
+			}
+
+			// Handle poisoning
+			if (!player._conditions[POISONED]) {
+				if (_vm->getRandomNumber(9) != 1 || !player.charSavingThrow())
+					player._conditions[POISONED] *= 2;
+				else
+					// Poison wears off
+					player._conditions[POISONED] = 0;
+			}
+
+			// Handle poisoning
+			if (!player._conditions[DISEASED]) {
+				if (_vm->getRandomNumber(9) != 1 || !player.charSavingThrow())
+					player._conditions[DISEASED] *= 2;
+				else
+					// Disease wears off
+					player._conditions[DISEASED] = 0;
+			}
+
+			// Handle insane status
+			if (player._conditions[INSANE])
+				player._conditions[INSANE]++;
+
+			if (player._conditions[DEAD]) {
+				if (++player._conditions[DEAD] == 0)
+					player._conditions[DEAD] = -1;
+			}
+
+			if (player._conditions[STONED]) {
+				if (++player._conditions[STONED] == 0)
+					player._conditions[STONED] = -1;
+			}
+
+			if (player._conditions[ERADICATED]) {
+				if (++player._conditions[ERADICATED] == 0)
+					player._conditions[ERADICATED] = -1;
+			}
+
+			if (player._conditions[IN_LOVE]) {
+				if (++player._conditions[IN_LOVE] > 10) {
+					player._conditions[IN_LOVE] = 0;
+					player._conditions[HEART_BROKEN] = 1;
+				}
+			}
+
+			player._conditions[WEAK] = player._conditions[DRUNK];
+			player._conditions[DRUNK] = 0;
+
+			if (player._conditions[DEPRESSED]) {
+				player._conditions[DEPRESSED] = (player._conditions[DEPRESSED] + 1) % 4;
+			}
+		}
+	}
+
+	// Increment the time
+	addTime(numMinutes);
+
+	for (int idx = 0; idx < _partyCount; ++idx) {
+		PlayerStruct &player = _activeParty[idx];
+
+		if (player._conditions[CONFUSED] && _vm->getRandomNumber(2) == 1) {
+			if (player.charSavingThrow()) {
+				player._conditions[CONFUSED] = 0;
+			} else {
+				player._conditions[CONFUSED]--;
+			}
+		}
+
+		if (player._conditions[PARALYZED] && _vm->getRandomNumber(4) == 1)
+			player._conditions[PARALYZED]--;
+	}
+	
+	if (killed)
+		_vm->_interface->charIconsPrint(true);
+
+	if (_isNight != (_minutes < (5 * 60) || _minutes >= (21 * 60)))
+		_vm->_map->loadSky();
+}
+
+void Party::addTime(int numMinutes) {
+	int day = _day;
+	_minutes += numMinutes;
+	
+	// If the total minutes has exceeded a day, move to next one
+	while (_minutes >= (24 * 60)) {
+		_minutes -= 24 * 60;
+		if (++_day >= 100) {
+			_day -= 100;
+			++_year;
+		}
+	}
+
+	if ((_day % 10) == 1 || numMinutes > (24 * 60)) {
+		if (_day != day) {
+			warning("TODO: resetBlacksmith? and giveInterest?");
+		}
+	}
+
+	if (_day != day)
+		_newDay = true;
+
+	if (_newDay && _minutes >= 300) {
+		if (_vm->_mode != MODE_9 && _vm->_mode != MODE_17) {
+			resetTemps();
+			if (_rested || _vm->_mode == MODE_5) {
+				_rested = false;
+			} else {
+				for (int idx = 0; idx < _partyCount; ++idx) {
+					if (_activeParty[idx]._conditions[WEAK] >= 0)
+						_activeParty[idx]._conditions[WEAK]++;
+				}
+
+				ErrorScroll::show(_vm, THE_PARTY_NEEDS_REST, WT_NONFREEZED_WAIT);
+			}
+
+			_vm->_interface->charIconsPrint(true);
+		}
+
+		_newDay = false;
+	}
+}
+
+void Party::resetTemps() {
+	for (int idx = 0; idx < _partyCount; ++idx) {
+		PlayerStruct &player = _activeParty[idx];
+
+		player._magicResistence._temporary = 0;
+		player._energyResistence._temporary = 0;
+		player._poisonResistence._temporary = 0;
+		player._electricityResistence._temporary = 0;
+		player._coldResistence._temporary = 0;
+		player._fireResistence._temporary = 0;
+		player._ACTemp = 0;
+		player._level._temporary = 0;
+		player._luck._temporary = 0;
+		player._accuracy._temporary = 0;
+		player._speed._temporary = 0;
+		player._endurance._temporary = 0;
+		player._personality._temporary = 0;
+		player._intellect._temporary = 0;
+		player._might._temporary = 0;
+	}
+
+	_poisonResistence = 0;
+	_coldResistence = 0;
+	_electricityResistence = 0;
+	_fireResistence = 0;
+	_lightCount = 0;
+	_levitateActive = false;
+	_walkOnWaterActive = false;
+	_wizardEyeActive = false;
+	_clairvoyanceActive = false;
+	_heroismActive = false;
+	_holyBonusActive = false;
+	_powerShieldActive = false;
+	_blessedActive = false;
+}
+
+
 } // End of namespace Xeen
diff --git a/engines/xeen/party.h b/engines/xeen/party.h
index d8fe2ab..75a6c2b 100644
--- a/engines/xeen/party.h
+++ b/engines/xeen/party.h
@@ -66,6 +66,7 @@ enum Condition { CURSED = 0, HEART_BROKEN = 1, WEAK = 2, POISONED = 3,
 #define TOTAL_CHARACTERS 30
 #define XEEN_TOTAL_CHARACTERS 24
 #define MAX_ACTIVE_PARTY 6
+#define TOTAL_STATS 7
 
 class XeenEngine;
 
@@ -133,6 +134,10 @@ public:
 	int getAge(int partyYear, bool ignoreTemp);
 
 	int getMaxHp();
+
+	int getStat(int statNum, int v2);
+
+	bool charSavingThrow();
 };
 
 class Roster: public Common::Array<PlayerStruct> {
@@ -143,6 +148,8 @@ public:
 };
 
 class Party {
+private:
+	XeenEngine *_vm;
 public:
 	// Dynamic data that's saved
 	int _partyCount;
@@ -202,8 +209,11 @@ public:
 	// Other party related runtime data
 	Common::Array<PlayerStruct> _activeParty;
 	int _combatPartyCount;
+	bool _partyDead;
+	bool _newDay;
+	bool _isNight;
 public:
-	Party();
+	Party(XeenEngine *vm);
 
 	void synchronize(Common::Serializer &s);
 
@@ -212,6 +222,12 @@ public:
 	bool isInParty(int charId);
 
 	void copyPartyToRoster(Roster &r);
+
+	void changeTime(int numMinutes);
+
+	void addTime(int numMinutes);
+
+	void resetTemps();
 };
 
 } // End of namespace Xeen
diff --git a/engines/xeen/resources.cpp b/engines/xeen/resources.cpp
index 51f26fe..085f84a 100644
--- a/engines/xeen/resources.cpp
+++ b/engines/xeen/resources.cpp
@@ -66,6 +66,8 @@ const char *const OPTIONS_TITLE =
 	"\v117Copyright (c) 1993 NWC, Inc.\n"
 	"All Rights Reserved\x01";
 
+const char *const THE_PARTY_NEEDS_REST = "\x0B""012The Party needs rest!";
+
 const char *const TERRAIN_TYPES[6] = {
 	"town", "cave", "towr", "cstl", "dung", "scfi"
 };
@@ -392,43 +394,27 @@ const int DIRECTION_ANIM_POSITIONS[4][4] = {
 	{ 0, 1, 2, 3 }, { 3, 0, 1, 2 }, { 2, 3, 0, 1 }, { 1, 2, 3, 0 }
 };
 
-const byte WALL_NUMBERS[4][96] = {
+const byte WALL_NUMBERS[4][48] = {
 	{
-	3, 0, 0, 0, 3, 0, 2, 0, 3, 0, 3, 0,
-	0, 0, 3, 0, 2, 0, 3, 0, 3, 0, 0, 0,
-	3, 0, 0, 0, 3, 0, 2, 0, 3, 0, 2, 0,
-	3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0,
-	0, 0, 3, 0, 0, 0, 3, 0, 2, 0, 3, 0,
-	2, 0, 3, 0, 2, 0, 3, 0, 2, 0, 3, 0,
-	0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 0,
-	2, 0, 2, 0, 0, 0, 0, 0, 1, 0, 1, 0
+		12, 0, 12, 8, 12, 12, 0, 12, 8, 12, 12, 0,
+		12, 0, 12, 8, 12, 8, 12, 12, 0, 12, 0, 12,
+		0, 12, 0, 12, 8, 12, 8, 12, 8, 12, 8, 12,
+		0, 0, 0, 0, 8, 8, 8, 8, 0, 0, 4, 4
 	}, {
-	2, 0, 3, 0, 2, 0, 1, 0, 2, 0, 2, 0,
-	3, 0, 2, 0, 1, 0, 2, 0, 2, 0, 3, 0,
-	2, 0, 3, 0, 2, 0, 1, 0, 2, 0, 1, 0,
-	2, 0, 2, 0, 3, 0, 2, 0, 3, 0, 2, 0,
-	3, 0, 2, 0, 3, 0, 2, 0, 1, 0, 2, 0,
-	1, 0, 2, 0, 1, 0, 2, 0, 1, 0, 2, 0,
-	3, 0, 3, 0, 3, 0, 3, 0, 1, 0, 1, 0,
-	1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0
+		8, 12, 8, 4, 8, 8, 12, 8, 4, 8, 8, 12,
+		8, 12, 8, 4, 8, 4, 8, 8, 12, 8, 12, 8,
+		12, 8, 12, 8, 4, 8, 4, 8, 4, 8, 4, 8,
+		12, 12, 12, 12, 4, 4, 4, 4, 0, 0, 0, 0
 	}, {
-	1, 0, 2, 0, 1, 0, 0, 0, 1, 0, 1, 0,
-	2, 0, 1, 0, 0, 0, 1, 0, 1, 0, 2, 0,
-	1, 0, 2, 0, 1, 0, 0, 0, 1, 0, 0, 0,
-	1, 0, 1, 0, 2, 0, 1, 0, 2, 0, 1, 0,
-	2, 0, 1, 0, 2, 0, 1, 0, 0, 0, 1, 0,
-	0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0,
-	2, 0, 2, 0, 2, 0, 2, 0, 0, 0, 0, 0,
-	0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 3, 0
+		4, 8, 4, 0, 4, 4, 8, 4, 0, 4, 4, 8,
+		4, 8, 4, 0, 4, 0, 4, 4, 8, 4, 8, 4,
+		8, 4, 8, 4, 0, 4, 0, 4, 0, 4, 0, 4,
+		8, 8, 8, 8, 0, 0, 0, 0, 0, 0, 12, 12
 	}, {
-	0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 0, 0,
-	1, 0, 0, 0, 3, 0, 0, 0, 0, 0, 1, 0,
-	0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 3, 0,
-	0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0,
-	1, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0,
-	3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0,
-	1, 0, 1, 0, 1, 0, 1, 0, 3, 0, 3, 0,
-	3, 0, 3, 0, 0, 0, 0, 0, 2, 0, 2, 0
+		0, 4, 0, 12, 0, 0, 4, 0, 12, 0, 0, 4,
+		0, 4, 0, 12, 0, 12, 0, 0, 4, 0, 4, 0,
+		4, 0, 4, 0, 12, 0, 12, 0, 12, 0, 12, 0,
+		4, 4, 4, 4, 12, 12, 12, 12, 0, 0, 8, 8
 	}
 };
 
diff --git a/engines/xeen/resources.h b/engines/xeen/resources.h
index 0ef9211..f6bcffa 100644
--- a/engines/xeen/resources.h
+++ b/engines/xeen/resources.h
@@ -32,6 +32,8 @@ extern const char *const CREDITS;
 
 extern const char *const OPTIONS_TITLE;
 
+extern const char *const THE_PARTY_NEEDS_REST;
+
 extern const char *const TERRAIN_TYPES[6];
 
 extern const char *const SURFACE_TYPE_NAMES[15];
@@ -88,7 +90,7 @@ extern const int OUTDOOR_OBJECT_Y[2][12];
 
 extern const int DIRECTION_ANIM_POSITIONS[4][4];
 
-extern const byte WALL_NUMBERS[4][96];
+extern const byte WALL_NUMBERS[4][48];
 
 extern const int DRAW_NUMBERS[25];
 
diff --git a/engines/xeen/scripts.cpp b/engines/xeen/scripts.cpp
index 0a864aa..5a36a32 100644
--- a/engines/xeen/scripts.cpp
+++ b/engines/xeen/scripts.cpp
@@ -61,4 +61,21 @@ void MazeEvents::synchronize(XeenSerializer &s) {
 	}
 }
 
+/*------------------------------------------------------------------------*/
+
+Scripts::Scripts(XeenEngine *vm) : _vm(vm) {
+}
+
+void Scripts::checkEvents() {
+	// TODO
+}
+
+void Scripts::giveTreasure() {
+	// TODO
+}
+
+void Scripts::openGrate(int v1, int v2) {
+	// TODO
+}
+
 } // End of namespace Xeen
diff --git a/engines/xeen/scripts.h b/engines/xeen/scripts.h
index 727d37f..4f49018 100644
--- a/engines/xeen/scripts.h
+++ b/engines/xeen/scripts.h
@@ -95,6 +95,8 @@ enum Opcode {
 	OP_PlayCD		= 0x3C
 };
 
+class XeenEngine;
+
 class MazeEvent {
 public:
 	Common::Point _position;
@@ -115,6 +117,19 @@ public:
 	void synchronize(XeenSerializer &s);
 };
 
+class Scripts {
+private:
+	XeenEngine *_vm;
+public:
+	Scripts(XeenEngine *vm);
+
+	void checkEvents();
+
+	void giveTreasure();
+
+	void openGrate(int v1, int v2);
+};
+
 } // End of namespace Xeen
 
 #endif /* XEEN_SCRIPTS_H */
diff --git a/engines/xeen/sprites.cpp b/engines/xeen/sprites.cpp
index 448ec0e..1d9a5c8 100644
--- a/engines/xeen/sprites.cpp
+++ b/engines/xeen/sprites.cpp
@@ -230,6 +230,7 @@ void SpriteResource::drawOffset(XSurface &dest, uint16 offset, const Common::Poi
 
 void SpriteResource::draw(XSurface &dest, int frame, const Common::Point &destPos, 
 		int flags, int scale) const {
+	scale = 0; // ***DEBUG***
 	if (scale == 0) {
 		drawOffset(dest, _index[frame]._offset1, destPos, flags);
 		if (_index[frame]._offset2)
diff --git a/engines/xeen/xeen.cpp b/engines/xeen/xeen.cpp
index 6b73de6..b8f9030 100644
--- a/engines/xeen/xeen.cpp
+++ b/engines/xeen/xeen.cpp
@@ -42,8 +42,10 @@ XeenEngine::XeenEngine(OSystem *syst, const XeenGameDescription *gameDesc)
 	_files = nullptr;
 	_interface = nullptr;
 	_map = nullptr;
+	_party = nullptr;
 	_saves = nullptr;
 	_screen = nullptr;
+	_scripts = nullptr;
 	_sound = nullptr;
 	_eventData = nullptr;
 	_loadDarkSide = 1;
@@ -63,8 +65,10 @@ XeenEngine::~XeenEngine() {
 	delete _events;
 	delete _interface;
 	delete _map;
+	delete _party;
 	delete _saves;
 	delete _screen;
+	delete _scripts;
 	delete _sound;
 	delete _eventData;
 	delete _files;
@@ -84,8 +88,10 @@ void XeenEngine::initialize() {
 	_events = new EventsManager(this);
 	_interface = new Interface(this);
 	_map = new Map(this);
-	_saves = new SavesManager(this, _party, _roster);
+	_party = new Party(this);
+	_saves = new SavesManager(this, *_party, _roster);
 	_screen = new Screen(this);
+	_scripts = new Scripts(this);
 	_screen->setupWindows();
 	_sound = new SoundManager(this);
 
@@ -281,13 +287,13 @@ void XeenEngine::play() {
 
 	if (getGameID() != GType_WorldOfXeen && !_loadDarkSide) {
 		_loadDarkSide = true;
-		_party._mazeId = 29;
-		_party._mazeDirection = DIR_NORTH;
-		_party._mazePosition.x = 25;
-		_party._mazePosition.y = 21;
+		_party->_mazeId = 29;
+		_party->_mazeDirection = DIR_NORTH;
+		_party->_mazePosition.x = 25;
+		_party->_mazePosition.y = 21;
 	}
 
-	_map->load(_party._mazeId);
+	_map->load(_party->_mazeId);
 
 	_interface->startup();
 	if (_mode == MODE_0) {
@@ -307,9 +313,22 @@ void XeenEngine::play() {
 
 	_moveMonsters = true;
 
+	gameLoop();
+}
+
+void XeenEngine::gameLoop() {
 	// Main game loop
 	while (!shouldQuit()) {
-		_events->pollEventsAndWait();
+		_map->cellFlagLookup(_party->_mazePosition);
+		if (_map->_currentIsEvent) {
+			_scripts->checkEvents();
+			if (shouldQuit())
+				return;
+		}
+		_scripts->giveTreasure();
+
+		// Wait loop
+		_interface->wait();
 	}
 }
 
diff --git a/engines/xeen/xeen.h b/engines/xeen/xeen.h
index e6bcd8c..59816b0 100644
--- a/engines/xeen/xeen.h
+++ b/engines/xeen/xeen.h
@@ -41,6 +41,7 @@
 #include "xeen/party.h"
 #include "xeen/saves.h"
 #include "xeen/screen.h"
+#include "xeen/scripts.h"
 #include "xeen/sound.h"
 
 /**
@@ -102,6 +103,8 @@ private:
 	void play();
 
 	void pleaseWait();
+
+	void gameLoop();
 protected:
 	/**
 	* Play the game
@@ -131,14 +134,15 @@ public:
 	FileManager *_files;
 	Interface *_interface;
 	Map *_map;
+	Party *_party;
 	SavesManager *_saves;
 	Screen *_screen;
+	Scripts *_scripts;
 	SoundManager *_sound;
 	Mode _mode;
 	GameEvent _gameEvent;
 	Common::SeekableReadStream *_eventData;
 	Roster _roster;
-	Party _party;
 	int _loadDarkSide;
 	bool _dangerSenseAllowed;
 	int _face1State;


Commit: ec294d662e7d54a9927c2b85ec430e1519be5de7
    https://github.com/scummvm/scummvm/commit/ec294d662e7d54a9927c2b85ec430e1519be5de7
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-01-19T12:13:03-05:00

Commit Message:
XEEN: Add extra ending code for pausing turns

Changed paths:
    engines/xeen/dialogs.cpp
    engines/xeen/interface.cpp
    engines/xeen/interface.h
    engines/xeen/party.cpp
    engines/xeen/party.h
    engines/xeen/sound.h
    engines/xeen/xeen.cpp



diff --git a/engines/xeen/dialogs.cpp b/engines/xeen/dialogs.cpp
index 824e824..d1662ae 100644
--- a/engines/xeen/dialogs.cpp
+++ b/engines/xeen/dialogs.cpp
@@ -52,6 +52,7 @@ void ButtonContainer::addButton(const Common::Rect &bounds, int val, SpriteResou
 
 bool ButtonContainer::checkEvents(XeenEngine *vm) {
 	EventsManager &events = *vm->_events;
+	_buttonValue = 0;
 
 	if (events._leftButton) {
 		// Check whether any button is selected
diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp
index e15c057..8ff0b92 100644
--- a/engines/xeen/interface.cpp
+++ b/engines/xeen/interface.cpp
@@ -49,6 +49,7 @@ Interface::Interface(XeenEngine *vm) : ButtonContainer(), InterfaceMap(vm), _vm(
 	_thinWall = false;
 	_overallFrame = 0;
 	_upDoorText = false;
+	_steppingFX = 0;
 
 	Common::fill(&_combatCharIds[0], &_combatCharIds[8], 0);
 	initDrawStructs();
@@ -2316,7 +2317,7 @@ void Interface::updateAutoMap() {
  * Waits for a keypress or click, whilst still allowing the game scene to
  * be animated.
  */
-void Interface::wait() {
+void Interface::perform() {
 	EventsManager &events = *_vm->_events;
 	Map &map = *_vm->_map;
 	Party &party = *_vm->_party;
@@ -2328,7 +2329,7 @@ void Interface::wait() {
 		draw3d(true);
 
 		// Wait for a frame
-		while (!_vm->shouldQuit()) {
+		do {
 			events.pollEventsAndWait();
 			checkEvents(_vm);
 		} while (!_buttonValue && events.timeElapsed() < 1 && !_vm->_party->_partyDead);
@@ -2392,6 +2393,8 @@ void Interface::wait() {
 			_upDoorText = false;
 			_flipDefaultGround = !_flipDefaultGround;
 			_flipGround = !_flipGround;
+
+			stepTime();
 			break;
 		default:
 			break;
@@ -2410,4 +2413,29 @@ void Interface::chargeStep() {
 	}
 }
 
+/**
+ * Handles incrementing game time
+ */
+void Interface::stepTime() {
+	Party &party = *_vm->_party;
+	SoundManager &sound = *_vm->_sound;
+	doStepCode();
+	
+	if (++party._ctr24 == 24)
+		party._ctr24 = 0;
+
+	if (_buttonValue != Common::KEYCODE_SPACE && _buttonValue != Common::KEYCODE_w) {
+		_steppingFX ^= 1;
+		sound.playFX(_steppingFX + 7);
+	}
+
+	_upDoorText = false;
+	_flipDefaultGround = !_flipDefaultGround;
+	_flipGround = !_flipGround;
+}
+
+void Interface::doStepCode() {
+	// TODO
+}
+
 } // End of namespace Xeen
diff --git a/engines/xeen/interface.h b/engines/xeen/interface.h
index c6fee9e..af26611 100644
--- a/engines/xeen/interface.h
+++ b/engines/xeen/interface.h
@@ -74,6 +74,7 @@ private:
 	bool _thinWall;
 	int _overallFrame;
 	bool _upDoorText;
+	int _steppingFX;
 
 	void initDrawStructs();
 
@@ -100,6 +101,10 @@ private:
 	void updateAutoMap();
 
 	void chargeStep();
+
+	void stepTime();
+
+	void doStepCode();
 public:
 	Interface(XeenEngine *vm);
 
@@ -119,7 +124,7 @@ public:
 
 	void charIconsPrint(bool updateFlag);
 
-	void wait();
+	void perform();
 };
 
 } // End of namespace Xeen
diff --git a/engines/xeen/party.cpp b/engines/xeen/party.cpp
index 6d5cc22..4571bbe 100644
--- a/engines/xeen/party.cpp
+++ b/engines/xeen/party.cpp
@@ -198,7 +198,7 @@ Party::Party(XeenEngine *vm): _vm(vm) {
 	_cloudsEnd = false;
 	_darkSideEnd = false;
 	_worldEnd = false;
-	hour_maybe = 0;
+	_ctr24 = 0;
 	_day = 0;
 	_year = 0;
 	_minutes = 0;
@@ -273,7 +273,7 @@ void Party::synchronize(Common::Serializer &s) {
 	s.syncAsUint16LE(_cloudsEnd);
 	s.syncAsUint16LE(_darkSideEnd);
 	s.syncAsUint16LE(_worldEnd);
-	s.syncAsUint16LE(hour_maybe);
+	s.syncAsUint16LE(_ctr24);
 	s.syncAsUint16LE(_day);
 	s.syncAsUint16LE(_year);
 	s.syncAsUint16LE(_minutes);
diff --git a/engines/xeen/party.h b/engines/xeen/party.h
index 75a6c2b..8db52df 100644
--- a/engines/xeen/party.h
+++ b/engines/xeen/party.h
@@ -176,7 +176,7 @@ public:
 	bool _cloudsEnd;
 	bool _darkSideEnd;
 	bool _worldEnd;
-	int hour_maybe;
+	int _ctr24;	// TODO: Figure out proper name
 	int _day;
 	int _year;
 	int _minutes;
diff --git a/engines/xeen/sound.h b/engines/xeen/sound.h
index 553b1c6..c121524 100644
--- a/engines/xeen/sound.h
+++ b/engines/xeen/sound.h
@@ -42,6 +42,8 @@ public:
 	void playSong(Common::SeekableReadStream &f) {}
 
 	void playSample(const Common::SeekableReadStream *stream, int v2) {}
+
+	void playFX(int id) {}
 };
 
 } // End of namespace Xeen
diff --git a/engines/xeen/xeen.cpp b/engines/xeen/xeen.cpp
index b8f9030..e9b4d93 100644
--- a/engines/xeen/xeen.cpp
+++ b/engines/xeen/xeen.cpp
@@ -327,8 +327,8 @@ void XeenEngine::gameLoop() {
 		}
 		_scripts->giveTreasure();
 
-		// Wait loop
-		_interface->wait();
+		// Main user interface handler for waiting for and processing user input
+		_interface->perform();
 	}
 }
 


Commit: e559a99c2794c727d04adf4602f0aac1112af765
    https://github.com/scummvm/scummvm/commit/e559a99c2794c727d04adf4602f0aac1112af765
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-01-19T15:29:57-05:00

Commit Message:
XEEN: Initial implementation of drawMiniMap

Changed paths:
    engines/xeen/interface.cpp
    engines/xeen/interface.h
    engines/xeen/map.cpp
    engines/xeen/map.h



diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp
index 8ff0b92..bcb406d 100644
--- a/engines/xeen/interface.cpp
+++ b/engines/xeen/interface.cpp
@@ -722,7 +722,7 @@ void Interface::draw3d(bool updateFlag) {
 	}
 
 	animate3d();
-	updateAutoMap();
+	drawMiniMap();
 
 	if (_vm->_falling == 1) {
 		error("TODO: Indoor falling");
@@ -808,7 +808,7 @@ void Interface::setMainButtons() {
 	addButton(Common::Rect(235, 169, 259, 189), 176, &_iconSprites);
 	addButton(Common::Rect(260, 169, 284, 189), 243, &_iconSprites);
 	addButton(Common::Rect(286, 169, 310, 189), 177, &_iconSprites);
-	addButton(Common::Rect(236,  11, 308,  69),  61, &_iconSprites, false);
+	addButton(Common::Rect(236,  11, 308,  69),  Common::KEYCODE_EQUALS, &_iconSprites, false);
 	addButton(Common::Rect(239,  27, 312,  37),  49, &_iconSprites, false);
 	addButton(Common::Rect(239,  37, 312,  47),  50, &_iconSprites, false);
 	addButton(Common::Rect(239,  47, 312,  57),  51, &_iconSprites, false);
@@ -2309,96 +2309,468 @@ void Interface::setMazeBits() {
 	}
 }
 
-void Interface::updateAutoMap() {
-	// TODO
-}
-
-/**
- * Waits for a keypress or click, whilst still allowing the game scene to
- * be animated.
- */
-void Interface::perform() {
-	EventsManager &events = *_vm->_events;
+void Interface::drawMiniMap() {
 	Map &map = *_vm->_map;
 	Party &party = *_vm->_party;
-	Scripts &scripts = *_vm->_scripts;
-	const Common::Rect waitBounds(8, 8, 224, 140);
+	Screen &screen = *_vm->_screen;
+	Window &window1 = screen._windows[1];
 
-	while (!_vm->shouldQuit()) {
-		events.updateGameCounter();
-		draw3d(true);
+	if (screen._windows[2]._enabled || screen._windows[10]._enabled ||
+			(!party._automapOn && !party._wizardEyeActive))
+		return;
 
-		// Wait for a frame
-		do {
-			events.pollEventsAndWait();
-			checkEvents(_vm);
-		} while (!_buttonValue && events.timeElapsed() < 1 && !_vm->_party->_partyDead);
+	int v, frame;
+	int frame2 = _overallFrame * 2;
+	bool eyeActive = party._wizardEyeActive;
+	if (party._automapOn)
+		party._wizardEyeActive = false;
 
-		if (!_buttonValue && !_vm->_party->_partyDead)
-			continue;
+	if (map._isOutdoors) {
+		_globalSprites.draw(window1, 15, Common::Point(237, 12));
 
-		if (_buttonValue == Common::KEYCODE_SPACE ||
-				(events._leftButton && waitBounds.contains(events._mousePos))) {
-			int lookupId = map.mazeLookup(party._mazePosition, 
-				WALL_NUMBERS[party._mazeDirection][2]);
+		for (int rowNum = 0, yp = 12, yDiff = 3; rowNum < MINIMAP_SIZE; ++rowNum, yp += 8, --yDiff) {
+			for (int colNum = 0, xp = 237, xDiff = -3; colNum < MINIMAP_SIZE; ++colNum, xp += 10, ++xDiff) {
+				v = map.mazeLookup(
+					Common::Point(party._mazePosition.x + xDiff, party._mazePosition.y + yDiff),
+					4);
+				frame = map.mazeDataCurrent()._surfaceTypes[v];
 
-			bool eventsFlag = true;
-			switch (lookupId) {
-			case 1:
-				if (!map._isOutdoors) {
-					scripts.openGrate(13, 1);
-					eventsFlag = _buttonValue != 0;
+				if (frame != -1 && (map._currentSteppedOn || party._wizardEyeActive)) {
+					map._tileSprites.draw(window1, frame, Common::Point(xp, yp));
 				}
+			}
+		}
 
-			case 6:
-				if (!map._isOutdoors) {
-					scripts.openGrate(9, 0);
-					eventsFlag = _buttonValue != 0;
+		for (int rowNum = 0, yp = 12, yDiff = 3; rowNum < MINIMAP_SIZE; ++rowNum, yp += 8, --yDiff) {
+			for (int colNum = 0, xp = 237, xDiff = -3; colNum < MINIMAP_SIZE; ++colNum, xp += 10, ++xDiff) {
+				v = map.mazeLookup(
+					Common::Point(party._mazePosition.x + xDiff, party._mazePosition.y + yDiff),
+					4);
+				frame = map.mazeData()._wallTypes[v];
+
+				if (frame != -1 && (map._currentSteppedOn || party._wizardEyeActive)) {
+					map._tileSprites.draw(window1, frame + 16, Common::Point(xp, yp));
 				}
+			}
+		}
+
+		for (int rowNum = 0, yp = 12, yDiff = 3; rowNum < MINIMAP_SIZE; ++rowNum, yp += 8, --yDiff) {
+			for (int colNum = 0, xp = 237, xDiff = -3; colNum < MINIMAP_SIZE; ++colNum, xp += 10, ++xDiff) {
+				v = map.mazeLookup(
+					Common::Point(party._mazePosition.x + xDiff, party._mazePosition.y + yDiff),
+					4);
+
+				if (v != -1 && (map._currentSteppedOn || party._wizardEyeActive)) {
+					map._tileSprites.draw(window1, v + 32, Common::Point(xp, yp));
+				}
+			}
+		}
+	} else {
+		frame2 = (frame2 + 2) % 8;
+		
+		// First draw cell back for positions in the map that have been revealed
+		for (int rowNum = 0, yp = 12, yDiff = 3; rowNum < MINIMAP_SIZE; ++rowNum, yp += 8, --yDiff) {
+			for (int colNum = 0, xp = 237, xDiff = -3; colNum < MINIMAP_SIZE; ++colNum, xp += 10, ++xDiff) {
+				v = map.mazeLookup(
+					Common::Point(party._mazePosition.x + xDiff, party._mazePosition.y + yDiff),
+					0, 0xffff);
+
+				if (v != 0xffff && (map._currentSteppedOn || party._wizardEyeActive)) {
+					map._tileSprites.draw(window1, 0, Common::Point(xp, yp));
+				}
+			}
+		}
+
+		// Draw tiles based on the surface for each revelaed tile
+		for (int rowNum = 0, yp = 17, yDiff = 3; rowNum < MINIMAP_SIZE; ++rowNum, yp += 8, --yDiff) {
+			for (int colNum = 0, xp = 242, xDiff = -3; colNum < MINIMAP_SIZE; ++colNum, xp += 10, ++xDiff) {
+				v = map.mazeLookup(
+					Common::Point(party._mazePosition.x + xDiff, party._mazePosition.y + yDiff),
+					0, 0xffff);
+
+				if (v != 0xffff && !map._currentSurfaceId && 
+						(map._currentSteppedOn || party._wizardEyeActive)) {
+					map._tileSprites.draw(window1, 
+						map.mazeData()._surfaceTypes[map._currentSurfaceId] + 36,
+						Common::Point(xp, yp));
+				}
+			}
+		}
+
+		v = map.mazeLookup(Common::Point(party._mazePosition.x - 4, party._mazePosition.y + 4), 0xffff, 0);
+		if (v != 0xffff && !map._currentSurfaceId && 
+				(map._currentSteppedOn || party._wizardEyeActive)) {
+			map._tileSprites.draw(window1,
+				map.mazeData()._surfaceTypes[map._currentSurfaceId] + 36,
+				Common::Point(232, 9));
+		}
+
+		// Right edge
+		for (int rowNum = 0, yp = 242, yDiff = -3; rowNum < MINIMAP_SIZE; ++rowNum, --yDiff, yp += 8) {
+			v = map.mazeLookup(
+					Common::Point(party._mazePosition.x - 4, party._mazePosition.y + yDiff),
+					0, 0xffff);
+
+			if (v != 0xffff && !map._currentSurfaceId &&
+				(map._currentSteppedOn || party._wizardEyeActive)) {
+				map._tileSprites.draw(window1,
+					map.mazeData()._surfaceTypes[map._currentSurfaceId] + 36,
+					Common::Point(232, yp));
+			}
+		}
+
+		// Top edge
+		for (int colNum = 0, xp = 242, xDiff = -3; colNum < MINIMAP_SIZE; ++colNum, --xDiff, xp += 8) {
+			v = map.mazeLookup(
+				Common::Point(party._mazePosition.x + xDiff, party._mazePosition.y + 4),
+				0, 0xffff);
+
+			if (v != 0xffff && !map._currentSurfaceId &&
+					(map._currentSteppedOn || party._wizardEyeActive)) {
+				map._tileSprites.draw(window1,
+					map.mazeData()._surfaceTypes[map._currentSurfaceId] + 36,
+					Common::Point(xp, 9));
+			}
+		}
+
+		//
+		for (int idx = 0, xp = 237, yp = 60, xDiff = -3; idx < MINIMAP_SIZE; 
+				++idx, --xDiff, xp += 10, yp -= 8) {
+			v = map.mazeLookup(
+				Common::Point(party._mazePosition.x - 4, party._mazePosition.y - 3 + idx),
+				12, 0xffff);
+
+			switch (v) {
+			case 1:
+				frame = 18;
+				break;
+			case 3:
+				frame = 22;
+				break;
+			case 4:
+			case 13:
+				frame = 16;
+				break;
+			case 5:
+			case 8:
+				frame = 2;
+				break;
+			case 6:
+				frame = 30;
+				break;
+			case 7:
+				frame = 32;
 				break;
 			case 9:
-				if (!map._isOutdoors) {
-					scripts.openGrate(6, 0);
-					eventsFlag = _buttonValue != 0;
-				}
+				frame = 24;
+				break;
+			case 10:
+				frame = 28;
+				break;
+			case 11:
+				frame = 14;
+				break;
+			case 12:
+				frame = frame2 + 4;
+				break;
+			case 14:
+				frame = 24;
+				break;
+			case 15:
+				frame = 26;
+				break;
+			default:
+				frame = -1;
 				break;
+			}
+
+			if (frame != -1 && (map._currentSteppedOn || party._wizardEyeActive))
+				map._tileSprites.draw(window1, frame, Common::Point(222, yp));
+
+			v = map.mazeLookup(
+				Common::Point(party._mazePosition.x - 3 + idx, party._mazePosition.y + 4),
+				0);
+
+			switch (v) {
+			case 1:
+				frame = 19;
+				break;
+			case 2:
+				frame = 35;
+				break;
+			case 3:
+				frame = 23;
+				break;
+			case 4:
 			case 13:
-				if (!map._isOutdoors) {
-					scripts.openGrate(1, 1);
-					eventsFlag = _buttonValue != 0;
-				}
+				frame = 17;
+				break;
+			case 5:
+			case 8:
+				frame = 3;
+				break;
+			case 6:
+				frame = 31;
+				break;
+			case 7:
+				frame = 33;
+				break;
+			case 9:
+				frame = 21;
+				break;
+			case 10:
+				frame = 29;
+				break;
+			case 11:
+				frame = 15;
+				break;
+			case 12:
+				frame = frame2 + 5;
+				break;
+			case 14:
+				frame = 25;
+				break;
+			case 15:
+				frame = 27;
 				break;
 			default:
+				frame = -1;
 				break;
 			}
-			if (eventsFlag) {
-				scripts.checkEvents();
-				if (_vm->shouldQuit())
-					return;
+
+			if (frame != -1 && (map._currentSteppedOn || party._wizardEyeActive))
+				map._tileSprites.draw(window1, frame, Common::Point(xp, 4));
+		}
+
+		//
+		for (int rowNum = 0, yp = 12, yDiff = 3; rowNum < MINIMAP_SIZE;
+				++rowNum, --yDiff, yp -= 8) {
+			for (int colNum = 0, xp = 237, xDiff = -3; colNum < MINIMAP_SIZE;
+					++colNum, ++xDiff, xp += 10) {
+				if (colNum == 4 && rowNum == 4) {
+					// Center of the minimap
+					_globalSprites.draw(window1, party._mazeDirection + 1,
+						Common::Point(272, 40));
+				}
+
+				v = map.mazeLookup(Common::Point(party._mazePosition.x + xDiff,
+					party._mazePosition.y + yDiff), 12, 0xffff);
+				switch (v) {
+				case 1:
+					frame = 18;
+					break;
+				case 3:
+					frame = 22;
+					break;
+				case 4:
+				case 13:
+					frame = 16;
+					break;
+				case 5:
+				case 8:
+					frame = 2;
+					break;
+				case 6:
+					frame = 30;
+					break;
+				case 7:
+					frame = 32;
+					break;
+				case 9:
+					frame = 20;
+					break;
+				case 10:
+					frame = 28;
+					break;
+				case 11:
+					frame = 14;
+					break;
+				case 12:
+					frame = frame2 + 4;
+					break;
+				case 14:
+					frame = 24;
+					break;
+				case 15:
+					frame = 26;
+					break;
+				default:
+					frame = -1;
+					break;
+				}
+
+				if (frame != -1 && (map._currentSteppedOn || party._wizardEyeActive)) {
+					map._tileSprites.draw(window1, frame, Common::Point(xp, yp));
+				}
+
+				v = map.mazeLookup(Common::Point(party._mazePosition.x + xDiff,
+					party._mazePosition.y + yDiff), 12, 0xffff);
+				switch (v) {
+				case 1:
+					frame = 19;
+					break;
+				case 2:
+					frame = 35;
+					break;
+				case 3:
+					frame = 23;
+					break;
+				case 4:
+				case 13:
+					frame = 17;
+					break;
+				case 5:
+				case 8:
+					frame = 3;
+					break;
+				case 6:
+					frame = 31;
+					break;
+				case 7:
+					frame = 33;
+					break;
+				case 9:
+					frame = 21;
+					break;
+				case 10:
+					frame = 29;
+					break;
+				case 11:
+					frame = 15;
+					break;
+				case 12:
+					frame = frame2 + 5;
+					break;
+				case 14:
+					frame = 25;
+					break;
+				case 15:
+					frame = 27;
+					break;
+				default:
+					frame = -1;
+					break;
+				}
+
+				if (v == -1 && (map._currentSteppedOn || party._wizardEyeActive)) {
+					map._tileSprites.draw(window1, frame, Common::Point(xp, yp));
+				}
 			}
 		}
 
-		switch (_buttonValue) {
-		case Common::KEYCODE_TAB:
-			// Stop mosters doing any movement
-			_vm->_moveMonsters = false;
-			warning("TODO: showControlPanel");
-			break;
+		// Final loop
+		for (int rowNum = 0, yp = 12, yDiff = 3; rowNum < MINIMAP_SIZE; ++rowNum, yp += 8, --yDiff) {
+			for (int colNum = 0, xp = 237, xDiff = -3; colNum < MINIMAP_SIZE; ++colNum, xp += 10, ++xDiff) {
+				v = map.mazeLookup(
+					Common::Point(party._mazePosition.x + xDiff, party._mazePosition.y + yDiff),
+					0, 0xffff);
 
-		case Common::KEYCODE_SPACE:
-		case Common::KEYCODE_w:
-			// Wait one turn
-			chargeStep();
-			moveMonsters();
-			_upDoorText = false;
-			_flipDefaultGround = !_flipDefaultGround;
-			_flipGround = !_flipGround;
+				if (v != 0xffff && !map._currentSurfaceId &&
+					(map._currentSteppedOn || party._wizardEyeActive)) {
+					map._tileSprites.draw(window1, 1, Common::Point(xp, yp));
+				}
+			}
+		}
+	}
+
+	if (map._isOutdoors) {
+		_globalSprites.draw(window1, party._mazeDirection + 1,
+			Common::Point(267, 36));
+	}
+
+	_globalSprites.draw(window1, 6, Common::Point(223, 3));
+	party._wizardEyeActive = eyeActive;
+}
+
+/**
+ * Waits for a keypress or click, whilst still allowing the game scene to
+ * be animated.
+ */
+void Interface::perform() {
+	EventsManager &events = *_vm->_events;
+	Map &map = *_vm->_map;
+	Party &party = *_vm->_party;
+	Scripts &scripts = *_vm->_scripts;
+	const Common::Rect waitBounds(8, 8, 224, 140);
+
+	events.updateGameCounter();
+	draw3d(true);
+
+	// Wait for a frame
+	do {
+		events.pollEventsAndWait();
+		checkEvents(_vm);
+	} while (!_buttonValue && events.timeElapsed() < 1 && !_vm->_party->_partyDead);
 
-			stepTime();
+	if (!_buttonValue && !_vm->_party->_partyDead)
+		return;
+
+	if (_buttonValue == Common::KEYCODE_SPACE ||
+			(events._leftButton && waitBounds.contains(events._mousePos))) {
+		int lookupId = map.mazeLookup(party._mazePosition, 
+			WALL_NUMBERS[party._mazeDirection][2]);
+
+		bool eventsFlag = true;
+		switch (lookupId) {
+		case 1:
+			if (!map._isOutdoors) {
+				scripts.openGrate(13, 1);
+				eventsFlag = _buttonValue != 0;
+			}
+
+		case 6:
+			if (!map._isOutdoors) {
+				scripts.openGrate(9, 0);
+				eventsFlag = _buttonValue != 0;
+			}
+			break;
+		case 9:
+			if (!map._isOutdoors) {
+				scripts.openGrate(6, 0);
+				eventsFlag = _buttonValue != 0;
+			}
+			break;
+		case 13:
+			if (!map._isOutdoors) {
+				scripts.openGrate(1, 1);
+				eventsFlag = _buttonValue != 0;
+			}
 			break;
 		default:
 			break;
 		}
+		if (eventsFlag) {
+			scripts.checkEvents();
+			if (_vm->shouldQuit())
+				return;
+		}
+	}
+
+	switch (_buttonValue) {
+	case Common::KEYCODE_TAB:
+		// Stop mosters doing any movement
+		_vm->_moveMonsters = false;
+		warning("TODO: showControlPanel");
+		break;
+
+	case Common::KEYCODE_SPACE:
+	case Common::KEYCODE_w:
+		// Wait one turn
+		chargeStep();
+		moveMonsters();
+		_upDoorText = false;
+		_flipDefaultGround = !_flipDefaultGround;
+		_flipGround = !_flipGround;
+
+		stepTime();
+		break;
+	case Common::KEYCODE_EQUALS:
+	case Common::KEYCODE_KP_EQUALS:
+		// Toggle minimap
+		party._automapOn = !party._automapOn;
+		break;
+	default:
+		break;
 	}
 }
 
diff --git a/engines/xeen/interface.h b/engines/xeen/interface.h
index af26611..2e19d22 100644
--- a/engines/xeen/interface.h
+++ b/engines/xeen/interface.h
@@ -33,6 +33,8 @@ namespace Xeen {
 
 class XeenEngine;
 
+#define MINIMAP_SIZE 7
+
 class Interface: public ButtonContainer, public InterfaceMap {
 private:
 	XeenEngine *_vm;
@@ -98,7 +100,7 @@ private:
 
 	void setMazeBits();
 
-	void updateAutoMap();
+	void drawMiniMap();
 
 	void chargeStep();
 
diff --git a/engines/xeen/map.cpp b/engines/xeen/map.cpp
index bef0511..17c49be 100644
--- a/engines/xeen/map.cpp
+++ b/engines/xeen/map.cpp
@@ -1195,7 +1195,7 @@ void Map::load(int mapId) {
 	loadSky();
 }
 
-int Map::mazeLookup(const Common::Point &pt, int layerShift) {
+int Map::mazeLookup(const Common::Point &pt, int layerShift, int wallMask) {
 	Common::Point pos = pt;
 	int mapId = _vm->_party->_mazeId;
 
@@ -1259,7 +1259,7 @@ int Map::mazeLookup(const Common::Point &pt, int layerShift) {
 			_currentSteppedOn = _mazeData[_mazeDataIndex]._steppedOnTiles[pos.y][pos.x];
 		}
 
-		return (_mazeData[_mazeDataIndex]._wallData[pos.y][pos.x]._data >> layerShift) & 0xF;
+		return (_mazeData[_mazeDataIndex]._wallData[pos.y][pos.x]._data >> layerShift) & wallMask;
 
 	} else {
 		_currentSteppedOn = _isOutdoors;
diff --git a/engines/xeen/map.h b/engines/xeen/map.h
index ae8ad28..16ef15c 100644
--- a/engines/xeen/map.h
+++ b/engines/xeen/map.h
@@ -362,7 +362,6 @@ private:
 	int _sideMonsters;
 	bool _stepped;
 	int _mazeDataIndex;
-	bool _currentSteppedOn;
 
 	void loadEvents(int mapId);
 public:
@@ -387,12 +386,13 @@ public:
 	MazeWallLayers _currentWall;
 	int _currentTile;
 	int _currentSurfaceId;
+	bool _currentSteppedOn;
 public:
 	Map(XeenEngine *vm);
 
 	void load(int mapId);
 
-	int mazeLookup(const Common::Point &pt, int layerShift);
+	int mazeLookup(const Common::Point &pt, int layerShift, int wallMask = 0xf);
 
 	void cellFlagLookup(const Common::Point &pt);
 
@@ -404,6 +404,8 @@ public:
 
 	MazeData mazeData() { return _mazeData[0]; }
 
+	MazeData mazeDataCurrent() { return _mazeData[_mazeDataIndex]; }
+
 	void loadSky();
 };
 


Commit: 1f312098ade02210345a5adffcc2dd531d24ee7f
    https://github.com/scummvm/scummvm/commit/1f312098ade02210345a5adffcc2dd531d24ee7f
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-01-19T16:20:40-05:00

Commit Message:
XEEN: Minor minimap fixes

Changed paths:
    engines/xeen/interface.cpp
    engines/xeen/map.cpp
    engines/xeen/map.h



diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp
index bcb406d..c017514 100644
--- a/engines/xeen/interface.cpp
+++ b/engines/xeen/interface.cpp
@@ -1115,7 +1115,7 @@ void Interface::setMazeBits() {
 		break;
 	}
 
-	_thinWall = (_vm->_map->_currentWall._data != 0x8888) && _wo[27];
+	_thinWall = (_vm->_map->_currentWall._data != INVALID_CELL) && _wo[27];
 
 	switch (_vm->_map->getCell(8) - 1) {
 	case 1:
@@ -2315,9 +2315,13 @@ void Interface::drawMiniMap() {
 	Screen &screen = *_vm->_screen;
 	Window &window1 = screen._windows[1];
 
-	if (screen._windows[2]._enabled || screen._windows[10]._enabled ||
-			(!party._automapOn && !party._wizardEyeActive))
+	if (screen._windows[2]._enabled || screen._windows[10]._enabled)
 		return;
+	if (!party._automapOn && !party._wizardEyeActive) {
+		// Draw the Might & Magic logo
+		_globalSprites.draw(window1, 5, Common::Point(232, 9));
+		return;
+	}
 
 	int v, frame;
 	int frame2 = _overallFrame * 2;
@@ -2365,9 +2369,13 @@ void Interface::drawMiniMap() {
 				}
 			}
 		}
+		
+		// Draw the direction arrow
+		_globalSprites.draw(window1, party._mazeDirection + 1,
+			Common::Point(267, 36));
 	} else {
 		frame2 = (frame2 + 2) % 8;
-		
+		party._wizardEyeActive = true; //**DEBUG**
 		// First draw cell back for positions in the map that have been revealed
 		for (int rowNum = 0, yp = 12, yDiff = 3; rowNum < MINIMAP_SIZE; ++rowNum, yp += 8, --yDiff) {
 			for (int colNum = 0, xp = 237, xDiff = -3; colNum < MINIMAP_SIZE; ++colNum, xp += 10, ++xDiff) {
@@ -2375,7 +2383,7 @@ void Interface::drawMiniMap() {
 					Common::Point(party._mazePosition.x + xDiff, party._mazePosition.y + yDiff),
 					0, 0xffff);
 
-				if (v != 0xffff && (map._currentSteppedOn || party._wizardEyeActive)) {
+				if (v != INVALID_CELL && (map._currentSteppedOn || party._wizardEyeActive)) {
 					map._tileSprites.draw(window1, 0, Common::Point(xp, yp));
 				}
 			}
@@ -2396,7 +2404,7 @@ void Interface::drawMiniMap() {
 				}
 			}
 		}
-
+		
 		v = map.mazeLookup(Common::Point(party._mazePosition.x - 4, party._mazePosition.y + 4), 0xffff, 0);
 		if (v != 0xffff && !map._currentSurfaceId && 
 				(map._currentSteppedOn || party._wizardEyeActive)) {
@@ -2548,7 +2556,7 @@ void Interface::drawMiniMap() {
 			for (int colNum = 0, xp = 237, xDiff = -3; colNum < MINIMAP_SIZE;
 					++colNum, ++xDiff, xp += 10) {
 				if (colNum == 4 && rowNum == 4) {
-					// Center of the minimap
+					// Center of the minimap. Draw the direction arrow
 					_globalSprites.draw(window1, party._mazeDirection + 1,
 						Common::Point(272, 40));
 				}
@@ -2673,11 +2681,7 @@ void Interface::drawMiniMap() {
 		}
 	}
 
-	if (map._isOutdoors) {
-		_globalSprites.draw(window1, party._mazeDirection + 1,
-			Common::Point(267, 36));
-	}
-
+	// Draw outer rectangle around the automap
 	_globalSprites.draw(window1, 6, Common::Point(223, 3));
 	party._wizardEyeActive = eyeActive;
 }
diff --git a/engines/xeen/map.cpp b/engines/xeen/map.cpp
index 17c49be..2bc6107 100644
--- a/engines/xeen/map.cpp
+++ b/engines/xeen/map.cpp
@@ -1225,7 +1225,7 @@ int Map::mazeLookup(const Common::Point &pt, int layerShift, int wallMask) {
 		} else {
 			// No map, so reached outside indoor area or outer space outdoors
 			_currentSteppedOn = true;
-			return _isOutdoors ? SURFTYPE_SPACE : 0x8888;
+			return _isOutdoors ? SURFTYPE_SPACE : INVALID_CELL;
 		}
 	}
 
@@ -1263,7 +1263,7 @@ int Map::mazeLookup(const Common::Point &pt, int layerShift, int wallMask) {
 
 	} else {
 		_currentSteppedOn = _isOutdoors;
-		return _isOutdoors ? SURFTYPE_SPACE : 0x8888;
+		return _isOutdoors ? SURFTYPE_SPACE : INVALID_CELL;
 	}
 }
 
@@ -1382,8 +1382,8 @@ int Map::getCell(int idx) {
 		} else {
 			_currentSurfaceId = (mapId >= 25 && mapId <= 27) ? 7 : 0;
 		}
-		_currentWall._data = 0x8888;
-		return 0x8888;
+		_currentWall._data = INVALID_CELL;
+		return INVALID_CELL;
 	} 
 
 	_mazeDataIndex = 0;
@@ -1416,8 +1416,8 @@ int Map::getCell(int idx) {
 					_currentSurfaceId = (mapId >= 25 && mapId <= 27) ? SURFTYPE_ROAD : SURFTYPE_DEFAULT;
 				}
 
-				_currentWall._data = 0x8888;
-				return 0x8888;
+				_currentWall._data = INVALID_CELL;
+				return INVALID_CELL;
 			}
 		
 			_mazeDataIndex = 0;
@@ -1452,8 +1452,8 @@ int Map::getCell(int idx) {
 					_currentSurfaceId = (mapId >= 25 && mapId <= 27) ? SURFTYPE_ROAD : SURFTYPE_DEFAULT;
 				}
 
-				_currentWall._data = 0x8888;
-				return 0x8888;
+				_currentWall._data = INVALID_CELL;
+				return INVALID_CELL;
 			}
 		}
 
diff --git a/engines/xeen/map.h b/engines/xeen/map.h
index 16ef15c..9b19b3a 100644
--- a/engines/xeen/map.h
+++ b/engines/xeen/map.h
@@ -35,6 +35,7 @@ namespace Xeen {
 #define MAP_WIDTH 16
 #define MAP_HEIGHT 16
 #define TOTAL_SURFACES 16
+#define INVALID_CELL 0x8888
 
 class XeenEngine;
 


Commit: e966feff5ec36cd2f58cafcf1870937aa10bd86f
    https://github.com/scummvm/scummvm/commit/e966feff5ec36cd2f58cafcf1870937aa10bd86f
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-01-19T18:42:40-05:00

Commit Message:
XEEN: Implemented movement code

Changed paths:
    engines/xeen/dialogs.cpp
    engines/xeen/interface.cpp
    engines/xeen/interface.h



diff --git a/engines/xeen/dialogs.cpp b/engines/xeen/dialogs.cpp
index d1662ae..b25a8e1 100644
--- a/engines/xeen/dialogs.cpp
+++ b/engines/xeen/dialogs.cpp
@@ -69,10 +69,10 @@ bool ButtonContainer::checkEvents(XeenEngine *vm) {
 	} else if (events.isKeyPending()) {
 		Common::KeyState keyState;
 		events.getKey(keyState);
-		if (keyState.ascii >= 32 && keyState.ascii <= 127) {
-			_buttonValue = keyState.ascii;
+		
+		_buttonValue = keyState.keycode | (keyState.flags << 8);
+		if (_buttonValue)
 			return true;
-		}
 	}
 
 	return false;
diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp
index c017514..b6e368e 100644
--- a/engines/xeen/interface.cpp
+++ b/engines/xeen/interface.cpp
@@ -801,13 +801,13 @@ void Interface::setMainButtons() {
 	addButton(Common::Rect(235, 117, 259, 137),  77, &_iconSprites);
 	addButton(Common::Rect(260, 117, 284, 137),  73, &_iconSprites);
 	addButton(Common::Rect(286, 117, 310, 137),  81, &_iconSprites);
-	addButton(Common::Rect(109, 137, 122, 147),   9, &_iconSprites);
-	addButton(Common::Rect(235, 148, 259, 168), 240, &_iconSprites);
-	addButton(Common::Rect(260, 148, 284, 168), 242, &_iconSprites);
-	addButton(Common::Rect(286, 148, 310, 168), 241, &_iconSprites);
-	addButton(Common::Rect(235, 169, 259, 189), 176, &_iconSprites);
-	addButton(Common::Rect(260, 169, 284, 189), 243, &_iconSprites);
-	addButton(Common::Rect(286, 169, 310, 189), 177, &_iconSprites);
+	addButton(Common::Rect(109, 137, 122, 147), Common::KEYCODE_TAB, &_iconSprites);
+	addButton(Common::Rect(235, 148, 259, 168), Common::KEYCODE_LEFT, &_iconSprites);
+	addButton(Common::Rect(260, 148, 284, 168), Common::KEYCODE_UP, &_iconSprites);
+	addButton(Common::Rect(286, 148, 310, 168), Common::KEYCODE_RIGHT, &_iconSprites);
+	addButton(Common::Rect(235, 169, 259, 189), (Common::KBD_CTRL << 16) |Common::KEYCODE_LEFT, &_iconSprites);
+	addButton(Common::Rect(260, 169, 284, 189), Common::KEYCODE_DOWN, &_iconSprites);
+	addButton(Common::Rect(286, 169, 310, 189), (Common::KBD_CTRL << 16) | Common::KEYCODE_RIGHT, &_iconSprites);
 	addButton(Common::Rect(236,  11, 308,  69),  Common::KEYCODE_EQUALS, &_iconSprites, false);
 	addButton(Common::Rect(239,  27, 312,  37),  49, &_iconSprites, false);
 	addButton(Common::Rect(239,  37, 312,  47),  50, &_iconSprites, false);
@@ -2768,6 +2768,131 @@ void Interface::perform() {
 
 		stepTime();
 		break;
+
+	case (Common::KBD_CTRL << 16) | Common::KEYCODE_LEFT:
+	case Common::KEYCODE_KP4:
+		if (checkMoveDirection((Common::KBD_CTRL << 16) | Common::KEYCODE_LEFT)) {
+			switch (party._mazeDirection) {
+			case DIR_NORTH:
+				--party._mazePosition.x;
+				break;
+			case DIR_SOUTH:
+				++party._mazePosition.x;
+				break;
+			case DIR_EAST:
+				++party._mazePosition.y;
+				break;
+			case DIR_WEST:
+				--party._mazePosition.y;
+				break;
+			default:
+				break;
+			}
+
+			chargeStep();
+			_isAnimReset = true;
+			party._mazeDirection = (Direction)((int)party._mazeDirection & 3);
+			_flipSky = !_flipSky;
+			stepTime();
+		}
+		break;
+
+	case (Common::KBD_CTRL << 16) | Common::KEYCODE_RIGHT:
+	case Common::KEYCODE_KP6:
+		if (checkMoveDirection((Common::KBD_CTRL << 16) | Common::KEYCODE_RIGHT)) {
+			switch (party._mazeDirection) {
+			case DIR_NORTH:
+				++party._mazePosition.x;
+				break;
+			case DIR_SOUTH:
+				--party._mazePosition.x;
+				break;
+			case DIR_EAST:
+				--party._mazePosition.y;
+				break;
+			case DIR_WEST:
+				++party._mazePosition.y;
+				break;
+			default:
+				break;
+			}
+
+			chargeStep();
+			_isAnimReset = true;
+			party._mazeDirection = (Direction)((int)party._mazeDirection & 3);
+			_flipSky = !_flipSky;
+			stepTime();
+		}
+		break;
+
+	case Common::KEYCODE_LEFT:
+	case Common::KEYCODE_KP7:
+		party._mazeDirection = (Direction)((int)party._mazeDirection - 1);
+		_isAnimReset = true;
+		party._mazeDirection = (Direction)((int)party._mazeDirection & 3);
+		_flipSky = !_flipSky;
+		stepTime();
+		break;
+
+	case Common::KEYCODE_RIGHT:
+	case Common::KEYCODE_KP9:
+		party._mazeDirection = (Direction)((int)party._mazeDirection + 1);
+		_isAnimReset = true;
+		party._mazeDirection = (Direction)((int)party._mazeDirection & 3);
+		_flipSky = !_flipSky;
+		stepTime();
+		break;
+
+	case Common::KEYCODE_UP:
+	case Common::KEYCODE_KP8:
+		if (checkMoveDirection(Common::KEYCODE_UP)) {
+			switch (party._mazeDirection) {
+			case DIR_NORTH:
+				++party._mazePosition.y;
+				break;
+			case DIR_SOUTH:
+				--party._mazePosition.y;
+				break;
+			case DIR_EAST:
+				++party._mazePosition.x;
+				break;
+			case DIR_WEST:
+				--party._mazePosition.x;
+				break;
+			default:
+				break;
+			}
+
+			chargeStep();
+			stepTime();
+		}
+		break;
+
+	case Common::KEYCODE_DOWN:
+	case Common::KEYCODE_KP2:
+		if (checkMoveDirection(Common::KEYCODE_DOWN)) {
+			switch (party._mazeDirection) {
+			case DIR_NORTH:
+				--party._mazePosition.y;
+				break;
+			case DIR_SOUTH:
+				++party._mazePosition.y;
+				break;
+			case DIR_EAST:
+				--party._mazePosition.x;
+				break;
+			case DIR_WEST:
+				++party._mazePosition.x;
+				break;
+			default:
+				break;
+			}
+
+			chargeStep();
+			stepTime();
+		}
+		break;
+
 	case Common::KEYCODE_EQUALS:
 	case Common::KEYCODE_KP_EQUALS:
 		// Toggle minimap
@@ -2814,4 +2939,102 @@ void Interface::doStepCode() {
 	// TODO
 }
 
+bool Interface::checkMoveDirection(int key) {
+	Map &map = *_vm->_map;
+	Party &party = *_vm->_party;
+	SoundManager &sound = *_vm->_sound;
+	Direction dir = party._mazeDirection;
+
+	switch (_buttonValue) {
+	case (Common::KBD_CTRL << 16) | Common::KEYCODE_LEFT:
+		party._mazeDirection = (party._mazeDirection == DIR_NORTH) ? DIR_WEST :
+			(Direction)(party._mazeDirection - 1);
+		break;
+	case (Common::KBD_CTRL << 16) | Common::KEYCODE_RIGHT:
+		party._mazeDirection = (party._mazeDirection == DIR_WEST) ? DIR_NORTH :
+			(Direction)(party._mazeDirection + 1);
+		break;
+	case Common::KEYCODE_DOWN:
+		party._mazeDirection = (party._mazeDirection == DIR_NORTH) ? DIR_SOUTH : DIR_NORTH;
+		break;
+	default:
+		break;
+	}
+	
+	map.getCell(7);
+	int startSurfaceId = map._currentSurfaceId;
+	int surfaceId;
+
+	if (map._isOutdoors) {
+		party._mazeDirection = dir;
+
+		switch ((int)map._currentWall._outdoors._surfaceId) {
+		case 5:
+			if (_vm->_files->_isDarkCc)
+				goto check;
+
+			// Deliberate FAll-through
+		case 0:
+		case 2:
+		case 4:
+		case 8:
+		case 11:
+		case 13:
+		case 14:
+			surfaceId = map.mazeData()._surfaceTypes[map._currentSurfaceId];
+			if (surfaceId == SURFTYPE_WATER) {
+				if (party.checkSkill(SWIMMING) || party._walkOnWaterActive)
+					return true;
+			} else if (surfaceId == SURFTYPE_DWATER) {
+				if (party._walkOnWaterActive)
+					return true;
+			}
+			else if (surfaceId != SURFTYPE_SPACE) {
+				return true;
+			}
+
+			sound.playFX(21);
+			return false;
+
+		case 1:
+		case 7:
+		case 9:
+		case 10:
+		case 12:
+			check:
+			if (party.checkSkill(MOUNTAINEER))
+				return true;
+
+			sound.playFX(21);
+			return false;
+
+		default:
+			break;
+		}
+	} else {
+		int surfaceId = map.getCell(2);
+		if (surfaceId >= map.mazeData()._difficulties._wallNoPass) {
+			party._mazeDirection = dir;
+		} else {
+			party._mazeDirection = dir;
+
+			if (surfaceId == SURFTYPE_SWAMP || party.checkSkill(SWIMMING) ||
+					party._walkOnWaterActive) {
+				sound.playFX(46);
+				return false;
+			} else {
+				if (_buttonValue == 242 && _wo[107]) {
+					_vm->_openDoor = true;
+					sound.playFX(47);
+					draw3d(true);
+					_vm->_openDoor = false;
+				}
+				return true;
+			}
+		}
+	}
+
+	return true;
+}
+
 } // End of namespace Xeen
diff --git a/engines/xeen/interface.h b/engines/xeen/interface.h
index 2e19d22..8497cc6 100644
--- a/engines/xeen/interface.h
+++ b/engines/xeen/interface.h
@@ -107,6 +107,8 @@ private:
 	void stepTime();
 
 	void doStepCode();
+
+	bool checkMoveDirection(int key);
 public:
 	Interface(XeenEngine *vm);
 


Commit: ebc155ac0abc5eda87541cf56f46b7d18d9903b3
    https://github.com/scummvm/scummvm/commit/ebc155ac0abc5eda87541cf56f46b7d18d9903b3
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-01-19T18:51:29-05:00

Commit Message:
XEEN: Replaced UI button values with KeyCode constants

Changed paths:
    engines/xeen/interface.cpp



diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp
index b6e368e..708e8b7 100644
--- a/engines/xeen/interface.cpp
+++ b/engines/xeen/interface.cpp
@@ -792,15 +792,15 @@ void Interface::moveMonsters() {
 void Interface::setMainButtons() {
 	clearButtons();
 
-	addButton(Common::Rect(235,  75, 259,  95),  83, &_iconSprites);
-	addButton(Common::Rect(260,  75, 284,  95),  67, &_iconSprites);
-	addButton(Common::Rect(286,  75, 310,  95),  82, &_iconSprites);
-	addButton(Common::Rect(235,  96, 259, 116),  66, &_iconSprites);
-	addButton(Common::Rect(260,  96, 284, 116),  68, &_iconSprites);
-	addButton(Common::Rect(286,  96, 310, 116),  86, &_iconSprites);
-	addButton(Common::Rect(235, 117, 259, 137),  77, &_iconSprites);
-	addButton(Common::Rect(260, 117, 284, 137),  73, &_iconSprites);
-	addButton(Common::Rect(286, 117, 310, 137),  81, &_iconSprites);
+	addButton(Common::Rect(235,  75, 259,  95),  Common::KEYCODE_s, &_iconSprites);
+	addButton(Common::Rect(260,  75, 284,  95),  Common::KEYCODE_c, &_iconSprites);
+	addButton(Common::Rect(286,  75, 310,  95),  Common::KEYCODE_r, &_iconSprites);
+	addButton(Common::Rect(235,  96, 259, 116),  Common::KEYCODE_b, &_iconSprites);
+	addButton(Common::Rect(260,  96, 284, 116),  Common::KEYCODE_d, &_iconSprites);
+	addButton(Common::Rect(286,  96, 310, 116),  Common::KEYCODE_v, &_iconSprites);
+	addButton(Common::Rect(235, 117, 259, 137),  Common::KEYCODE_m, &_iconSprites);
+	addButton(Common::Rect(260, 117, 284, 137),  Common::KEYCODE_i, &_iconSprites);
+	addButton(Common::Rect(286, 117, 310, 137),  Common::KEYCODE_q, &_iconSprites);
 	addButton(Common::Rect(109, 137, 122, 147), Common::KEYCODE_TAB, &_iconSprites);
 	addButton(Common::Rect(235, 148, 259, 168), Common::KEYCODE_LEFT, &_iconSprites);
 	addButton(Common::Rect(260, 148, 284, 168), Common::KEYCODE_UP, &_iconSprites);
@@ -809,9 +809,9 @@ void Interface::setMainButtons() {
 	addButton(Common::Rect(260, 169, 284, 189), Common::KEYCODE_DOWN, &_iconSprites);
 	addButton(Common::Rect(286, 169, 310, 189), (Common::KBD_CTRL << 16) | Common::KEYCODE_RIGHT, &_iconSprites);
 	addButton(Common::Rect(236,  11, 308,  69),  Common::KEYCODE_EQUALS, &_iconSprites, false);
-	addButton(Common::Rect(239,  27, 312,  37),  49, &_iconSprites, false);
-	addButton(Common::Rect(239,  37, 312,  47),  50, &_iconSprites, false);
-	addButton(Common::Rect(239,  47, 312,  57),  51, &_iconSprites, false);
+	addButton(Common::Rect(239,  27, 312,  37),  Common::KEYCODE_1, &_iconSprites, false);
+	addButton(Common::Rect(239, 37, 312, 47), Common::KEYCODE_2, &_iconSprites, false);
+	addButton(Common::Rect(239, 47, 312, 57), Common::KEYCODE_3, &_iconSprites, false);
 }
 
 void Interface::setMazeBits() {


Commit: dc8592a9128ed389ba9d466bac96bc15609d3eef
    https://github.com/scummvm/scummvm/commit/dc8592a9128ed389ba9d466bac96bc15609d3eef
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-01-19T19:28:38-05:00

Commit Message:
XEEN: Fix loading of wall types

Changed paths:
    engines/xeen/map.cpp



diff --git a/engines/xeen/map.cpp b/engines/xeen/map.cpp
index 2bc6107..bf03905 100644
--- a/engines/xeen/map.cpp
+++ b/engines/xeen/map.cpp
@@ -1118,12 +1118,14 @@ void Map::load(int mapId) {
 		for (int i = 0; i < TOTAL_SURFACES; ++i)
 			_wallSprites._surfaces[i].clear();
 
-		Common::String fwlName = Common::String::format("%s.til",
-			TERRAIN_TYPES[_mazeData[0]._wallKind]);
-		_wallSprites._fwl1.load(fwlName);
-		_wallSprites._fwl2.load(fwlName);
-		_wallSprites._fwl3.load(fwlName);
-		_wallSprites._fwl4.load(fwlName);
+		_wallSprites._fwl1.load(Common::String::format("f%s1.fwl",
+			TERRAIN_TYPES[_mazeData[0]._wallKind]));
+		_wallSprites._fwl2.load(Common::String::format("f%s2.fwl",
+			TERRAIN_TYPES[_mazeData[0]._wallKind]));
+		_wallSprites._fwl3.load(Common::String::format("f%s3.fwl",
+			TERRAIN_TYPES[_mazeData[0]._wallKind]));
+		_wallSprites._fwl4.load(Common::String::format("f%s4.fwl",
+			TERRAIN_TYPES[_mazeData[0]._wallKind]));
 		_wallSprites._swl.load(Common::String::format("s%s.swl",
 			TERRAIN_TYPES[_mazeData[0]._wallKind]));
 
@@ -1182,7 +1184,7 @@ void Map::load(int mapId) {
 
 		indoorList._ground._sprites = &_groundSprites;
 
-		// Down show horizon for certain maps
+		// Don't show horizon for certain maps
 		if (_vm->_files->_isDarkCc) {
 			if ((mapId >= 89 && mapId <= 112) || mapId == 128 || mapId == 129)
 				indoorList._horizon._sprites = nullptr;


Commit: a1fb631fe3fc16b534dab2e9074bf8a56d16bdc3
    https://github.com/scummvm/scummvm/commit/a1fb631fe3fc16b534dab2e9074bf8a56d16bdc3
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-01-19T22:38:20-05:00

Commit Message:
XEEN: Fix resetting sprites on ground tiles when drawing

Changed paths:
    engines/xeen/interface_map.cpp



diff --git a/engines/xeen/interface_map.cpp b/engines/xeen/interface_map.cpp
index 1f92711..5b1d4e9 100644
--- a/engines/xeen/interface_map.cpp
+++ b/engines/xeen/interface_map.cpp
@@ -1112,8 +1112,8 @@ void InterfaceMap::drawIndoors() {
 		map.getCell(DRAW_NUMBERS[cellIndex]);
 
 		DrawStruct &drawStruct = _indoorList._groundTiles[cellIndex];
-		if (!map._surfaceSprites[map._currentSurfaceId].empty())
-			drawStruct._sprites = &map._surfaceSprites[map._currentSurfaceId];
+		SpriteResource &sprites = map._surfaceSprites[map._currentSurfaceId];
+		drawStruct._sprites = sprites.empty() ? (SpriteResource *)nullptr : &sprites;
 
 		surfaceId = map.mazeData()._surfaceTypes[map._currentSurfaceId];
 		if (surfaceId == SURFTYPE_WATER || surfaceId == SURFTYPE_LAVA || 


Commit: 8cd2e5ad9234b148ad5a960d44422ae982e9091f
    https://github.com/scummvm/scummvm/commit/8cd2e5ad9234b148ad5a960d44422ae982e9091f
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-01-19T22:38:33-05:00

Commit Message:
XEEN: Further work on sprite scaling

Changed paths:
    engines/xeen/sprites.cpp
    engines/xeen/xsurface.cpp



diff --git a/engines/xeen/sprites.cpp b/engines/xeen/sprites.cpp
index 1d9a5c8..62074ed 100644
--- a/engines/xeen/sprites.cpp
+++ b/engines/xeen/sprites.cpp
@@ -230,7 +230,7 @@ void SpriteResource::drawOffset(XSurface &dest, uint16 offset, const Common::Poi
 
 void SpriteResource::draw(XSurface &dest, int frame, const Common::Point &destPos, 
 		int flags, int scale) const {
-	scale = 0; // ***DEBUG***
+
 	if (scale == 0) {
 		drawOffset(dest, _index[frame]._offset1, destPos, flags);
 		if (_index[frame]._offset2)
diff --git a/engines/xeen/xsurface.cpp b/engines/xeen/xsurface.cpp
index b01ade1..7060a63 100644
--- a/engines/xeen/xsurface.cpp
+++ b/engines/xeen/xsurface.cpp
@@ -112,8 +112,8 @@ void XSurface::transBlitTo(XSurface &dest, const Common::Point &destPos,
 			}
 		} while (++distIndex < highestDim);
 
-		destX -= distXCount / 2;
-		destY -= distYCount - 1;
+		destX += (this->w - distXCount) / 2;
+		destY += (this->h - distYCount) / 2;
 	}
 
 	// Start of draw logic for scaled sprites


Commit: d32c90eee9c683b4d62656d3e13d888c16aad9c3
    https://github.com/scummvm/scummvm/commit/d32c90eee9c683b4d62656d3e13d888c16aad9c3
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-01-19T23:18:44-05:00

Commit Message:
XEEN: Some minimap drawing fixes

Changed paths:
    engines/xeen/interface.cpp



diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp
index 708e8b7..67f6363 100644
--- a/engines/xeen/interface.cpp
+++ b/engines/xeen/interface.cpp
@@ -2376,7 +2376,7 @@ void Interface::drawMiniMap() {
 	} else {
 		frame2 = (frame2 + 2) % 8;
 		party._wizardEyeActive = true; //**DEBUG**
-		// First draw cell back for positions in the map that have been revealed
+		// First draw the default surface bases for each cell to show
 		for (int rowNum = 0, yp = 12, yDiff = 3; rowNum < MINIMAP_SIZE; ++rowNum, yp += 8, --yDiff) {
 			for (int colNum = 0, xp = 237, xDiff = -3; colNum < MINIMAP_SIZE; ++colNum, xp += 10, ++xDiff) {
 				v = map.mazeLookup(
@@ -2388,59 +2388,58 @@ void Interface::drawMiniMap() {
 				}
 			}
 		}
-
-		// Draw tiles based on the surface for each revelaed tile
+		
+		// Draw correct surface bases for revealed tiles
 		for (int rowNum = 0, yp = 17, yDiff = 3; rowNum < MINIMAP_SIZE; ++rowNum, yp += 8, --yDiff) {
 			for (int colNum = 0, xp = 242, xDiff = -3; colNum < MINIMAP_SIZE; ++colNum, xp += 10, ++xDiff) {
 				v = map.mazeLookup(
 					Common::Point(party._mazePosition.x + xDiff, party._mazePosition.y + yDiff),
 					0, 0xffff);
+				int surfaceId = map.mazeData()._surfaceTypes[map._currentSurfaceId];
 
-				if (v != 0xffff && !map._currentSurfaceId && 
+				if (v != INVALID_CELL && map._currentSurfaceId &&
 						(map._currentSteppedOn || party._wizardEyeActive)) {
-					map._tileSprites.draw(window1, 
-						map.mazeData()._surfaceTypes[map._currentSurfaceId] + 36,
-						Common::Point(xp, yp));
+					map._tileSprites.draw(window1, surfaceId + 36, Common::Point(xp, yp));
 				}
 			}
 		}
 		
 		v = map.mazeLookup(Common::Point(party._mazePosition.x - 4, party._mazePosition.y + 4), 0xffff, 0);
-		if (v != 0xffff && !map._currentSurfaceId && 
+		if (v != INVALID_CELL && map._currentSurfaceId &&
 				(map._currentSteppedOn || party._wizardEyeActive)) {
 			map._tileSprites.draw(window1,
 				map.mazeData()._surfaceTypes[map._currentSurfaceId] + 36,
 				Common::Point(232, 9));
 		}
-
-		// Right edge
-		for (int rowNum = 0, yp = 242, yDiff = -3; rowNum < MINIMAP_SIZE; ++rowNum, --yDiff, yp += 8) {
+		
+		// Handle drawing surface sprites partially clipped at the left edge
+		for (int rowNum = 0, yp = 17, yDiff = 3; rowNum < MINIMAP_SIZE; ++rowNum, --yDiff, yp += 8) {
 			v = map.mazeLookup(
 					Common::Point(party._mazePosition.x - 4, party._mazePosition.y + yDiff),
 					0, 0xffff);
 
-			if (v != 0xffff && !map._currentSurfaceId &&
-				(map._currentSteppedOn || party._wizardEyeActive)) {
+			if (v != INVALID_CELL && map._currentSurfaceId &&
+					(map._currentSteppedOn || party._wizardEyeActive)) {
 				map._tileSprites.draw(window1,
 					map.mazeData()._surfaceTypes[map._currentSurfaceId] + 36,
 					Common::Point(232, yp));
 			}
 		}
 
-		// Top edge
-		for (int colNum = 0, xp = 242, xDiff = -3; colNum < MINIMAP_SIZE; ++colNum, --xDiff, xp += 8) {
+		// Handle drawing surface sprites partially clipped at the top edge
+		for (int colNum = 0, xp = 242, xDiff = -3; colNum < MINIMAP_SIZE; ++colNum, ++xDiff, xp += 8) {
 			v = map.mazeLookup(
 				Common::Point(party._mazePosition.x + xDiff, party._mazePosition.y + 4),
 				0, 0xffff);
 
-			if (v != 0xffff && !map._currentSurfaceId &&
+			if (v != INVALID_CELL && map._currentSurfaceId &&
 					(map._currentSteppedOn || party._wizardEyeActive)) {
 				map._tileSprites.draw(window1,
 					map.mazeData()._surfaceTypes[map._currentSurfaceId] + 36,
 					Common::Point(xp, 9));
 			}
 		}
-
+		
 		//
 		for (int idx = 0, xp = 237, yp = 60, xDiff = -3; idx < MINIMAP_SIZE; 
 				++idx, --xDiff, xp += 10, yp -= 8) {
@@ -2552,7 +2551,7 @@ void Interface::drawMiniMap() {
 
 		//
 		for (int rowNum = 0, yp = 12, yDiff = 3; rowNum < MINIMAP_SIZE;
-				++rowNum, --yDiff, yp -= 8) {
+				++rowNum, --yDiff, yp += 8) {
 			for (int colNum = 0, xp = 237, xDiff = -3; colNum < MINIMAP_SIZE;
 					++colNum, ++xDiff, xp += 10) {
 				if (colNum == 4 && rowNum == 4) {
@@ -2673,8 +2672,8 @@ void Interface::drawMiniMap() {
 					Common::Point(party._mazePosition.x + xDiff, party._mazePosition.y + yDiff),
 					0, 0xffff);
 
-				if (v != 0xffff && !map._currentSurfaceId &&
-					(map._currentSteppedOn || party._wizardEyeActive)) {
+				if (v != INVALID_CELL && !map._currentSurfaceId &&
+						(map._currentSteppedOn || party._wizardEyeActive)) {
 					map._tileSprites.draw(window1, 1, Common::Point(xp, yp));
 				}
 			}
@@ -2988,8 +2987,7 @@ bool Interface::checkMoveDirection(int key) {
 			} else if (surfaceId == SURFTYPE_DWATER) {
 				if (party._walkOnWaterActive)
 					return true;
-			}
-			else if (surfaceId != SURFTYPE_SPACE) {
+			} else if (surfaceId != SURFTYPE_SPACE) {
 				return true;
 			}
 


Commit: aab62d606ec726b6363f067cee17c284d8b396d1
    https://github.com/scummvm/scummvm/commit/aab62d606ec726b6363f067cee17c284d8b396d1
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-01-19T23:57:13-05:00

Commit Message:
XEEN: More minimap fixes

Changed paths:
    engines/xeen/interface.cpp



diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp
index 67f6363..16ded9e 100644
--- a/engines/xeen/interface.cpp
+++ b/engines/xeen/interface.cpp
@@ -2375,7 +2375,7 @@ void Interface::drawMiniMap() {
 			Common::Point(267, 36));
 	} else {
 		frame2 = (frame2 + 2) % 8;
-		party._wizardEyeActive = true; //**DEBUG**
+
 		// First draw the default surface bases for each cell to show
 		for (int rowNum = 0, yp = 12, yDiff = 3; rowNum < MINIMAP_SIZE; ++rowNum, yp += 8, --yDiff) {
 			for (int colNum = 0, xp = 237, xDiff = -3; colNum < MINIMAP_SIZE; ++colNum, xp += 10, ++xDiff) {
@@ -2442,7 +2442,7 @@ void Interface::drawMiniMap() {
 		
 		//
 		for (int idx = 0, xp = 237, yp = 60, xDiff = -3; idx < MINIMAP_SIZE; 
-				++idx, --xDiff, xp += 10, yp -= 8) {
+				++idx, ++xDiff, xp += 10, yp -= 8) {
 			v = map.mazeLookup(
 				Common::Point(party._mazePosition.x - 4, party._mazePosition.y - 3 + idx),
 				12, 0xffff);
@@ -2549,7 +2549,7 @@ void Interface::drawMiniMap() {
 				map._tileSprites.draw(window1, frame, Common::Point(xp, 4));
 		}
 
-		//
+		// Draw the front/back walls of cells in the minimap
 		for (int rowNum = 0, yp = 12, yDiff = 3; rowNum < MINIMAP_SIZE;
 				++rowNum, --yDiff, yp += 8) {
 			for (int colNum = 0, xp = 237, xDiff = -3; colNum < MINIMAP_SIZE;
@@ -2665,15 +2665,14 @@ void Interface::drawMiniMap() {
 			}
 		}
 
-		// Final loop
+		// Draw the top of blocked/wall cells on the map
 		for (int rowNum = 0, yp = 12, yDiff = 3; rowNum < MINIMAP_SIZE; ++rowNum, yp += 8, --yDiff) {
 			for (int colNum = 0, xp = 237, xDiff = -3; colNum < MINIMAP_SIZE; ++colNum, xp += 10, ++xDiff) {
 				v = map.mazeLookup(
 					Common::Point(party._mazePosition.x + xDiff, party._mazePosition.y + yDiff),
 					0, 0xffff);
 
-				if (v != INVALID_CELL && !map._currentSurfaceId &&
-						(map._currentSteppedOn || party._wizardEyeActive)) {
+				if (v == INVALID_CELL || (!map._currentSteppedOn && !party._wizardEyeActive)) {
 					map._tileSprites.draw(window1, 1, Common::Point(xp, yp));
 				}
 			}


Commit: 2427f203ee9b98d639ecb0bde6aad17c35875a43
    https://github.com/scummvm/scummvm/commit/2427f203ee9b98d639ecb0bde6aad17c35875a43
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-01-20T08:20:07-05:00

Commit Message:
XEEN: Implemented handleLight

Changed paths:
    engines/xeen/interface.cpp
    engines/xeen/interface.h
    engines/xeen/map.cpp
    engines/xeen/map.h
    engines/xeen/party.cpp
    engines/xeen/party.h



diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp
index 16ded9e..e117813 100644
--- a/engines/xeen/interface.cpp
+++ b/engines/xeen/interface.cpp
@@ -743,6 +743,10 @@ void Interface::draw3d(bool updateFlag) {
 
 	// TODO: more stuff
 
+	_vm->_party->_stepped = false;
+	if (_vm->_mode == MODE_9) {
+		// TODO
+	}
 	events.wait(2);
 }
 
@@ -933,6 +937,8 @@ void Interface::setMazeBits() {
 		break;
 	}
 
+	_vm->_party->handleLight();
+
 	switch (_vm->_map->getCell(3) - 1) {
 	case 1:
 		++_wo[73];
@@ -3015,7 +3021,7 @@ bool Interface::checkMoveDirection(int key) {
 		} else {
 			party._mazeDirection = dir;
 
-			if (surfaceId == SURFTYPE_SWAMP || party.checkSkill(SWIMMING) ||
+			if (startSurfaceId == SURFTYPE_SWAMP || party.checkSkill(SWIMMING) ||
 					party._walkOnWaterActive) {
 				sound.playFX(46);
 				return false;
diff --git a/engines/xeen/interface.h b/engines/xeen/interface.h
index 8497cc6..9634788 100644
--- a/engines/xeen/interface.h
+++ b/engines/xeen/interface.h
@@ -68,7 +68,6 @@ private:
 	bool _buttonsLoaded;
 	Common::String _interfaceText;
 	int _hiliteChar;
-	int _intrIndex1;
 	bool _flag1;
 	int _animCounter;
 	bool _isAnimReset;
@@ -110,6 +109,8 @@ private:
 
 	bool checkMoveDirection(int key);
 public:
+	int _intrIndex1;
+public:
 	Interface(XeenEngine *vm);
 
 	void setup();
diff --git a/engines/xeen/map.cpp b/engines/xeen/map.cpp
index bf03905..6554125 100644
--- a/engines/xeen/map.cpp
+++ b/engines/xeen/map.cpp
@@ -544,8 +544,8 @@ MazeData::MazeData() {
 	for (int y = 0; y < MAP_HEIGHT; ++y) {
 		for (int x = 0; x < MAP_WIDTH; ++x)
 			_wallData[y][x]._data = 0;
-		Common::fill(&_seenTiles[y][0], &_seenTiles[y][MAP_WIDTH], 0);
-		Common::fill(&_steppedOnTiles[y][0], &_steppedOnTiles[y][MAP_WIDTH], 0);
+		Common::fill(&_seenTiles[y][0], &_seenTiles[y][MAP_WIDTH], false);
+		Common::fill(&_steppedOnTiles[y][0], &_steppedOnTiles[y][MAP_WIDTH], false);
 		_wallTypes[y] = 0;
 		_surfaceTypes[y] = 0;
 	}
@@ -859,7 +859,6 @@ Map::Map(XeenEngine *vm) : _vm(vm), _mobData(vm) {
 	_sideMonsters = 0;
 	_sidePictures = 0;
 	_isOutdoors = false;
-	_stepped = false;
 	_mazeDataIndex = 0;
 	_currentSteppedOn = false;
 	_currentSurfaceId = 0;
@@ -886,7 +885,7 @@ void Map::load(int mapId) {
 		PleaseWait::show(_vm);
 	}
 
-	_stepped = true;
+	_vm->_party->_stepped = true;
 	_vm->_party->_mazeId = mapId;
 	_vm->_events->clearEvents();
 
diff --git a/engines/xeen/map.h b/engines/xeen/map.h
index 9b19b3a..80c46dd 100644
--- a/engines/xeen/map.h
+++ b/engines/xeen/map.h
@@ -361,7 +361,6 @@ private:
 	int _sidePictures;
 	int _sideObjects;
 	int _sideMonsters;
-	bool _stepped;
 	int _mazeDataIndex;
 
 	void loadEvents(int mapId);
diff --git a/engines/xeen/party.cpp b/engines/xeen/party.cpp
index 4571bbe..3736869 100644
--- a/engines/xeen/party.cpp
+++ b/engines/xeen/party.cpp
@@ -231,6 +231,7 @@ Party::Party(XeenEngine *vm): _vm(vm) {
 	_partyDead = false;
 	_newDay = false;
 	_isNight = false;
+	_stepped = false;
 }
 
 void Party::synchronize(Common::Serializer &s) {
@@ -543,5 +544,21 @@ void Party::resetTemps() {
 	_blessedActive = false;
 }
 
+void Party::handleLight() {
+	Map &map = *_vm->_map;
+
+	if (_stepped) {
+		map.cellFlagLookup(_mazePosition);
+		if (map._currentIsDrain && _lightCount)
+			--_lightCount;
+
+		if (checkSkill(CARTOGRAPHER)) {
+			map.mazeDataCurrent()._steppedOnTiles[_mazePosition.y & 15][_mazePosition.x & 15] = true;
+		}
+	}
+
+	_vm->_interface->_intrIndex1 = _lightCount || 
+		(map.mazeData()._mazeFlags2 & FLAG_IS_DARK) == 0 ? 4 : 0;
+}
 
 } // End of namespace Xeen
diff --git a/engines/xeen/party.h b/engines/xeen/party.h
index 8db52df..e2180e5 100644
--- a/engines/xeen/party.h
+++ b/engines/xeen/party.h
@@ -212,6 +212,7 @@ public:
 	bool _partyDead;
 	bool _newDay;
 	bool _isNight;
+	bool _stepped;
 public:
 	Party(XeenEngine *vm);
 
@@ -228,6 +229,8 @@ public:
 	void addTime(int numMinutes);
 
 	void resetTemps();
+
+	void handleLight();
 };
 
 } // End of namespace Xeen


Commit: 8b4d25d415bff87cfcc00fdf827139dda2fa4014
    https://github.com/scummvm/scummvm/commit/8b4d25d415bff87cfcc00fdf827139dda2fa4014
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-01-20T08:46:27-05:00

Commit Message:
XEEN: Implemented doStepCode

Changed paths:
    engines/xeen/combat.h
    engines/xeen/interface.cpp
    engines/xeen/interface.h
    engines/xeen/map.cpp
    engines/xeen/map.h
    engines/xeen/party.cpp
    engines/xeen/party.h
    engines/xeen/scripts.cpp
    engines/xeen/scripts.h
    engines/xeen/xeen.cpp
    engines/xeen/xeen.h



diff --git a/engines/xeen/combat.h b/engines/xeen/combat.h
index c64741b..8e54353 100644
--- a/engines/xeen/combat.h
+++ b/engines/xeen/combat.h
@@ -27,6 +27,24 @@
 
 namespace Xeen {
 
+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
+};
+
 class XeenEngine;
 
 class Combat {
diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp
index e117813..cd96f05 100644
--- a/engines/xeen/interface.cpp
+++ b/engines/xeen/interface.cpp
@@ -541,6 +541,7 @@ void Interface::draw3d(bool updateFlag) {
 	Combat &combat = *_vm->_combat;
 	EventsManager &events = *_vm->_events;
 	Map &map = *_vm->_map;
+	Party &party = *_vm->_party;
 	Screen &screen = *_vm->_screen;
 
 	if (screen._windows[11]._enabled)
@@ -724,11 +725,11 @@ void Interface::draw3d(bool updateFlag) {
 	animate3d();
 	drawMiniMap();
 
-	if (_vm->_falling == 1) {
+	if (party._falling == 1) {
 		error("TODO: Indoor falling");
 	}
 
-	if (_vm->_falling == 2) {
+	if (party._falling == 2) {
 		screen.saveBackground(1);
 	}
 
@@ -2940,6 +2941,72 @@ void Interface::stepTime() {
 }
 
 void Interface::doStepCode() {
+	Map &map = *_vm->_map;
+	Party &party = *_vm->_party;
+	int damage = 0;
+
+	party._stepped = true;
+	_upDoorText = false;
+
+	map.getCell(2);
+	int surfaceId = map.mazeData()._surfaceTypes[map._currentSurfaceId];
+
+	switch (surfaceId) {
+	case SURFTYPE_SPACE:
+		// Wheeze.. can't breathe in space! Explosive decompression, here we come 
+		party._partyDead = true;
+		break;
+	case SURFTYPE_LAVA:
+		// It burns, it burns! 
+		damage = 100;
+		party._damageType = DT_FIRE;
+		break;
+	case SURFTYPE_SKY:
+		// We can fly, we can.. oh wait, we can't!
+		damage = 100;
+		party._damageType = DT_PHYSICAL;
+		party._falling = true;
+		break;
+	case SURFTYPE_DESERT:
+		// Without navigation skills, simulate getting lost by adding extra time
+		if (map._isOutdoors && !party.checkSkill(NAVIGATOR))
+			party.addTime(170);
+		break;
+	case SURFTYPE_CLOUD:
+		if (!party._levitateActive) {
+			party._damageType = DT_PHYSICAL;
+			party._falling = true;
+			damage = 100;
+		}
+		break;
+	default:
+		break;
+	}
+
+	if (_vm->_files->_isDarkCc && party._gameFlags[374]) {
+		party._falling = false;
+	} else {
+		if (party._falling)
+			doFalling();
+
+		if ((party._mazePosition.x & 16) || (party._mazePosition.y & 16)) {
+			map.getNewMaze();
+		}
+
+		if (damage) {
+			_flipGround = !_flipGround;
+			draw3d(true);
+
+			warning("TODO: apply damage");
+
+			_flipGround = !_flipGround;
+		} else if (party._partyDead) {
+			draw3d(true);
+		}
+	}
+}
+
+void Interface::doFalling() {
 	// TODO
 }
 
diff --git a/engines/xeen/interface.h b/engines/xeen/interface.h
index 9634788..4cd40b9 100644
--- a/engines/xeen/interface.h
+++ b/engines/xeen/interface.h
@@ -129,6 +129,8 @@ public:
 
 	void charIconsPrint(bool updateFlag);
 
+	void doFalling();
+
 	void perform();
 };
 
diff --git a/engines/xeen/map.cpp b/engines/xeen/map.cpp
index 6554125..7e1f854 100644
--- a/engines/xeen/map.cpp
+++ b/engines/xeen/map.cpp
@@ -877,7 +877,7 @@ void Map::load(int mapId) {
 	IndoorDrawList &indoorList = _vm->_interface->_indoorList;
 	OutdoorDrawList &outdoorList = _vm->_interface->_outdoorList;
 
-	if (_vm->_falling) {
+	if (_vm->_party->_falling) {
 		Window &w = screen._windows[9];
 		w.open();
 		w.writeString(OOPS);
@@ -1500,4 +1500,8 @@ void Map::loadSky() {
 		? "sky.sky" : "night.sky");
 }
 
+void Map::getNewMaze() {
+	// TODO
+}
+
 } // End of namespace Xeen
diff --git a/engines/xeen/map.h b/engines/xeen/map.h
index 80c46dd..3241825 100644
--- a/engines/xeen/map.h
+++ b/engines/xeen/map.h
@@ -26,6 +26,7 @@
 #include "common/stream.h"
 #include "common/array.h"
 #include "common/rect.h"
+#include "xeen/combat.h"
 #include "xeen/party.h"
 #include "xeen/scripts.h"
 #include "xeen/sprites.h"
@@ -39,24 +40,6 @@ namespace Xeen {
 
 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,
@@ -407,6 +390,8 @@ public:
 	MazeData mazeDataCurrent() { return _mazeData[_mazeDataIndex]; }
 
 	void loadSky();
+
+	void getNewMaze();
 };
 
 } // End of namespace Xeen
diff --git a/engines/xeen/party.cpp b/engines/xeen/party.cpp
index 3736869..d465cc9 100644
--- a/engines/xeen/party.cpp
+++ b/engines/xeen/party.cpp
@@ -232,6 +232,8 @@ Party::Party(XeenEngine *vm): _vm(vm) {
 	_newDay = false;
 	_isNight = false;
 	_stepped = false;
+	_damageType = DT_PHYSICAL;
+	_falling = false;
 }
 
 void Party::synchronize(Common::Serializer &s) {
diff --git a/engines/xeen/party.h b/engines/xeen/party.h
index e2180e5..c598e8c 100644
--- a/engines/xeen/party.h
+++ b/engines/xeen/party.h
@@ -27,6 +27,7 @@
 #include "common/array.h"
 #include "common/rect.h"
 #include "common/serializer.h"
+#include "xeen/combat.h"
 #include "xeen/items.h"
 
 namespace Xeen {
@@ -213,6 +214,8 @@ public:
 	bool _newDay;
 	bool _isNight;
 	bool _stepped;
+	int _falling;
+	DamageType _damageType;
 public:
 	Party(XeenEngine *vm);
 
diff --git a/engines/xeen/scripts.cpp b/engines/xeen/scripts.cpp
index 5a36a32..55388ec 100644
--- a/engines/xeen/scripts.cpp
+++ b/engines/xeen/scripts.cpp
@@ -21,6 +21,7 @@
  */
 
 #include "xeen/scripts.h"
+#include "xeen/party.h"
 
 namespace Xeen {
 
diff --git a/engines/xeen/scripts.h b/engines/xeen/scripts.h
index 4f49018..9974892 100644
--- a/engines/xeen/scripts.h
+++ b/engines/xeen/scripts.h
@@ -27,7 +27,6 @@
 #include "common/system.h"
 #include "common/serializer.h"
 #include "xeen/files.h"
-#include "xeen/party.h"
 
 namespace Xeen {
 
diff --git a/engines/xeen/xeen.cpp b/engines/xeen/xeen.cpp
index e9b4d93..38026d0 100644
--- a/engines/xeen/xeen.cpp
+++ b/engines/xeen/xeen.cpp
@@ -53,7 +53,6 @@ XeenEngine::XeenEngine(OSystem *syst, const XeenGameDescription *gameDesc)
 	_face1State = 0;
 	_face2State = 0;
 	_noDirectionSense = false;
-	_falling = 0;
 	_moveMonsters = false;
 	_mode = MODE_0;
 	_openDoor = 0;
diff --git a/engines/xeen/xeen.h b/engines/xeen/xeen.h
index 59816b0..3e86374 100644
--- a/engines/xeen/xeen.h
+++ b/engines/xeen/xeen.h
@@ -148,7 +148,6 @@ public:
 	int _face1State;
 	int _face2State;
 	bool _noDirectionSense;
-	int _falling;
 	bool _moveMonsters;
 	int _openDoor;
 public:


Commit: 5cc3afab7293cdaf2ce339f2527da7ce5ed804fc
    https://github.com/scummvm/scummvm/commit/5cc3afab7293cdaf2ce339f2527da7ce5ed804fc
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-01-20T19:48:44-05:00

Commit Message:
XEEN: Implemented getNewMaze

Changed paths:
    engines/xeen/map.cpp



diff --git a/engines/xeen/map.cpp b/engines/xeen/map.cpp
index 7e1f854..6b577eb 100644
--- a/engines/xeen/map.cpp
+++ b/engines/xeen/map.cpp
@@ -1501,7 +1501,54 @@ void Map::loadSky() {
 }
 
 void Map::getNewMaze() {
-	// TODO
+	Party &party = *_vm->_party;
+	Common::Point pt = party._mazePosition;
+	int mapId = party._mazeId;
+
+	// Get the correct map to use from the cached list
+	_mazeDataIndex = 0;
+	while (_mazeData[_mazeDataIndex]._mazeId == mapId)
+		++_mazeDataIndex;
+
+	// Adjust Y and X to be in the 0-15 range, and on the correct surrounding
+	// map if either value is < 0 or >= 16
+	if (pt.y & 16) {
+		if (pt.y >= 0) {
+			pt.y -= 16;
+			mapId = _mazeData[_mazeDataIndex]._surroundingMazes._north;
+		} else {
+			pt.y += 16;
+			mapId = _mazeData[_mazeDataIndex]._surroundingMazes._south;
+		}
+
+		if (mapId) {
+			_mazeDataIndex = 0;
+			while (_mazeData[_mazeDataIndex]._mazeId == mapId)
+				++_mazeDataIndex;
+		}
+	}
+
+	if (pt.x & 16) {
+		if (pt.x >= 0) {
+			pt.x -= 16;
+			mapId = _mazeData[_mazeDataIndex]._surroundingMazes._east;
+		} else {
+			pt.x += 16;
+			mapId = _mazeData[_mazeDataIndex]._surroundingMazes._west;
+		}
+
+		if (mapId) {
+			_mazeDataIndex = 0;
+			while (_mazeData[_mazeDataIndex]._mazeId == mapId)
+				++_mazeDataIndex;
+		}
+	}
+
+	// Save the adjusted (0,0)-(15,15) position and load the given map.
+	// This will make it the new center, with it's own surrounding mazees loaded
+	party._mazePosition = pt;
+	if (mapId)
+		load(mapId);
 }
 
 } // End of namespace Xeen


Commit: 397a10eae5d63d148815386d782fd7b035c195fd
    https://github.com/scummvm/scummvm/commit/397a10eae5d63d148815386d782fd7b035c195fd
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-01-20T21:05:15-05:00

Commit Message:
XEEN: Moved setMazeBits to InterfaceMap and fixed some incorrect code in it

Changed paths:
    engines/xeen/interface.cpp
    engines/xeen/interface.h
    engines/xeen/interface_map.cpp
    engines/xeen/interface_map.h



diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp
index cd96f05..d2fea36 100644
--- a/engines/xeen/interface.cpp
+++ b/engines/xeen/interface.cpp
@@ -46,7 +46,6 @@ Interface::Interface(XeenEngine *vm) : ButtonContainer(), InterfaceMap(vm), _vm(
 	_animCounter = 0;
 	_isAnimReset = false;
 	_tillMove = 0;
-	_thinWall = false;
 	_overallFrame = 0;
 	_upDoorText = false;
 	_steppingFX = 0;
@@ -819,1503 +818,6 @@ void Interface::setMainButtons() {
 	addButton(Common::Rect(239, 47, 312, 57), Common::KEYCODE_3, &_iconSprites, false);
 }
 
-void Interface::setMazeBits() {
-	Common::fill(&_wo[0], &_wo[308], 0);
-
-	switch (_vm->_map->getCell(0) - 1) {
-	case 0:
-		++_wo[125];
-		break;
-	case 1:
-		++_wo[69];
-		break;
-	case 2:
-		++_wo[185];
-		break;
-	case 3:
-	case 12:
-		++_wo[105];
-		break;
-	case 4:
-	case 7:
-		++_wo[25];
-		break;
-	case 5:
-		++_wo[225];
-		break;
-	case 6:
-		++_wo[205];
-		break;
-	case 8:
-		++_wo[145];
-		break;
-	case 9:
-		++_wo[305];
-		break;
-	case 10:
-		++_wo[245];
-		break;
-	case 11:
-		++_wo[165];
-		break;
-	case 13:
-		++_wo[265];
-		break;
-	case 14:
-		++_wo[285];
-		break;
-	default:
-		break;
-	}
-
-	switch (_vm->_map->getCell(1) - 1) {
-	case 1:
-		++_wo[72];
-		break;
-	case 0:
-	case 2:
-	case 3:
-	case 4:
-	case 5:
-	case 6:
-	case 7:
-	case 8:
-	case 9:
-	case 10:
-	case 11:
-	case 12:
-	case 13:
-	case 14:
-		++_wo[28];
-		break;
-	default:
-		break;
-	}
-
-	switch (_vm->_map->getCell(2) - 1) {
-	case 0:
-		++_wo[127];
-		break;
-	case 1:
-		++_wo[71];
-		break;
-	case 2:
-		++_wo[187];
-		break;
-	case 3:
-	case 12:
-		++_wo[107];
-		break;
-	case 4:
-	case 7:
-		++_wo[27];
-		break;
-	case 5:
-		++_wo[227];
-		break;
-	case 6:
-		++_wo[207];
-		break;
-	case 8:
-		++_wo[147];
-		break;
-	case 9:
-		++_wo[307];
-		break;
-	case 10:
-		++_wo[247];
-		break;
-	case 11:
-		++_wo[167];
-		break;
-	case 13:
-		++_wo[267];
-		break;
-	case 14:
-		++_wo[287];
-		break;
-	default:
-		break;
-	}
-
-	_vm->_party->handleLight();
-
-	switch (_vm->_map->getCell(3) - 1) {
-	case 1:
-		++_wo[73];
-		break;
-	case 0:
-	case 2:
-	case 3:
-	case 4:
-	case 5:
-	case 6:
-	case 7:
-	case 8:
-	case 9:
-	case 10:
-	case 11:
-	case 12:
-	case 13:
-	case 14:
-		++_wo[29];
-		break;
-	default:
-		break;
-	}
-
-	switch (_vm->_map->getCell(4) - 1) {
-	case 0:
-		++_wo[126];
-		break;
-	case 1:
-		++_wo[70];
-		break;
-	case 2:
-		++_wo[186];
-		break;
-	case 3:
-	case 12:
-		++_wo[106];
-		break;
-	case 4:
-	case 7:
-		++_wo[26];
-		break;
-	case 5:
-		++_wo[226];
-		break;
-	case 6:
-		++_wo[206];
-	case 8:
-		++_wo[146];
-		break;
-	case 9:
-		++_wo[306];
-		break;
-	case 10:
-		++_wo[246];
-		break;
-		break;
-	case 11:
-		++_wo[166];
-		break;
-	case 13:
-		++_wo[266];
-		break;
-	case 14:
-		++_wo[286];
-		break;
-	default:
-		break;
-	}
-
-	switch (_vm->_map->getCell(5) - 1) {
-	case 0:
-		++_wo[122];
-		break;
-	case 1:
-		++_wo[64];
-		break;
-	case 2:
-		++_wo[182];
-		break;
-	case 3:
-	case 12:
-		++_wo[102];
-		break;
-	case 5:
-		++_wo[222];
-		break;
-	case 6:
-		++_wo[202];
-		break;
-	case 8:
-		++_wo[142];
-		break;
-	case 9:
-		++_wo[302];
-		break;
-	case 10:
-		++_wo[242];
-		break;
-	case 11:
-		++_wo[162];
-		break;
-	case 13:
-		++_wo[262];
-		break;
-	case 14:
-		++_wo[282];
-		break;
-	default:
-		break;
-	}
-
-	switch (_vm->_map->getCell(6) - 1) {
-	case 1:
-		++_wo[67];
-		break;
-	case 0:
-	case 2:
-	case 3:
-	case 4:
-	case 5:
-	case 6:
-	case 7:
-	case 8:
-	case 9:
-	case 10:
-	case 11:
-	case 12:
-	case 13:
-	case 14:
-		++_wo[23];
-		break;
-	default:
-		break;
-	}
-
-	switch (_vm->_map->getCell(7) - 1) {
-	case 0:
-		++_wo[124];
-		break;
-	case 1:
-		++_wo[66];
-		break;
-	case 2:
-		++_wo[184];
-		break;
-	case 3:
-	case 12:
-		++_wo[104];
-		break;
-	case 4:
-	case 7:
-		++_wo[22];
-		break;
-	case 5:
-		++_wo[224];
-		break;
-	case 6:
-		++_wo[204];
-		break;
-	case 8:
-		++_wo[144];
-		break;
-	case 9:
-		++_wo[304];
-		break;
-	case 10:
-		++_wo[244];
-		break;
-	case 11:
-		++_wo[164];
-		break;
-	case 13:
-		++_wo[264];
-		break;
-	case 14:
-		++_wo[284];
-		break;
-	default:
-		break;
-	}
-
-	_thinWall = (_vm->_map->_currentWall._data != INVALID_CELL) && _wo[27];
-
-	switch (_vm->_map->getCell(8) - 1) {
-	case 1:
-		++_wo[68];
-		break;
-	case 0:
-	case 2:
-	case 3:
-	case 4:
-	case 5:
-	case 6:
-	case 7:
-	case 8:
-	case 9:
-	case 10:
-	case 11:
-	case 12:
-	case 13:
-	case 14:
-		++_wo[24];
-		break;
-	default:
-		break;
-	}
-
-	switch (_vm->_map->getCell(9) - 1) {
-	case 0:
-		++_wo[123];
-		break;
-	case 1:
-		++_wo[65];
-		break;
-	case 2:
-		++_wo[183];
-		break;
-	case 3:
-	case 12:
-		++_wo[103];
-		break;
-	case 4:
-	case 7:
-		++_wo[21];
-		break;
-	case 5:
-		++_wo[223];
-		break;
-	case 6:
-		++_wo[203];
-		break;
-	case 8:
-		++_wo[143];
-		break;
-	case 9:
-		++_wo[3033];
-		break;
-	case 10:
-		++_wo[243];
-		break;
-	case 11:
-		++_wo[163];
-		break;
-	case 13:
-		++_wo[263];
-		break;
-	case 14:
-		++_wo[283];
-		break;
-	default:
-		break;
-	}
-
-	switch (_vm->_map->getCell(10) - 1) {
-	case 0:
-		++_wo[117];
-		break;
-	case 1:
-		++_wo[55];
-		break;
-	case 2:
-		++_wo[177];
-		break;
-	case 3:
-	case 12:
-		++_wo[97];
-		break;
-	case 4:
-	case 7:
-		++_wo[11];
-		break;
-	case 5:
-		++_wo[217];
-		break;
-	case 6:
-		++_wo[197];
-		break;
-	case 8:
-		++_wo[137];
-		break;
-	case 9:
-		++_wo[297];
-		break;
-	case 10:
-		++_wo[237];
-	case 11:
-		++_wo[157];
-		break;
-	case 13:
-		++_wo[257];
-		break;
-	case 14:
-		++_wo[277];
-		break;
-	default:
-		break;
-	}
-
-	switch (_vm->_map->getCell(11) - 1) {
-	case 1:
-		++_wo[60];
-		break;
-	case 0:
-	case 2:
-	case 3:
-	case 4:
-	case 5:
-	case 6:
-	case 7:
-	case 8:
-	case 9:
-	case 10:
-	case 11:
-	case 12:
-	case 13:
-	case 14:
-		++_wo[16];
-		break;
-	default:
-		break;
-	}
-
-	switch (_vm->_map->getCell(12) - 1) {
-	case 0:
-		++_wo[118];
-		break;
-	case 1:
-		++_wo[56];
-		break;
-	case 2:
-		++_wo[178];
-		break;
-	case 3:
-	case 12:
-		++_wo[98];
-		break;
-	case 4:
-	case 7:
-		++_wo[12];
-		break;
-	case 5:
-		++_wo[218];
-		break;
-	case 6:
-		++_wo[198];
-		break;
-	case 8:
-		++_wo[138];
-		break;
-	case 9:
-		++_wo[298];
-		break;
-	case 10:
-		++_wo[238];
-		break;
-	case 11:
-		++_wo[158];
-		break;
-	case 13:
-		++_wo[258];
-		break;
-	case 14:
-		++_wo[278];
-		break;
-	default:
-		break;
-	}
-
-	switch (_vm->_map->getCell(13) - 1) {
-	case 1:
-		++_wo[61];
-		break;
-	case 0:
-	case 2:
-	case 3:
-	case 4:
-	case 5:
-	case 6:
-	case 7:
-	case 8:
-	case 9:
-	case 10:
-	case 11:
-	case 12:
-	case 13:
-	case 14:
-		++_wo[17];
-		break;
-	default:
-		break;
-	}
-
-	switch (_vm->_map->getCell(14) - 1) {
-	case 0:
-		++_wo[121];
-		break;
-	case 1:
-		++_wo[59];
-		break;
-	case 2:
-		++_wo[181];
-		break;
-	case 3:
-	case 12:
-		++_wo[101];
-		break;
-	case 4:
-	case 7:
-		++_wo[15];
-		break;
-	case 5:
-		++_wo[221];
-		break;
-	case 6:
-		++_wo[201];
-		break;
-	case 8:
-		++_wo[141];
-		break;
-	case 9:
-		++_wo[301];
-		break;
-	case 10:
-		++_wo[241];
-		break;
-	case 11:
-		++_wo[161];
-		break;
-	case 13:
-		++_wo[261];
-		break;
-	case 14:
-		++_wo[281];
-		break;
-	default:
-		break;
-	}
-
-	switch (_vm->_map->getCell(15) - 1) {
-	case 1:
-		++_wo[63];
-		break;
-	case 0:
-	case 2:
-	case 3:
-	case 4:
-	case 5:
-	case 6:
-	case 7:
-	case 8:
-	case 9:
-	case 10:
-	case 11:
-	case 12:
-	case 13:
-	case 14:
-		++_wo[19];
-		break;
-	default:
-		break;
-	}
-
-	switch (_vm->_map->getCell(16) - 1) {
-	case 0:
-		++_wo[120];
-		break;
-	case 1:
-		++_wo[58];
-		break;
-	case 2:
-		++_wo[180];
-		break;
-	case 3:
-	case 12:
-		++_wo[100];
-		break;
-	case 4:
-	case 7:
-		++_wo[14];
-		break;
-	case 5:
-		++_wo[220];
-		break;
-	case 6:
-		++_wo[200];
-		break;
-	case 8:
-		++_wo[140];
-		break;
-	case 9:
-		++_wo[300];
-		break;
-	case 10:
-		++_wo[240];
-		break;
-	case 11:
-		++_wo[160];
-		break;
-	case 13:
-		++_wo[260];
-		break;
-	case 14:
-		++_wo[280];
-		break;
-	default:
-		break;
-	}
-
-	switch (_vm->_map->getCell(17) - 1) {
-	case 1:
-		++_wo[62];
-		break;
-	case 0:
-	case 2:
-	case 3:
-	case 4:
-	case 5:
-	case 6:
-	case 7:
-	case 8:
-	case 9:
-	case 10:
-	case 11:
-	case 12:
-	case 13:
-	case 14:
-		++_wo[18];
-		break;
-	default:
-		break;
-	}
-
-	switch (_vm->_map->getCell(18) - 1) {
-	case 0:
-		++_wo[119];
-		break;
-	case 1:
-		++_wo[57];
-		break;
-	case 2:
-		++_wo[179];
-		break;
-	case 3:
-	case 12:
-		++_wo[99];
-		break;
-	case 4:
-	case 7:
-		++_wo[13];
-		break;
-	case 5:
-		++_wo[219];
-		break;
-	case 6:
-		++_wo[199];
-		break;
-	case 8:
-		++_wo[139];
-		break;
-	case 9:
-		++_wo[299];
-		break;
-	case 10:
-		++_wo[239];
-		break;
-	case 11:
-		++_wo[159];
-		break;
-	case 13:
-		++_wo[259];
-		break;
-	case 14:
-		++_wo[279];
-		break;
-	default:
-		break;
-	}
-
-	switch (_vm->_map->getCell(19) - 1) {
-	case 0:
-		++_wo[108];
-		break;
-	case 1:
-		++_wo[78];
-		break;
-	case 2:
-		++_wo[168];
-	case 3:
-	case 12:
-		++_wo[88];
-		break;
-	case 4:
-	case 7:
-		++_wo[34];
-		break;
-	case 5:
-		++_wo[208];
-		break;
-	case 6:
-		++_wo[188];
-		break;
-	case 8:
-		++_wo[128];
-		break;
-	case 9:
-		++_wo[288];
-		break;
-	case 10:
-		++_wo[228];
-		break;
-	case 11:
-		++_wo[148];
-		break;
-	case 13:
-		++_wo[248];
-		break;
-	case 14:
-		++_wo[268];
-		break;
-	default:
-		break;
-	}
-
-	switch (_vm->_map->getCell(20) - 1) {
-	case 1:
-		++_wo[76];
-		break;
-	case 0:
-	case 2:
-	case 3:
-	case 4:
-	case 5:
-	case 6:
-	case 7:
-	case 8:
-	case 9:
-	case 10:
-	case 11:
-	case 12:
-	case 13:
-	case 14:
-		++_wo[32];
-		break;
-	default:
-		break;
-	}
-
-	switch (_vm->_map->getCell(21) - 1) {
-	case 0:
-		++_wo[109];
-		break;
-	case 1:
-		++_wo[44];
-		break;
-	case 2:
-		++_wo[169];
-		break;
-	case 3:
-	case 12:
-		++_wo[89];
-		break;
-	case 4:
-	case 7:
-		++_wo[0];
-		break;
-	case 5:
-		++_wo[209];
-		break;
-	case 6:
-		++_wo[189];
-		break;
-	case 8:
-		++_wo[129];
-		break;
-	case 9:
-		++_wo[289];
-		break;
-	case 10:
-		++_wo[229];
-		break;
-	case 11:
-		++_wo[149];
-		break;
-	case 13:
-		++_wo[249];
-		break;
-	case 14:
-		++_wo[269];
-		break;
-	default:
-		break;
-	}
-
-	switch (_vm->_map->getCell(22) - 1) {
-	case 1:
-		++_wo[74];
-		break;
-	case 0:
-	case 2:
-	case 3:
-	case 4:
-	case 5:
-	case 6:
-	case 7:
-	case 8:
-	case 9:
-	case 10:
-	case 11:
-	case 12:
-	case 13:
-	case 14:
-		++_wo[30];
-		break;
-	default:
-		break;
-	}
-
-	switch (_vm->_map->getCell(23) - 1) {
-	case 0:
-		++_wo[110];
-		break;
-	case 1:
-		++_wo[45];
-		break;
-	case 2:
-		++_wo[170];
-		break;
-	case 3:
-	case 12:
-		++_wo[90];
-		break;
-	case 4:
-	case 7:
-		++_wo[1];
-		break;
-	case 5:
-		++_wo[210];
-		break;
-	case 6:
-		++_wo[190];
-		break;
-	case 8:
-		++_wo[130];
-		break;
-	case 9:
-		++_wo[290];
-		break;
-	case 10:
-		++_wo[230];
-		break;
-	case 11:
-		++_wo[150];
-		break;
-	case 13:
-		++_wo[250];
-		break;
-	case 14:
-		++_wo[270];
-		break;
-	default:
-		break;
-	}
-
-	switch (_vm->_map->getCell(24) - 1) {
-	case 1:
-		++_wo[52];
-		break;
-	case 0:
-	case 2:
-	case 3:
-	case 4:
-	case 5:
-	case 6:
-	case 7:
-	case 8:
-	case 9:
-	case 10:
-	case 11:
-	case 12:
-	case 13:
-	case 14:
-		++_wo[8];
-		break;
-	default:
-		break;
-	}
-
-	switch (_vm->_map->getCell(25) - 1) {
-	case 0:
-		++_wo[111];
-		break;
-	case 1:
-		++_wo[46];
-		break;
-	case 2:
-		++_wo[171];
-		break;
-	case 3:
-	case 12:
-		++_wo[91];
-		break;
-	case 4:
-	case 7:
-		++_wo[2];
-		break;
-	case 5:
-		++_wo[211];
-		break;
-	case 6:
-		++_wo[191];
-		break;
-	case 8:
-		++_wo[131];
-		break;
-	case 9:
-		++_wo[291];
-		break;
-	case 10:
-		++_wo[231];
-		break;
-	case 11:
-		++_wo[151];
-		break;
-	case 13:
-		++_wo[251];
-		break;
-	case 14:
-		++_wo[271];
-		break;
-	default:
-		break;
-	}
-
-	switch (_vm->_map->getCell(26) - 1) {
-	case 1:
-		++_wo[51];
-		break;
-	case 0:
-	case 2:
-	case 3:
-	case 4:
-	case 5:
-	case 6:
-	case 7:
-	case 8:
-	case 9:
-	case 10:
-	case 11:
-	case 12:
-	case 13:
-	case 14:
-		++_wo[7];
-		break;
-	default:
-		break;
-	}
-
-	switch (_vm->_map->getCell(27) - 1) {
-	case 0:
-		++_wo[116];
-		break;
-	case 1:
-		++_wo[50];
-		break;
-	case 2:
-		++_wo[176];
-		break;
-	case 3:
-	case 12:
-		++_wo[96];
-		break;
-	case 4:
-	case 7:
-		++_wo[6];
-		break;
-	case 5:
-		++_wo[216];
-		break;
-	case 6:
-		++_wo[196];
-		break;
-	case 8:
-		++_wo[136];
-		break;
-	case 9:
-		++_wo[296];
-		break;
-	case 10:
-		++_wo[236];
-		break;
-	case 11:
-		++_wo[156];
-		break;
-	case 13:
-		++_wo[256];
-		break;
-	case 14:
-		++_wo[276];
-		break;
-	default:
-		break;
-	}
-
-	switch (_vm->_map->getCell(28) - 1) {
-	case 1:
-		++_wo[53];
-		break;
-	case 0:
-	case 2:
-	case 3:
-	case 4:
-	case 5:
-	case 6:
-	case 7:
-	case 8:
-	case 9:
-	case 10:
-	case 11:
-	case 12:
-	case 13:
-	case 14:
-		++_wo[9];
-		break;
-	default:
-		break;
-	}
-
-	switch (_vm->_map->getCell(29) - 1) {
-	case 0:
-		++_wo[115];
-		break;
-	case 1:
-		++_wo[49];
-		break;
-	case 2:
-		++_wo[175];
-		break;
-	case 3:
-	case 12:
-		++_wo[95];
-		break;
-	case 4:
-	case 7:
-		++_wo[5];
-		break;
-	case 5:
-		++_wo[215];
-		break;
-	case 6:
-		++_wo[195];
-		break;
-	case 8:
-		++_wo[135];
-		break;
-	case 9:
-		++_wo[295];
-		break;
-	case 10:
-		++_wo[235];
-		break;
-	case 11:
-		++_wo[155];
-		break;
-	case 13:
-		++_wo[255];
-		break;
-	case 14:
-		++_wo[275];
-		break;
-	default:
-		break;
-	}
-
-	switch (_vm->_map->getCell(30) - 1) {
-	case 1:
-		++_wo[54];
-		break;
-	case 0:
-	case 2:
-	case 3:
-	case 4:
-	case 5:
-	case 6:
-	case 7:
-	case 8:
-	case 9:
-	case 10:
-	case 11:
-	case 12:
-	case 13:
-	case 14:
-		++_wo[10];
-		break;
-	default:
-		break;
-	}
-
-	switch (_vm->_map->getCell(31) - 1) {
-	case 0:
-		++_wo[114];
-		break;
-	case 1:
-		++_wo[48];
-		break;
-	case 2:
-		++_wo[174];
-		break;
-	case 3:
-	case 12:
-		++_wo[94];
-		break;
-	case 4:
-		++_wo[4];
-		break;
-	case 5:
-		++_wo[214];
-		break;
-	case 6:
-		++_wo[194];
-		break;
-	case 8:
-		++_wo[134];
-		break;
-	case 9:
-		++_wo[294];
-		break;
-	case 10:
-		++_wo[234];
-		break;
-	case 11:
-		++_wo[154];
-		break;
-	case 13:
-		++_wo[254];
-		break;
-	case 14:
-		++_wo[274];
-		break;
-	default:
-		break;
-	}
-
-	switch (_vm->_map->getCell(32) - 1) {
-	case 1:
-		++_wo[75];
-		break;
-	case 0:
-	case 2:
-	case 3:
-	case 4:
-	case 5:
-	case 6:
-	case 7:
-	case 8:
-	case 9:
-	case 10:
-	case 11:
-	case 12:
-	case 13:
-	case 14:
-		++_wo[31];
-		break;
-	default:
-		break;
-	}
-
-	switch (_vm->_map->getCell(33) - 1) {
-	case 0:
-		++_wo[112];
-		break;
-	case 1:
-		++_wo[47];
-		break;
-	case 2:
-		++_wo[172];
-		break;
-	case 3:
-	case 12:
-		++_wo[92];
-		break;
-	case 4:
-	case 7:
-		++_wo[3];
-		break;
-	case 5:
-		++_wo[212];
-		break;
-	case 6:
-		++_wo[192];
-		break;
-	case 8:
-		++_wo[132];
-		break;
-	case 9:
-		++_wo[292];
-		break;
-	case 10:
-		++_wo[232];
-		break;
-	case 11:
-		++_wo[152];
-		break;
-	case 13:
-		++_wo[252];
-		break;
-	case 14:
-		++_wo[272];
-		break;
-	default:
-		break;
-	}
-
-	switch (_vm->_map->getCell(34) - 1) {
-	case 1:
-		++_wo[77];
-		break;
-	case 0:
-	case 2:
-	case 3:
-	case 4:
-	case 5:
-	case 6:
-	case 7:
-	case 8:
-	case 9:
-	case 10:
-	case 11:
-	case 12:
-	case 13:
-	case 14:
-		++_wo[33];
-		break;
-	default:
-		break;
-	}
-
-	switch (_vm->_map->getCell(35) - 1) {
-	case 0:
-		++_wo[113];
-		break;
-	case 1:
-		++_wo[79];
-		break;
-	case 2:
-		++_wo[173];
-		break;
-	case 3:
-	case 12:
-		++_wo[93];
-		break;
-	case 4:
-	case 7:
-		++_wo[35];
-		break;
-	case 5:
-		++_wo[213];
-		break;
-	case 6:
-		++_wo[193];
-		break;
-	case 8:
-		++_wo[133];
-		break;
-	case 9:
-		++_wo[293];
-		break;
-	case 10:
-		++_wo[233];
-		break;
-	case 11:
-		++_wo[153];
-		break;
-	case 13:
-		++_wo[253];
-		break;
-	case 14:
-		++_wo[273];
-		break;
-	default:
-		break;
-	}
-
-	switch (_vm->_map->getCell(36) - 1) {
-	case 1:
-		++_wo[83];
-		break;
-	case 0:
-	case 2:
-	case 3:
-	case 4:
-	case 5:
-	case 6:
-	case 7:
-	case 8:
-	case 9:
-	case 10:
-	case 11:
-	case 12:
-	case 13:
-	case 14:
-		++_wo[39];
-		break;
-	default:
-		break;
-	}
-
-	switch (_vm->_map->getCell(37) - 1) {
-	case 1:
-		++_wo[82];
-		break;
-	case 0:
-	case 2:
-	case 3:
-	case 4:
-	case 5:
-	case 6:
-	case 7:
-	case 8:
-	case 9:
-	case 10:
-	case 11:
-	case 12:
-	case 13:
-	case 14:
-		++_wo[38];
-		break;
-	default:
-		break;
-	}
-
-	switch (_vm->_map->getCell(38) - 1) {
-	case 1:
-		++_wo[81];
-		break;
-	case 0:
-	case 2:
-	case 3:
-	case 4:
-	case 5:
-	case 6:
-	case 7:
-	case 8:
-	case 9:
-	case 10:
-	case 11:
-	case 12:
-	case 13:
-	case 14:
-		++_wo[37];
-		break;
-	default:
-		break;
-	}
-
-	switch (_vm->_map->getCell(34) - 1) {
-	case 1:
-		++_wo[80];
-		break;
-	case 0:
-	case 2:
-	case 3:
-	case 4:
-	case 5:
-	case 6:
-	case 7:
-	case 8:
-	case 9:
-	case 10:
-	case 11:
-	case 12:
-	case 13:
-	case 14:
-		++_wo[36];
-		break;
-	default:
-		break;
-	}
-
-	switch (_vm->_map->getCell(40) - 1) {
-	case 1:
-		++_wo[84];
-		break;
-	case 0:
-	case 2:
-	case 3:
-	case 4:
-	case 5:
-	case 6:
-	case 7:
-	case 8:
-	case 9:
-	case 10:
-	case 11:
-	case 12:
-	case 13:
-	case 14:
-		++_wo[40];
-		break;
-	default:
-		break;
-	}
-
-	switch (_vm->_map->getCell(41) - 1) {
-	case 1:
-		++_wo[85];
-		break;
-	case 0:
-	case 2:
-	case 3:
-	case 4:
-	case 5:
-	case 6:
-	case 7:
-	case 8:
-	case 9:
-	case 10:
-	case 11:
-	case 12:
-	case 13:
-	case 14:
-		++_wo[41];
-		break;
-	default:
-		break;
-	}
-
-	switch (_vm->_map->getCell(42) - 1) {
-	case 1:
-		++_wo[86];
-		break;
-	case 0:
-	case 2:
-	case 3:
-	case 4:
-	case 5:
-	case 6:
-	case 7:
-	case 8:
-	case 9:
-	case 10:
-	case 11:
-	case 12:
-	case 13:
-	case 14:
-		++_wo[42];
-		break;
-	default:
-		break;
-	}
-
-	switch (_vm->_map->getCell(43) - 1) {
-	case 1:
-		++_wo[87];
-		break;
-	case 0:
-	case 2:
-	case 3:
-	case 4:
-	case 5:
-	case 6:
-	case 7:
-	case 8:
-	case 9:
-	case 10:
-	case 11:
-	case 12:
-	case 13:
-	case 14:
-		++_wo[43];
-		break;
-	default:
-		break;
-	}
-}
-
 void Interface::drawMiniMap() {
 	Map &map = *_vm->_map;
 	Party &party = *_vm->_party;
@@ -2990,7 +1492,8 @@ void Interface::doStepCode() {
 			doFalling();
 
 		if ((party._mazePosition.x & 16) || (party._mazePosition.y & 16)) {
-			map.getNewMaze();
+			if (map._isOutdoors)
+				map.getNewMaze();
 		}
 
 		if (damage) {
diff --git a/engines/xeen/interface.h b/engines/xeen/interface.h
index 4cd40b9..93c861e 100644
--- a/engines/xeen/interface.h
+++ b/engines/xeen/interface.h
@@ -72,7 +72,6 @@ private:
 	int _animCounter;
 	bool _isAnimReset;
 	byte _tillMove;
-	bool _thinWall;
 	int _overallFrame;
 	bool _upDoorText;
 	int _steppingFX;
@@ -97,8 +96,6 @@ private:
 
 	void setMainButtons();
 
-	void setMazeBits();
-
 	void drawMiniMap();
 
 	void chargeStep();
diff --git a/engines/xeen/interface_map.cpp b/engines/xeen/interface_map.cpp
index 5b1d4e9..c551e58 100644
--- a/engines/xeen/interface_map.cpp
+++ b/engines/xeen/interface_map.cpp
@@ -373,6 +373,1510 @@ InterfaceMap::InterfaceMap(XeenEngine *vm): _vm(vm) {
 	_charsShooting = false;
 	_objNumber = 0;
 	_combatFloatCounter = 0;
+	_thinWall = false;
+}
+
+
+void InterfaceMap::setMazeBits() {
+	Common::fill(&_wo[0], &_wo[308], 0);
+
+	switch (_vm->_map->getCell(0) - 1) {
+	case 0:
+		++_wo[125];
+		break;
+	case 1:
+		++_wo[69];
+		break;
+	case 2:
+		++_wo[185];
+		break;
+	case 3:
+	case 12:
+		++_wo[105];
+		break;
+	case 4:
+	case 7:
+		++_wo[25];
+		break;
+	case 5:
+		++_wo[225];
+		break;
+	case 6:
+		++_wo[205];
+		break;
+	case 8:
+		++_wo[145];
+		break;
+	case 9:
+		++_wo[305];
+		break;
+	case 10:
+		++_wo[245];
+		break;
+	case 11:
+		++_wo[165];
+		break;
+	case 13:
+		++_wo[265];
+		break;
+	case 14:
+		++_wo[285];
+		break;
+	default:
+		break;
+	}
+
+	switch (_vm->_map->getCell(1) - 1) {
+	case 1:
+		++_wo[72];
+		break;
+	case 0:
+	case 2:
+	case 3:
+	case 4:
+	case 5:
+	case 6:
+	case 7:
+	case 8:
+	case 9:
+	case 10:
+	case 11:
+	case 12:
+	case 13:
+	case 14:
+		++_wo[28];
+		break;
+	default:
+		break;
+	}
+
+	switch (_vm->_map->getCell(2) - 1) {
+	case 0:
+		++_wo[127];
+		break;
+	case 1:
+		++_wo[71];
+		break;
+	case 2:
+		++_wo[187];
+		break;
+	case 3:
+	case 12:
+		++_wo[107];
+		break;
+	case 4:
+	case 7:
+		++_wo[27];
+		break;
+	case 5:
+		++_wo[227];
+		break;
+	case 6:
+		++_wo[207];
+		break;
+	case 8:
+		++_wo[147];
+		break;
+	case 9:
+		++_wo[307];
+		break;
+	case 10:
+		++_wo[247];
+		break;
+	case 11:
+		++_wo[167];
+		break;
+	case 13:
+		++_wo[267];
+		break;
+	case 14:
+		++_wo[287];
+		break;
+	default:
+		break;
+	}
+
+	_vm->_party->handleLight();
+
+	switch (_vm->_map->getCell(3) - 1) {
+	case 1:
+		++_wo[73];
+		break;
+	case 0:
+	case 2:
+	case 3:
+	case 4:
+	case 5:
+	case 6:
+	case 7:
+	case 8:
+	case 9:
+	case 10:
+	case 11:
+	case 12:
+	case 13:
+	case 14:
+		++_wo[29];
+		break;
+	default:
+		break;
+	}
+
+	switch (_vm->_map->getCell(4) - 1) {
+	case 0:
+		++_wo[126];
+		break;
+	case 1:
+		++_wo[70];
+		break;
+	case 2:
+		++_wo[186];
+		break;
+	case 3:
+	case 12:
+		++_wo[106];
+		break;
+	case 4:
+	case 7:
+		++_wo[26];
+		break;
+	case 5:
+		++_wo[226];
+		break;
+	case 6:
+		++_wo[206];
+	case 8:
+		++_wo[146];
+		break;
+	case 9:
+		++_wo[306];
+		break;
+	case 10:
+		++_wo[246];
+		break;
+		break;
+	case 11:
+		++_wo[166];
+		break;
+	case 13:
+		++_wo[266];
+		break;
+	case 14:
+		++_wo[286];
+		break;
+	default:
+		break;
+	}
+
+	switch (_vm->_map->getCell(5) - 1) {
+	case 0:
+		++_wo[122];
+		break;
+	case 1:
+		++_wo[64];
+		break;
+	case 2:
+		++_wo[182];
+		break;
+	case 3:
+	case 12:
+		++_wo[102];
+		break;
+	case 4:
+	case 7:
+		++_wo[20];
+		break;
+	case 5:
+		++_wo[222];
+		break;
+	case 6:
+		++_wo[202];
+		break;
+	case 8:
+		++_wo[142];
+		break;
+	case 9:
+		++_wo[302];
+		break;
+	case 10:
+		++_wo[242];
+		break;
+	case 11:
+		++_wo[162];
+		break;
+	case 13:
+		++_wo[262];
+		break;
+	case 14:
+		++_wo[282];
+		break;
+	default:
+		break;
+	}
+
+	switch (_vm->_map->getCell(6) - 1) {
+	case 1:
+		++_wo[67];
+		break;
+	case 0:
+	case 2:
+	case 3:
+	case 4:
+	case 5:
+	case 6:
+	case 7:
+	case 8:
+	case 9:
+	case 10:
+	case 11:
+	case 12:
+	case 13:
+	case 14:
+		++_wo[23];
+		break;
+	default:
+		break;
+	}
+
+	switch (_vm->_map->getCell(7) - 1) {
+	case 0:
+		++_wo[124];
+		break;
+	case 1:
+		++_wo[66];
+		break;
+	case 2:
+		++_wo[184];
+		break;
+	case 3:
+	case 12:
+		++_wo[104];
+		break;
+	case 4:
+	case 7:
+		++_wo[22];
+		break;
+	case 5:
+		++_wo[224];
+		break;
+	case 6:
+		++_wo[204];
+		break;
+	case 8:
+		++_wo[144];
+		break;
+	case 9:
+		++_wo[304];
+		break;
+	case 10:
+		++_wo[244];
+		break;
+	case 11:
+		++_wo[164];
+		break;
+	case 13:
+		++_wo[264];
+		break;
+	case 14:
+		++_wo[284];
+		break;
+	default:
+		break;
+	}
+
+	_thinWall = (_vm->_map->_currentWall._data != INVALID_CELL) && _wo[27];
+
+	switch (_vm->_map->getCell(8) - 1) {
+	case 1:
+		++_wo[68];
+		break;
+	case 0:
+	case 2:
+	case 3:
+	case 4:
+	case 5:
+	case 6:
+	case 7:
+	case 8:
+	case 9:
+	case 10:
+	case 11:
+	case 12:
+	case 13:
+	case 14:
+		++_wo[24];
+		break;
+	default:
+		break;
+	}
+
+	switch (_vm->_map->getCell(9) - 1) {
+	case 0:
+		++_wo[123];
+		break;
+	case 1:
+		++_wo[65];
+		break;
+	case 2:
+		++_wo[183];
+		break;
+	case 3:
+	case 12:
+		++_wo[103];
+		break;
+	case 4:
+	case 7:
+		++_wo[21];
+		break;
+	case 5:
+		++_wo[223];
+		break;
+	case 6:
+		++_wo[203];
+		break;
+	case 8:
+		++_wo[143];
+		break;
+	case 9:
+		++_wo[3033];
+		break;
+	case 10:
+		++_wo[243];
+		break;
+	case 11:
+		++_wo[163];
+		break;
+	case 13:
+		++_wo[263];
+		break;
+	case 14:
+		++_wo[283];
+		break;
+	default:
+		break;
+	}
+
+	switch (_vm->_map->getCell(10) - 1) {
+	case 0:
+		++_wo[117];
+		break;
+	case 1:
+		++_wo[55];
+		break;
+	case 2:
+		++_wo[177];
+		break;
+	case 3:
+	case 12:
+		++_wo[97];
+		break;
+	case 4:
+	case 7:
+		++_wo[11];
+		break;
+	case 5:
+		++_wo[217];
+		break;
+	case 6:
+		++_wo[197];
+		break;
+	case 8:
+		++_wo[137];
+		break;
+	case 9:
+		++_wo[297];
+		break;
+	case 10:
+		++_wo[237];
+	case 11:
+		++_wo[157];
+		break;
+	case 13:
+		++_wo[257];
+		break;
+	case 14:
+		++_wo[277];
+		break;
+	default:
+		break;
+	}
+
+	switch (_vm->_map->getCell(11) - 1) {
+	case 1:
+		++_wo[60];
+		break;
+	case 0:
+	case 2:
+	case 3:
+	case 4:
+	case 5:
+	case 6:
+	case 7:
+	case 8:
+	case 9:
+	case 10:
+	case 11:
+	case 12:
+	case 13:
+	case 14:
+		++_wo[16];
+		break;
+	default:
+		break;
+	}
+
+	switch (_vm->_map->getCell(12) - 1) {
+	case 0:
+		++_wo[118];
+		break;
+	case 1:
+		++_wo[56];
+		break;
+	case 2:
+		++_wo[178];
+		break;
+	case 3:
+	case 12:
+		++_wo[98];
+		break;
+	case 4:
+	case 7:
+		++_wo[12];
+		break;
+	case 5:
+		++_wo[218];
+		break;
+	case 6:
+		++_wo[198];
+		break;
+	case 8:
+		++_wo[138];
+		break;
+	case 9:
+		++_wo[298];
+		break;
+	case 10:
+		++_wo[238];
+		break;
+	case 11:
+		++_wo[158];
+		break;
+	case 13:
+		++_wo[258];
+		break;
+	case 14:
+		++_wo[278];
+		break;
+	default:
+		break;
+	}
+
+	switch (_vm->_map->getCell(13) - 1) {
+	case 1:
+		++_wo[61];
+		break;
+	case 0:
+	case 2:
+	case 3:
+	case 4:
+	case 5:
+	case 6:
+	case 7:
+	case 8:
+	case 9:
+	case 10:
+	case 11:
+	case 12:
+	case 13:
+	case 14:
+		++_wo[17];
+		break;
+	default:
+		break;
+	}
+
+	switch (_vm->_map->getCell(14) - 1) {
+	case 0:
+		++_wo[121];
+		break;
+	case 1:
+		++_wo[59];
+		break;
+	case 2:
+		++_wo[181];
+		break;
+	case 3:
+	case 12:
+		++_wo[101];
+		break;
+	case 4:
+	case 7:
+		++_wo[15];
+		break;
+	case 5:
+		++_wo[221];
+		break;
+	case 6:
+		++_wo[201];
+		break;
+	case 8:
+		++_wo[141];
+		break;
+	case 9:
+		++_wo[301];
+		break;
+	case 10:
+		++_wo[241];
+		break;
+	case 11:
+		++_wo[161];
+		break;
+	case 13:
+		++_wo[261];
+		break;
+	case 14:
+		++_wo[281];
+		break;
+	default:
+		break;
+	}
+
+	switch (_vm->_map->getCell(15) - 1) {
+	case 1:
+		++_wo[63];
+		break;
+	case 0:
+	case 2:
+	case 3:
+	case 4:
+	case 5:
+	case 6:
+	case 7:
+	case 8:
+	case 9:
+	case 10:
+	case 11:
+	case 12:
+	case 13:
+	case 14:
+		++_wo[19];
+		break;
+	default:
+		break;
+	}
+
+	switch (_vm->_map->getCell(16) - 1) {
+	case 0:
+		++_wo[120];
+		break;
+	case 1:
+		++_wo[58];
+		break;
+	case 2:
+		++_wo[180];
+		break;
+	case 3:
+	case 12:
+		++_wo[100];
+		break;
+	case 4:
+	case 7:
+		++_wo[14];
+		break;
+	case 5:
+		++_wo[220];
+		break;
+	case 6:
+		++_wo[200];
+		break;
+	case 8:
+		++_wo[140];
+		break;
+	case 9:
+		++_wo[300];
+		break;
+	case 10:
+		++_wo[240];
+		break;
+	case 11:
+		++_wo[160];
+		break;
+	case 13:
+		++_wo[260];
+		break;
+	case 14:
+		++_wo[280];
+		break;
+	default:
+		break;
+	}
+
+	switch (_vm->_map->getCell(17) - 1) {
+	case 1:
+		++_wo[62];
+		break;
+	case 0:
+	case 2:
+	case 3:
+	case 4:
+	case 5:
+	case 6:
+	case 7:
+	case 8:
+	case 9:
+	case 10:
+	case 11:
+	case 12:
+	case 13:
+	case 14:
+		++_wo[18];
+		break;
+	default:
+		break;
+	}
+
+	switch (_vm->_map->getCell(18) - 1) {
+	case 0:
+		++_wo[119];
+		break;
+	case 1:
+		++_wo[57];
+		break;
+	case 2:
+		++_wo[179];
+		break;
+	case 3:
+	case 12:
+		++_wo[99];
+		break;
+	case 4:
+	case 7:
+		++_wo[13];
+		break;
+	case 5:
+		++_wo[219];
+		break;
+	case 6:
+		++_wo[199];
+		break;
+	case 8:
+		++_wo[139];
+		break;
+	case 9:
+		++_wo[299];
+		break;
+	case 10:
+		++_wo[239];
+		break;
+	case 11:
+		++_wo[159];
+		break;
+	case 13:
+		++_wo[259];
+		break;
+	case 14:
+		++_wo[279];
+		break;
+	default:
+		break;
+	}
+
+	switch (_vm->_map->getCell(19) - 1) {
+	case 0:
+		++_wo[108];
+		break;
+	case 1:
+		++_wo[78];
+		break;
+	case 2:
+		++_wo[168];
+	case 3:
+	case 12:
+		++_wo[88];
+		break;
+	case 4:
+	case 7:
+		++_wo[34];
+		break;
+	case 5:
+		++_wo[208];
+		break;
+	case 6:
+		++_wo[188];
+		break;
+	case 8:
+		++_wo[128];
+		break;
+	case 9:
+		++_wo[288];
+		break;
+	case 10:
+		++_wo[228];
+		break;
+	case 11:
+		++_wo[148];
+		break;
+	case 13:
+		++_wo[248];
+		break;
+	case 14:
+		++_wo[268];
+		break;
+	default:
+		break;
+	}
+
+	switch (_vm->_map->getCell(20) - 1) {
+	case 1:
+		++_wo[76];
+		break;
+	case 0:
+	case 2:
+	case 3:
+	case 4:
+	case 5:
+	case 6:
+	case 7:
+	case 8:
+	case 9:
+	case 10:
+	case 11:
+	case 12:
+	case 13:
+	case 14:
+		++_wo[32];
+		break;
+	default:
+		break;
+	}
+
+	switch (_vm->_map->getCell(21) - 1) {
+	case 0:
+		++_wo[109];
+		break;
+	case 1:
+		++_wo[44];
+		break;
+	case 2:
+		++_wo[169];
+		break;
+	case 3:
+	case 12:
+		++_wo[89];
+		break;
+	case 4:
+	case 7:
+		++_wo[0];
+		break;
+	case 5:
+		++_wo[209];
+		break;
+	case 6:
+		++_wo[189];
+		break;
+	case 8:
+		++_wo[129];
+		break;
+	case 9:
+		++_wo[289];
+		break;
+	case 10:
+		++_wo[229];
+		break;
+	case 11:
+		++_wo[149];
+		break;
+	case 13:
+		++_wo[249];
+		break;
+	case 14:
+		++_wo[269];
+		break;
+	default:
+		break;
+	}
+
+	switch (_vm->_map->getCell(22) - 1) {
+	case 1:
+		++_wo[74];
+		break;
+	case 0:
+	case 2:
+	case 3:
+	case 4:
+	case 5:
+	case 6:
+	case 7:
+	case 8:
+	case 9:
+	case 10:
+	case 11:
+	case 12:
+	case 13:
+	case 14:
+		++_wo[30];
+		break;
+	default:
+		break;
+	}
+
+	switch (_vm->_map->getCell(23) - 1) {
+	case 0:
+		++_wo[110];
+		break;
+	case 1:
+		++_wo[45];
+		break;
+	case 2:
+		++_wo[170];
+		break;
+	case 3:
+	case 12:
+		++_wo[90];
+		break;
+	case 4:
+	case 7:
+		++_wo[1];
+		break;
+	case 5:
+		++_wo[210];
+		break;
+	case 6:
+		++_wo[190];
+		break;
+	case 8:
+		++_wo[130];
+		break;
+	case 9:
+		++_wo[290];
+		break;
+	case 10:
+		++_wo[230];
+		break;
+	case 11:
+		++_wo[150];
+		break;
+	case 13:
+		++_wo[250];
+		break;
+	case 14:
+		++_wo[270];
+		break;
+	default:
+		break;
+	}
+
+	switch (_vm->_map->getCell(24) - 1) {
+	case 1:
+		++_wo[52];
+		break;
+	case 0:
+	case 2:
+	case 3:
+	case 4:
+	case 5:
+	case 6:
+	case 7:
+	case 8:
+	case 9:
+	case 10:
+	case 11:
+	case 12:
+	case 13:
+	case 14:
+		++_wo[8];
+		break;
+	default:
+		break;
+	}
+
+	switch (_vm->_map->getCell(25) - 1) {
+	case 0:
+		++_wo[111];
+		break;
+	case 1:
+		++_wo[46];
+		break;
+	case 2:
+		++_wo[171];
+		break;
+	case 3:
+	case 12:
+		++_wo[91];
+		break;
+	case 4:
+	case 7:
+		++_wo[2];
+		break;
+	case 5:
+		++_wo[211];
+		break;
+	case 6:
+		++_wo[191];
+		break;
+	case 8:
+		++_wo[131];
+		break;
+	case 9:
+		++_wo[291];
+		break;
+	case 10:
+		++_wo[231];
+		break;
+	case 11:
+		++_wo[151];
+		break;
+	case 13:
+		++_wo[251];
+		break;
+	case 14:
+		++_wo[271];
+		break;
+	default:
+		break;
+	}
+
+	switch (_vm->_map->getCell(26) - 1) {
+	case 1:
+		++_wo[51];
+		break;
+	case 0:
+	case 2:
+	case 3:
+	case 4:
+	case 5:
+	case 6:
+	case 7:
+	case 8:
+	case 9:
+	case 10:
+	case 11:
+	case 12:
+	case 13:
+	case 14:
+		++_wo[7];
+		break;
+	default:
+		break;
+	}
+
+	switch (_vm->_map->getCell(27) - 1) {
+	case 0:
+		++_wo[116];
+		break;
+	case 1:
+		++_wo[50];
+		break;
+	case 2:
+		++_wo[176];
+		break;
+	case 3:
+	case 12:
+		++_wo[96];
+		break;
+	case 4:
+	case 7:
+		++_wo[6];
+		break;
+	case 5:
+		++_wo[216];
+		break;
+	case 6:
+		++_wo[196];
+		break;
+	case 8:
+		++_wo[136];
+		break;
+	case 9:
+		++_wo[296];
+		break;
+	case 10:
+		++_wo[236];
+		break;
+	case 11:
+		++_wo[156];
+		break;
+	case 13:
+		++_wo[256];
+		break;
+	case 14:
+		++_wo[276];
+		break;
+	default:
+		break;
+	}
+
+	switch (_vm->_map->getCell(28) - 1) {
+	case 1:
+		++_wo[53];
+		break;
+	case 0:
+	case 2:
+	case 3:
+	case 4:
+	case 5:
+	case 6:
+	case 7:
+	case 8:
+	case 9:
+	case 10:
+	case 11:
+	case 12:
+	case 13:
+	case 14:
+		++_wo[9];
+		break;
+	default:
+		break;
+	}
+
+	switch (_vm->_map->getCell(29) - 1) {
+	case 0:
+		++_wo[115];
+		break;
+	case 1:
+		++_wo[49];
+		break;
+	case 2:
+		++_wo[175];
+		break;
+	case 3:
+	case 12:
+		++_wo[95];
+		break;
+	case 4:
+	case 7:
+		++_wo[5];
+		break;
+	case 5:
+		++_wo[215];
+		break;
+	case 6:
+		++_wo[195];
+		break;
+	case 8:
+		++_wo[135];
+		break;
+	case 9:
+		++_wo[295];
+		break;
+	case 10:
+		++_wo[235];
+		break;
+	case 11:
+		++_wo[155];
+		break;
+	case 13:
+		++_wo[255];
+		break;
+	case 14:
+		++_wo[275];
+		break;
+	default:
+		break;
+	}
+
+	switch (_vm->_map->getCell(30) - 1) {
+	case 1:
+		++_wo[54];
+		break;
+	case 0:
+	case 2:
+	case 3:
+	case 4:
+	case 5:
+	case 6:
+	case 7:
+	case 8:
+	case 9:
+	case 10:
+	case 11:
+	case 12:
+	case 13:
+	case 14:
+		++_wo[10];
+		break;
+	default:
+		break;
+	}
+
+	switch (_vm->_map->getCell(31) - 1) {
+	case 0:
+		++_wo[114];
+		break;
+	case 1:
+		++_wo[48];
+		break;
+	case 2:
+		++_wo[174];
+		break;
+	case 3:
+	case 12:
+		++_wo[94];
+		break;
+	case 4:
+	case 7:
+		++_wo[4];
+		break;
+	case 5:
+		++_wo[214];
+		break;
+	case 6:
+		++_wo[194];
+		break;
+	case 8:
+		++_wo[134];
+		break;
+	case 9:
+		++_wo[294];
+		break;
+	case 10:
+		++_wo[234];
+		break;
+	case 11:
+		++_wo[154];
+		break;
+	case 13:
+		++_wo[254];
+		break;
+	case 14:
+		++_wo[274];
+		break;
+	default:
+		break;
+	}
+
+	switch (_vm->_map->getCell(32) - 1) {
+	case 1:
+		++_wo[75];
+		break;
+	case 0:
+	case 2:
+	case 3:
+	case 4:
+	case 5:
+	case 6:
+	case 7:
+	case 8:
+	case 9:
+	case 10:
+	case 11:
+	case 12:
+	case 13:
+	case 14:
+		++_wo[31];
+		break;
+	default:
+		break;
+	}
+
+	switch (_vm->_map->getCell(33) - 1) {
+	case 0:
+		++_wo[112];
+		break;
+	case 1:
+		++_wo[47];
+		break;
+	case 2:
+		++_wo[172];
+		break;
+	case 3:
+	case 12:
+		++_wo[92];
+		break;
+	case 4:
+	case 7:
+		++_wo[3];
+		break;
+	case 5:
+		++_wo[212];
+		break;
+	case 6:
+		++_wo[192];
+		break;
+	case 8:
+		++_wo[132];
+		break;
+	case 9:
+		++_wo[292];
+		break;
+	case 10:
+		++_wo[232];
+		break;
+	case 11:
+		++_wo[152];
+		break;
+	case 13:
+		++_wo[252];
+		break;
+	case 14:
+		++_wo[272];
+		break;
+	default:
+		break;
+	}
+
+	switch (_vm->_map->getCell(34) - 1) {
+	case 1:
+		++_wo[77];
+		break;
+	case 0:
+	case 2:
+	case 3:
+	case 4:
+	case 5:
+	case 6:
+	case 7:
+	case 8:
+	case 9:
+	case 10:
+	case 11:
+	case 12:
+	case 13:
+	case 14:
+		++_wo[33];
+		break;
+	default:
+		break;
+	}
+
+	switch (_vm->_map->getCell(35) - 1) {
+	case 0:
+		++_wo[113];
+		break;
+	case 1:
+		++_wo[79];
+		break;
+	case 2:
+		++_wo[173];
+		break;
+	case 3:
+	case 12:
+		++_wo[93];
+		break;
+	case 4:
+	case 7:
+		++_wo[35];
+		break;
+	case 5:
+		++_wo[213];
+		break;
+	case 6:
+		++_wo[193];
+		break;
+	case 8:
+		++_wo[133];
+		break;
+	case 9:
+		++_wo[293];
+		break;
+	case 10:
+		++_wo[233];
+		break;
+	case 11:
+		++_wo[153];
+		break;
+	case 13:
+		++_wo[253];
+		break;
+	case 14:
+		++_wo[273];
+		break;
+	default:
+		break;
+	}
+
+	switch (_vm->_map->getCell(36) - 1) {
+	case 1:
+		++_wo[83];
+		break;
+	case 0:
+	case 2:
+	case 3:
+	case 4:
+	case 5:
+	case 6:
+	case 7:
+	case 8:
+	case 9:
+	case 10:
+	case 11:
+	case 12:
+	case 13:
+	case 14:
+		++_wo[39];
+		break;
+	default:
+		break;
+	}
+
+	switch (_vm->_map->getCell(37) - 1) {
+	case 1:
+		++_wo[82];
+		break;
+	case 0:
+	case 2:
+	case 3:
+	case 4:
+	case 5:
+	case 6:
+	case 7:
+	case 8:
+	case 9:
+	case 10:
+	case 11:
+	case 12:
+	case 13:
+	case 14:
+		++_wo[38];
+		break;
+	default:
+		break;
+	}
+
+	switch (_vm->_map->getCell(38) - 1) {
+	case 1:
+		++_wo[81];
+		break;
+	case 0:
+	case 2:
+	case 3:
+	case 4:
+	case 5:
+	case 6:
+	case 7:
+	case 8:
+	case 9:
+	case 10:
+	case 11:
+	case 12:
+	case 13:
+	case 14:
+		++_wo[37];
+		break;
+	default:
+		break;
+	}
+
+	switch (_vm->_map->getCell(34) - 1) {
+	case 1:
+		++_wo[77];
+		break;
+	case 0:
+	case 2:
+	case 3:
+	case 4:
+	case 5:
+	case 6:
+	case 7:
+	case 8:
+	case 9:
+	case 10:
+	case 11:
+	case 12:
+	case 13:
+	case 14:
+		++_wo[33];
+		break;
+	default:
+		break;
+	}
+
+	switch (_vm->_map->getCell(40) - 1) {
+	case 1:
+		++_wo[84];
+		break;
+	case 0:
+	case 2:
+	case 3:
+	case 4:
+	case 5:
+	case 6:
+	case 7:
+	case 8:
+	case 9:
+	case 10:
+	case 11:
+	case 12:
+	case 13:
+	case 14:
+		++_wo[40];
+		break;
+	default:
+		break;
+	}
+
+	switch (_vm->_map->getCell(41) - 1) {
+	case 1:
+		++_wo[85];
+		break;
+	case 0:
+	case 2:
+	case 3:
+	case 4:
+	case 5:
+	case 6:
+	case 7:
+	case 8:
+	case 9:
+	case 10:
+	case 11:
+	case 12:
+	case 13:
+	case 14:
+		++_wo[41];
+		break;
+	default:
+		break;
+	}
+
+	switch (_vm->_map->getCell(42) - 1) {
+	case 1:
+		++_wo[86];
+		break;
+	case 0:
+	case 2:
+	case 3:
+	case 4:
+	case 5:
+	case 6:
+	case 7:
+	case 8:
+	case 9:
+	case 10:
+	case 11:
+	case 12:
+	case 13:
+	case 14:
+		++_wo[42];
+		break;
+	default:
+		break;
+	}
+
+	switch (_vm->_map->getCell(43) - 1) {
+	case 1:
+		++_wo[87];
+		break;
+	case 0:
+	case 2:
+	case 3:
+	case 4:
+	case 5:
+	case 6:
+	case 7:
+	case 8:
+	case 9:
+	case 10:
+	case 11:
+	case 12:
+	case 13:
+	case 14:
+		++_wo[43];
+		break;
+	default:
+		break;
+	}
 }
 
 void InterfaceMap::setIndoorsMonsters() {
diff --git a/engines/xeen/interface_map.h b/engines/xeen/interface_map.h
index be17ef0..189598b 100644
--- a/engines/xeen/interface_map.h
+++ b/engines/xeen/interface_map.h
@@ -100,6 +100,9 @@ protected:
 	bool _isShooting;
 	bool _charsShooting;
 	int _objNumber;
+	bool _thinWall;
+
+	void setMazeBits();
 public:
 	OutdoorDrawList _outdoorList;
 	IndoorDrawList _indoorList;


Commit: adce5f9c2030813936268c0b7e58a33b6cfce003
    https://github.com/scummvm/scummvm/commit/adce5f9c2030813936268c0b7e58a33b6cfce003
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-01-20T21:37:57-05:00

Commit Message:
XEEN: Convert map _skySprites into a 2 element array

Changed paths:
    engines/xeen/interface_map.cpp
    engines/xeen/map.cpp
    engines/xeen/map.h



diff --git a/engines/xeen/interface_map.cpp b/engines/xeen/interface_map.cpp
index c551e58..2c1b973 100644
--- a/engines/xeen/interface_map.cpp
+++ b/engines/xeen/interface_map.cpp
@@ -3418,10 +3418,8 @@ void InterfaceMap::drawIndoors() {
 
 	map.cellFlagLookup(_vm->_party->_mazePosition);
 
-	// WORKAROUND: Original did an array lookup on _skySprites.
-	// Was this a feature for multiple skys that was abandoned?
-	assert(!map._currentSky);
-	_indoorList[0]._sprites = &map._skySprites;
+	assert(map._currentSky < 2);
+	_indoorList[0]._sprites = &map._skySprites[map._currentSky];
 	_indoorList[0]._flags = _flipSky ? SPRFLAG_HORIZ_FLIPPED : 0;
 
 	if (_vm->_openDoor) {
@@ -3433,7 +3431,7 @@ void InterfaceMap::drawIndoors() {
 			);
 		map.cellFlagLookup(pt);
 		
-		_indoorList._sky2._sprites = &map._skySprites;
+		_indoorList._sky2._sprites = &map._skySprites[0];
 	} else {
 		_indoorList._sky2._sprites = _indoorList[0]._sprites;
 	}
diff --git a/engines/xeen/map.cpp b/engines/xeen/map.cpp
index 6b577eb..e541d37 100644
--- a/engines/xeen/map.cpp
+++ b/engines/xeen/map.cpp
@@ -868,7 +868,7 @@ Map::Map(XeenEngine *vm) : _vm(vm), _mobData(vm) {
 	_currentCantRest = false;
 	_currentIsDrain = false;
 	_currentIsEvent = false;
-	_currentSky = false;
+	_currentSky = 0;
 	_currentMonsterFlags = 0;
 }
 
@@ -1082,7 +1082,7 @@ void Map::load(int mapId) {
 
 		_groundSprites.load("water.out");
 		_tileSprites.load("outdoor.til");
-		outdoorList._skySprite._sprites = &_skySprites;
+		outdoorList._skySprite._sprites = &_skySprites[0];
 		outdoorList._groundSprite._sprites = &_groundSprites;
 		
 		for (int i = 0; i < TOTAL_SURFACES; ++i) {
@@ -1100,7 +1100,7 @@ void Map::load(int mapId) {
 	} else {
 		warning("TODO");	// Sound loading
 
-		_mazeSkySprites.load(Common::String::format("%s.sky",
+		_skySprites[1].load(Common::String::format("%s.sky",
 			TERRAIN_TYPES[_mazeData[0]._wallKind]));
 		_groundSprites.load(Common::String::format("%s.gnd",
 			TERRAIN_TYPES[_mazeData[0]._wallKind]));
@@ -1354,7 +1354,7 @@ void Map::cellFlagLookup(const Common::Point &pt) {
 	_currentCantRest = cell._flags & FLAG_WATER;
 	_currentIsDrain = cell._flags & OUTFLAG_DRAIN;
 	_currentIsEvent = cell._flags & FLAG_AUTOEXECUTE_EVENT;
-	_currentSky = cell._flags & OUTFLAG_OBJECT_EXISTS;
+	_currentSky = (cell._flags & OUTFLAG_OBJECT_EXISTS) ? 1 : 0;
 	_currentMonsterFlags = cell._flags & 7;
 }
 
@@ -1495,7 +1495,7 @@ void Map::loadSky() {
 	Party &party = *_vm->_party;
 
 	party._isNight = party._minutes < (5 * 60) || party._minutes >= (21 * 60);
-	_skySprites.load(((party._mazeId >= 89 && party._mazeId <= 112) ||
+	_skySprites[0].load(((party._mazeId >= 89 && party._mazeId <= 112) ||
 		party._mazeId == 128 || party._mazeId == 129) || !party._isNight 
 		? "sky.sky" : "night.sky");
 }
diff --git a/engines/xeen/map.h b/engines/xeen/map.h
index 3241825..d8444eb 100644
--- a/engines/xeen/map.h
+++ b/engines/xeen/map.h
@@ -354,8 +354,7 @@ public:
 	MazeEvents _events;
 	HeadData _headData;
 	AnimationInfo _animationInfo;
-	SpriteResource _skySprites;
-	SpriteResource _mazeSkySprites;
+	SpriteResource _skySprites[2];
 	SpriteResource _groundSprites;
 	SpriteResource _tileSprites;
 	SpriteResource _surfaceSprites[TOTAL_SURFACES];
@@ -364,7 +363,7 @@ public:
 	bool _currentCantRest;
 	bool _currentIsDrain;
 	bool _currentIsEvent;
-	bool _currentSky;
+	int _currentSky;
 	int _currentMonsterFlags;
 	MazeWallLayers _currentWall;
 	int _currentTile;


Commit: 69ca508e8fd16e79bfa5a0f66ced3ccf9fb2dbf8
    https://github.com/scummvm/scummvm/commit/69ca508e8fd16e79bfa5a0f66ced3ccf9fb2dbf8
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-01-20T22:13:26-05:00

Commit Message:
XEEN: Fix settig stepped on tiles

Changed paths:
    engines/xeen/interface_map.cpp
    engines/xeen/map.h



diff --git a/engines/xeen/interface_map.cpp b/engines/xeen/interface_map.cpp
index 2c1b973..4ff64b3 100644
--- a/engines/xeen/interface_map.cpp
+++ b/engines/xeen/interface_map.cpp
@@ -1758,9 +1758,9 @@ void InterfaceMap::setMazeBits() {
 		break;
 	}
 
-	switch (_vm->_map->getCell(34) - 1) {
+	switch (_vm->_map->getCell(39) - 1) {
 	case 1:
-		++_wo[77];
+		++_wo[80];
 		break;
 	case 0:
 	case 2:
@@ -1776,7 +1776,7 @@ void InterfaceMap::setMazeBits() {
 	case 12:
 	case 13:
 	case 14:
-		++_wo[33];
+		++_wo[36];
 		break;
 	default:
 		break;
diff --git a/engines/xeen/map.h b/engines/xeen/map.h
index d8444eb..8735973 100644
--- a/engines/xeen/map.h
+++ b/engines/xeen/map.h
@@ -384,9 +384,9 @@ public:
 
 	int getCell(int idx);
 
-	MazeData mazeData() { return _mazeData[0]; }
+	MazeData &mazeData() { return _mazeData[0]; }
 
-	MazeData mazeDataCurrent() { return _mazeData[_mazeDataIndex]; }
+	MazeData &mazeDataCurrent() { return _mazeData[_mazeDataIndex]; }
 
 	void loadSky();
 


Commit: 932222de7dd32ff0a0b643a2e9d756160bff27bf
    https://github.com/scummvm/scummvm/commit/932222de7dd32ff0a0b643a2e9d756160bff27bf
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-01-21T20:42:44-05:00

Commit Message:
XEEN: Skeleton beginnings of script handling

Changed paths:
    engines/xeen/files.cpp
    engines/xeen/files.h
    engines/xeen/interface.cpp
    engines/xeen/interface.h
    engines/xeen/map.cpp
    engines/xeen/scripts.cpp
    engines/xeen/scripts.h



diff --git a/engines/xeen/files.cpp b/engines/xeen/files.cpp
index f8e7a3f..0c3402f 100644
--- a/engines/xeen/files.cpp
+++ b/engines/xeen/files.cpp
@@ -232,4 +232,15 @@ void File::openFile(const Common::String &filename, Common::Archive &archive) {
 		error("Could not open file - %s", filename.c_str());
 }
 
+Common::String File::readString() {
+	Common::String result;
+	char c;
+
+	while (pos() < size() && (c = (char)readByte()) != '\0')
+		result += c;
+
+	return result;
+}
+
+
 } // End of namespace Xeen
diff --git a/engines/xeen/files.h b/engines/xeen/files.h
index f350e34..f0c92d1 100644
--- a/engines/xeen/files.h
+++ b/engines/xeen/files.h
@@ -75,6 +75,8 @@ public:
 
 	void openFile(const Common::String &filename);
 	void openFile(const Common::String &filename, Common::Archive &archive);
+
+	Common::String readString();
 };
 
 class XeenSerializer : public Common::Serializer {
diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp
index d2fea36..e31b9e2 100644
--- a/engines/xeen/interface.cpp
+++ b/engines/xeen/interface.cpp
@@ -43,7 +43,6 @@ Interface::Interface(XeenEngine *vm) : ButtonContainer(), InterfaceMap(vm), _vm(
 	_hiliteChar = -1;
 	_intrIndex1 = 0;
 	_flag1 = false;
-	_animCounter = 0;
 	_isAnimReset = false;
 	_tillMove = 0;
 	_overallFrame = 0;
@@ -542,6 +541,7 @@ void Interface::draw3d(bool updateFlag) {
 	Map &map = *_vm->_map;
 	Party &party = *_vm->_party;
 	Screen &screen = *_vm->_screen;
+	Scripts &scripts = *_vm->_scripts;
 
 	if (screen._windows[11]._enabled)
 		return;
@@ -570,7 +570,7 @@ void Interface::draw3d(bool updateFlag) {
 			mazeObject._frame = animEntry._frame1._frames[directionIndex];
 		} else {
 			++mazeObject._frame;
-			if ((int)idx == objNum && _animCounter > 0 && (
+			if ((int)idx == objNum && scripts._animCounter > 0 && (
 					objObject._spriteId == (_vm->_files->_isDarkCc ? 15 : 16) ||
 					objObject._spriteId == 58 || objObject._spriteId == 73)) {
 				if (mazeObject._frame > 4 || mazeObject._spriteId == 58)
diff --git a/engines/xeen/interface.h b/engines/xeen/interface.h
index 93c861e..37ac7be 100644
--- a/engines/xeen/interface.h
+++ b/engines/xeen/interface.h
@@ -66,10 +66,8 @@ private:
 	int _heroismUIFrame;
 	int _flipUIFrame;
 	bool _buttonsLoaded;
-	Common::String _interfaceText;
 	int _hiliteChar;
 	bool _flag1;
-	int _animCounter;
 	bool _isAnimReset;
 	byte _tillMove;
 	int _overallFrame;
@@ -107,6 +105,7 @@ private:
 	bool checkMoveDirection(int key);
 public:
 	int _intrIndex1;
+	Common::String _interfaceText;
 public:
 	Interface(XeenEngine *vm);
 
diff --git a/engines/xeen/map.cpp b/engines/xeen/map.cpp
index e541d37..d2f4c5e 100644
--- a/engines/xeen/map.cpp
+++ b/engines/xeen/map.cpp
@@ -1284,8 +1284,9 @@ void Map::loadEvents(int mapId) {
 	filename = Common::String::format("aaze%c%03d.txt",
 		(mapId >= 100) ? 'x' : '0', mapId);
 	File fText(filename);
-	_events._text.resize(fText.size());
-	fText.read(&_events._text[0], fText.size());
+	_events._text.clear();
+	while (fText.pos() < fText.size())
+		_events._text.push_back(fText.readString());
 	fText.close();
 }
 
diff --git a/engines/xeen/scripts.cpp b/engines/xeen/scripts.cpp
index 55388ec..50584a2 100644
--- a/engines/xeen/scripts.cpp
+++ b/engines/xeen/scripts.cpp
@@ -22,6 +22,7 @@
 
 #include "xeen/scripts.h"
 #include "xeen/party.h"
+#include "xeen/xeen.h"
 
 namespace Xeen {
 
@@ -65,9 +66,76 @@ void MazeEvents::synchronize(XeenSerializer &s) {
 /*------------------------------------------------------------------------*/
 
 Scripts::Scripts(XeenEngine *vm) : _vm(vm) {
+	Common::fill(&_charFX[0], &_charFX[MAX_ACTIVE_PARTY], 0);
+	_whoWill = 0;
+	_itemType = 0;
+	_treasureItems = 0;
+	_treasureGold = 0;
+	_treasureGems = 0;
+
+	_v2 = 0;
+	_nEdamageType = 0;
+	_animCounter = 0;
+	_eventSkipped = false;
 }
 
 void Scripts::checkEvents() {
+	Combat &combat = *_vm->_combat;
+	Interface &intf = *_vm->_interface;
+	Map &map = *_vm->_map;
+	Party &party = *_vm->_party;
+
+	int var18 = 0;
+	_itemType = 0;
+	int var4F = 0;
+	bool var50 = false;
+	_whoWill = 0;
+	Mode oldMode = _vm->_mode;
+	Common::fill(&_charFX[0], &_charFX[MAX_ACTIVE_PARTY], 0);
+	int items = _treasureItems;
+	
+	if (_treasureGold & _treasureItems) {
+		// TODO
+	} else {
+		// TODO
+	}
+
+	do {
+		int var4 = 0;
+		int varA = 0;
+		_animCounter = 0;
+		int var4E = 0;
+		const Common::Point pt = party._mazePosition;
+		int varC = 1;
+		_v2 = 1;
+		_nEdamageType = 0;
+		int var40 = -1;
+
+		// Break out of the events if there's an attacking monster
+		if (combat._attackMonsters[0] != -1) {
+			_eventSkipped = true;
+			break;
+		}
+
+		_eventSkipped = false;
+
+		for (uint eventIndex = 0; eventIndex < map._events.size(); ++eventIndex) {
+			MazeEvent &event = map._events[eventIndex];
+
+			if (event._position == pt && party._mazeDirection != (pt.x | pt.y)) {
+				if (event._direction == party._mazeDirection || event._direction == DIR_ALL) {
+					_vm->_mode = MODE_9;
+					intf._interfaceText = event._parameters.size() == 0 ? "" :
+						map._events._text[event._parameters[0]];
+					doOpcode(event._opcode, event._parameters);
+
+				} else {
+					var50 = true;
+				}
+			}
+		}
+	} while (0);
+
 	// TODO
 }
 
@@ -79,4 +147,97 @@ void Scripts::openGrate(int v1, int v2) {
 	// TODO
 }
 
+typedef void(Scripts::*ScriptMethodPtr)(Common::Array<byte> &);
+
+void Scripts::doOpcode(Opcode opcode, Common::Array<byte> &params) {
+	static const ScriptMethodPtr COMMAND_LIST[] = {
+		&Scripts::cmdNone, &Scripts::cmdDisplay0x01, &Scripts::cmdDoorTextSml,
+		&Scripts::cmdDoorTextLrg, &Scripts::cmdSignText,
+		&Scripts::cmdNPC, &Scripts::cmdPlayFX, &Scripts::cmdTeleportAndExit,
+		&Scripts::cmdIf1, &Scripts::cmdIf2, &Scripts::cmdIf3,
+		&Scripts::cmdMoveObj, &Scripts::cmdTakeOrGive, &Scripts::cmdNoAction,
+		&Scripts::cmdRemove, &Scripts::cmdSetChar, &Scripts::cmdSpawn,
+		&Scripts::cmdDoTownEvent, &Scripts::cmdExit, &Scripts::cmdAfterMap,
+		&Scripts::cmdGiveExtended, &Scripts::cmdConfirmWord, &Scripts::cmdDamage,
+		&Scripts::cmdJumpRnd, &Scripts::cmdAfterEvent, &Scripts::cmdCallEvent,
+		&Scripts::cmdReturn, &Scripts::cmdSetVar, &Scripts::cmdTakeOrGive2,
+		&Scripts::cmdTakeOrGive3, &Scripts::cmdCutsceneEndClouds,
+		&Scripts::cmdTeleportAndContinue, &Scripts::cmdWhoWill,
+		&Scripts::cmdRndDamage, &Scripts::cmdMoveWallObj, &Scripts::cmdAlterCellFlag,
+		&Scripts::cmdAlterHed, &Scripts::cmdDisplayStat, &Scripts::cmdTakeOrGive4,
+		&Scripts::cmdSeatTextSml, &Scripts::cmdPlayEventVoc, &Scripts::cmdDisplayBottom,
+		&Scripts::cmdIfMapFlag, &Scripts::cmdSelRndChar, &Scripts::cmdGiveEnchanted,
+		&Scripts::cmdItemType, &Scripts::cmdMakeNothingHere, &Scripts::cmdNoAction2,
+		&Scripts::cmdChooseNumeric, &Scripts::cmdDisplayBottomTwoLines,
+		&Scripts::cmdDisplayLarge, &Scripts::cmdExchObj, &Scripts::cmdFallToMap,
+		&Scripts::cmdDisplayMain, &Scripts::cmdGoto, &Scripts::cmdConfirmWord2,
+		&Scripts::cmdGotoRandom, &Scripts::cmdCutsceneEndDarkside,
+		&Scripts::cmdCutsceneEdWorld, &Scripts::cmdFlipWorld, &Scripts::cmdPlayCD
+	};
+
+	(this->*COMMAND_LIST[opcode])(params);
+}
+
+void Scripts::cmdNone(Common::Array<byte> &params) {}
+void Scripts::cmdDisplay0x01(Common::Array<byte> &params) {}
+void Scripts::cmdDoorTextSml(Common::Array<byte> &params) {}
+void Scripts::cmdDoorTextLrg(Common::Array<byte> &params) {}
+void Scripts::cmdSignText(Common::Array<byte> &params) {}
+void Scripts::cmdNPC(Common::Array<byte> &params) {}
+void Scripts::cmdPlayFX(Common::Array<byte> &params) {}
+void Scripts::cmdTeleportAndExit(Common::Array<byte> &params) {}
+void Scripts::cmdIf1(Common::Array<byte> &params) {}
+void Scripts::cmdIf2(Common::Array<byte> &params) {}
+void Scripts::cmdIf3(Common::Array<byte> &params) {}
+void Scripts::cmdMoveObj(Common::Array<byte> &params) {}
+void Scripts::cmdTakeOrGive(Common::Array<byte> &params) {}
+void Scripts::cmdNoAction(Common::Array<byte> &params) {}
+void Scripts::cmdRemove(Common::Array<byte> &params) {}
+void Scripts::cmdSetChar(Common::Array<byte> &params) {}
+void Scripts::cmdSpawn(Common::Array<byte> &params) {}
+void Scripts::cmdDoTownEvent(Common::Array<byte> &params) {}
+void Scripts::cmdExit(Common::Array<byte> &params) {}
+void Scripts::cmdAfterMap(Common::Array<byte> &params) {}
+void Scripts::cmdGiveExtended(Common::Array<byte> &params) {}
+void Scripts::cmdConfirmWord(Common::Array<byte> &params) {}
+void Scripts::cmdDamage(Common::Array<byte> &params) {}
+void Scripts::cmdJumpRnd(Common::Array<byte> &params) {}
+void Scripts::cmdAfterEvent(Common::Array<byte> &params) {}
+void Scripts::cmdCallEvent(Common::Array<byte> &params) {}
+void Scripts::cmdReturn(Common::Array<byte> &params) {}
+void Scripts::cmdSetVar(Common::Array<byte> &params) {}
+void Scripts::cmdTakeOrGive2(Common::Array<byte> &params) {}
+void Scripts::cmdTakeOrGive3(Common::Array<byte> &params) {}
+void Scripts::cmdCutsceneEndClouds(Common::Array<byte> &params) {}
+void Scripts::cmdTeleportAndContinue(Common::Array<byte> &params) {}
+void Scripts::cmdWhoWill(Common::Array<byte> &params) {}
+void Scripts::cmdRndDamage(Common::Array<byte> &params) {}
+void Scripts::cmdMoveWallObj(Common::Array<byte> &params) {}
+void Scripts::cmdAlterCellFlag(Common::Array<byte> &params) {}
+void Scripts::cmdAlterHed(Common::Array<byte> &params) {}
+void Scripts::cmdDisplayStat(Common::Array<byte> &params) {}
+void Scripts::cmdTakeOrGive4(Common::Array<byte> &params) {}
+void Scripts::cmdSeatTextSml(Common::Array<byte> &params) {}
+void Scripts::cmdPlayEventVoc(Common::Array<byte> &params) {}
+void Scripts::cmdDisplayBottom(Common::Array<byte> &params) {}
+void Scripts::cmdIfMapFlag(Common::Array<byte> &params) {}
+void Scripts::cmdSelRndChar(Common::Array<byte> &params) {}
+void Scripts::cmdGiveEnchanted(Common::Array<byte> &params) {}
+void Scripts::cmdItemType(Common::Array<byte> &params) {}
+void Scripts::cmdMakeNothingHere(Common::Array<byte> &params) {}
+void Scripts::cmdNoAction2(Common::Array<byte> &params) {}
+void Scripts::cmdChooseNumeric(Common::Array<byte> &params) {}
+void Scripts::cmdDisplayBottomTwoLines(Common::Array<byte> &params) {}
+void Scripts::cmdDisplayLarge(Common::Array<byte> &params) {}
+void Scripts::cmdExchObj(Common::Array<byte> &params) {}
+void Scripts::cmdFallToMap(Common::Array<byte> &params) {}
+void Scripts::cmdDisplayMain(Common::Array<byte> &params) {}
+void Scripts::cmdGoto(Common::Array<byte> &params) {}
+void Scripts::cmdConfirmWord2(Common::Array<byte> &params) {}
+void Scripts::cmdGotoRandom(Common::Array<byte> &params) {}
+void Scripts::cmdCutsceneEndDarkside(Common::Array<byte> &params) {}
+void Scripts::cmdCutsceneEdWorld(Common::Array<byte> &params) {}
+void Scripts::cmdFlipWorld(Common::Array<byte> &params) {}
+void Scripts::cmdPlayCD(Common::Array<byte> &params) {}
+
 } // End of namespace Xeen
diff --git a/engines/xeen/scripts.h b/engines/xeen/scripts.h
index 9974892..2fbcf78 100644
--- a/engines/xeen/scripts.h
+++ b/engines/xeen/scripts.h
@@ -26,6 +26,7 @@
 #include "common/scummsys.h"
 #include "common/system.h"
 #include "common/serializer.h"
+#include "common/str-array.h"
 #include "xeen/files.h"
 
 namespace Xeen {
@@ -111,7 +112,7 @@ public:
 
 class MazeEvents : public Common::Array<MazeEvent> {
 public:
-	Common::Array<byte> _text;
+	Common::StringArray _text;
 public:
 	void synchronize(XeenSerializer &s);
 };
@@ -119,6 +120,81 @@ public:
 class Scripts {
 private:
 	XeenEngine *_vm;
+	int _charFX[6];
+	int _whoWill;
+	int _itemType;
+	int _treasureItems;
+	int _treasureGold;
+	int _treasureGems;
+
+	int _v2;
+	int _nEdamageType;
+
+	void doOpcode(Opcode opcode, Common::Array<byte> &params);
+	void cmdNone(Common::Array<byte> &params);
+	void cmdDisplay0x01(Common::Array<byte> &params);
+	void cmdDoorTextSml(Common::Array<byte> &params);
+	void cmdDoorTextLrg(Common::Array<byte> &params);
+	void cmdSignText(Common::Array<byte> &params);
+	void cmdNPC(Common::Array<byte> &params);
+	void cmdPlayFX(Common::Array<byte> &params);
+	void cmdTeleportAndExit(Common::Array<byte> &params);
+	void cmdIf1(Common::Array<byte> &params);
+	void cmdIf2(Common::Array<byte> &params);
+	void cmdIf3(Common::Array<byte> &params);
+	void cmdMoveObj(Common::Array<byte> &params);
+	void cmdTakeOrGive(Common::Array<byte> &params);
+	void cmdNoAction(Common::Array<byte> &params);
+	void cmdRemove(Common::Array<byte> &params);
+	void cmdSetChar(Common::Array<byte> &params);
+	void cmdSpawn(Common::Array<byte> &params);
+	void cmdDoTownEvent(Common::Array<byte> &params);
+	void cmdExit(Common::Array<byte> &params);
+	void cmdAfterMap(Common::Array<byte> &params);
+	void cmdGiveExtended(Common::Array<byte> &params);
+	void cmdConfirmWord(Common::Array<byte> &params);
+	void cmdDamage(Common::Array<byte> &params);
+	void cmdJumpRnd(Common::Array<byte> &params);
+	void cmdAfterEvent(Common::Array<byte> &params);
+	void cmdCallEvent(Common::Array<byte> &params);
+	void cmdReturn(Common::Array<byte> &params);
+	void cmdSetVar(Common::Array<byte> &params);
+	void cmdTakeOrGive2(Common::Array<byte> &params);
+	void cmdTakeOrGive3(Common::Array<byte> &params);
+	void cmdCutsceneEndClouds(Common::Array<byte> &params);
+	void cmdTeleportAndContinue(Common::Array<byte> &params);
+	void cmdWhoWill(Common::Array<byte> &params);
+	void cmdRndDamage(Common::Array<byte> &params);
+	void cmdMoveWallObj(Common::Array<byte> &params);
+	void cmdAlterCellFlag(Common::Array<byte> &params);
+	void cmdAlterHed(Common::Array<byte> &params);
+	void cmdDisplayStat(Common::Array<byte> &params);
+	void cmdTakeOrGive4(Common::Array<byte> &params);
+	void cmdSeatTextSml(Common::Array<byte> &params);
+	void cmdPlayEventVoc(Common::Array<byte> &params);
+	void cmdDisplayBottom(Common::Array<byte> &params);
+	void cmdIfMapFlag(Common::Array<byte> &params);
+	void cmdSelRndChar(Common::Array<byte> &params);
+	void cmdGiveEnchanted(Common::Array<byte> &params);
+	void cmdItemType(Common::Array<byte> &params);
+	void cmdMakeNothingHere(Common::Array<byte> &params);
+	void cmdNoAction2(Common::Array<byte> &params);
+	void cmdChooseNumeric(Common::Array<byte> &params);
+	void cmdDisplayBottomTwoLines(Common::Array<byte> &params);
+	void cmdDisplayLarge(Common::Array<byte> &params);
+	void cmdExchObj(Common::Array<byte> &params);
+	void cmdFallToMap(Common::Array<byte> &params);
+	void cmdDisplayMain(Common::Array<byte> &params);
+	void cmdGoto(Common::Array<byte> &params);
+	void cmdConfirmWord2(Common::Array<byte> &params);
+	void cmdGotoRandom(Common::Array<byte> &params);
+	void cmdCutsceneEndDarkside(Common::Array<byte> &params);
+	void cmdCutsceneEdWorld(Common::Array<byte> &params);
+	void cmdFlipWorld(Common::Array<byte> &params);
+	void cmdPlayCD(Common::Array<byte> &params);
+public:
+	int _animCounter;
+	bool _eventSkipped;
 public:
 	Scripts(XeenEngine *vm);
 


Commit: 1b264ed299fd87262c2cf228418ec606fdf75646
    https://github.com/scummvm/scummvm/commit/1b264ed299fd87262c2cf228418ec606fdf75646
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-01-21T21:51:45-05:00

Commit Message:
XEEN: Implemented the first few script commands

Changed paths:
    engines/xeen/interface.cpp
    engines/xeen/interface.h
    engines/xeen/scripts.cpp
    engines/xeen/scripts.h



diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp
index e31b9e2..4b4e88a 100644
--- a/engines/xeen/interface.cpp
+++ b/engines/xeen/interface.cpp
@@ -734,7 +734,10 @@ void Interface::draw3d(bool updateFlag) {
 
 	assembleBorder();
 
-	// TODO: write strings
+	// Draw any on-screen text if flagged to do so
+	if (_upDoorText && combat._attackMonsters[0] == -1) {
+		screen._windows[3].writeString(_screenText);
+	}
 
 	if (updateFlag) {
 		screen._windows[1].update();
diff --git a/engines/xeen/interface.h b/engines/xeen/interface.h
index 37ac7be..87edb02 100644
--- a/engines/xeen/interface.h
+++ b/engines/xeen/interface.h
@@ -71,8 +71,8 @@ private:
 	bool _isAnimReset;
 	byte _tillMove;
 	int _overallFrame;
-	bool _upDoorText;
 	int _steppingFX;
+	Common::String _interfaceText;
 
 	void initDrawStructs();
 
@@ -105,7 +105,8 @@ private:
 	bool checkMoveDirection(int key);
 public:
 	int _intrIndex1;
-	Common::String _interfaceText;
+	Common::String _screenText;
+	bool _upDoorText;
 public:
 	Interface(XeenEngine *vm);
 
diff --git a/engines/xeen/scripts.cpp b/engines/xeen/scripts.cpp
index 50584a2..44b5cb3 100644
--- a/engines/xeen/scripts.cpp
+++ b/engines/xeen/scripts.cpp
@@ -87,7 +87,7 @@ void Scripts::checkEvents() {
 
 	int var18 = 0;
 	_itemType = 0;
-	int var4F = 0;
+	_var4F = 0;
 	bool var50 = false;
 	_whoWill = 0;
 	Mode oldMode = _vm->_mode;
@@ -101,7 +101,7 @@ void Scripts::checkEvents() {
 	}
 
 	do {
-		int var4 = 0;
+		_lineNum = 0;
 		int varA = 0;
 		_animCounter = 0;
 		int var4E = 0;
@@ -111,28 +111,33 @@ void Scripts::checkEvents() {
 		_nEdamageType = 0;
 		int var40 = -1;
 
-		// Break out of the events if there's an attacking monster
-		if (combat._attackMonsters[0] != -1) {
-			_eventSkipped = true;
-			break;
-		}
-
-		_eventSkipped = false;
-
-		for (uint eventIndex = 0; eventIndex < map._events.size(); ++eventIndex) {
-			MazeEvent &event = map._events[eventIndex];
+		while (_lineNum >= 0) {
+			// Break out of the events if there's an attacking monster
+			if (combat._attackMonsters[0] != -1) {
+				_eventSkipped = true;
+				break;
+			}
 
-			if (event._position == pt && party._mazeDirection != (pt.x | pt.y)) {
-				if (event._direction == party._mazeDirection || event._direction == DIR_ALL) {
-					_vm->_mode = MODE_9;
-					intf._interfaceText = event._parameters.size() == 0 ? "" :
-						map._events._text[event._parameters[0]];
-					doOpcode(event._opcode, event._parameters);
+			_eventSkipped = false;
+			uint eventIndex;
+			for (eventIndex = 0; eventIndex < map._events.size(); ++eventIndex) {
+				MazeEvent &event = map._events[eventIndex];
 
-				} else {
-					var50 = true;
+				if (event._position == pt && party._mazeDirection != (pt.x | pt.y)
+						&& event._line == _lineNum) {
+					if (event._direction == party._mazeDirection || event._direction == DIR_ALL) {
+						_vm->_mode = MODE_9;
+						_paramText = event._parameters.size() == 0 ? "" :
+							map._events._text[event._parameters[0]];
+						doOpcode(event._opcode, event._parameters);
+						break;
+					} else {
+						var50 = true;
+					}
 				}
 			}
+			if (eventIndex == map._events.size())
+				break;
 		}
 	} while (0);
 
@@ -151,20 +156,20 @@ typedef void(Scripts::*ScriptMethodPtr)(Common::Array<byte> &);
 
 void Scripts::doOpcode(Opcode opcode, Common::Array<byte> &params) {
 	static const ScriptMethodPtr COMMAND_LIST[] = {
-		&Scripts::cmdNone, &Scripts::cmdDisplay0x01, &Scripts::cmdDoorTextSml,
+		nullptr, &Scripts::cmdDisplay1, &Scripts::cmdDoorTextSml,
 		&Scripts::cmdDoorTextLrg, &Scripts::cmdSignText,
-		&Scripts::cmdNPC, &Scripts::cmdPlayFX, &Scripts::cmdTeleportAndExit,
-		&Scripts::cmdIf1, &Scripts::cmdIf2, &Scripts::cmdIf3,
+		&Scripts::cmdNPC, &Scripts::cmdPlayFX, &Scripts::cmdTeleport,
+		&Scripts::cmdIf, &Scripts::cmdIf, &Scripts::cmdIf,
 		&Scripts::cmdMoveObj, &Scripts::cmdTakeOrGive, &Scripts::cmdNoAction,
 		&Scripts::cmdRemove, &Scripts::cmdSetChar, &Scripts::cmdSpawn,
 		&Scripts::cmdDoTownEvent, &Scripts::cmdExit, &Scripts::cmdAfterMap,
 		&Scripts::cmdGiveExtended, &Scripts::cmdConfirmWord, &Scripts::cmdDamage,
 		&Scripts::cmdJumpRnd, &Scripts::cmdAfterEvent, &Scripts::cmdCallEvent,
-		&Scripts::cmdReturn, &Scripts::cmdSetVar, &Scripts::cmdTakeOrGive2,
-		&Scripts::cmdTakeOrGive3, &Scripts::cmdCutsceneEndClouds,
-		&Scripts::cmdTeleportAndContinue, &Scripts::cmdWhoWill,
+		&Scripts::cmdReturn, &Scripts::cmdSetVar, &Scripts::cmdTakeOrGive,
+		&Scripts::cmdTakeOrGive, &Scripts::cmdCutsceneEndClouds,
+		&Scripts::cmdTeleport, &Scripts::cmdWhoWill,
 		&Scripts::cmdRndDamage, &Scripts::cmdMoveWallObj, &Scripts::cmdAlterCellFlag,
-		&Scripts::cmdAlterHed, &Scripts::cmdDisplayStat, &Scripts::cmdTakeOrGive4,
+		&Scripts::cmdAlterHed, &Scripts::cmdDisplayStat, &Scripts::cmdTakeOrGive,
 		&Scripts::cmdSeatTextSml, &Scripts::cmdPlayEventVoc, &Scripts::cmdDisplayBottom,
 		&Scripts::cmdIfMapFlag, &Scripts::cmdSelRndChar, &Scripts::cmdGiveEnchanted,
 		&Scripts::cmdItemType, &Scripts::cmdMakeNothingHere, &Scripts::cmdNoAction2,
@@ -178,20 +183,64 @@ void Scripts::doOpcode(Opcode opcode, Common::Array<byte> &params) {
 	(this->*COMMAND_LIST[opcode])(params);
 }
 
-void Scripts::cmdNone(Common::Array<byte> &params) {}
-void Scripts::cmdDisplay0x01(Common::Array<byte> &params) {}
-void Scripts::cmdDoorTextSml(Common::Array<byte> &params) {}
-void Scripts::cmdDoorTextLrg(Common::Array<byte> &params) {}
+/**
+ * Display a msesage on-screen
+ */
+void Scripts::cmdDisplay1(Common::Array<byte> &params) {
+	Screen &screen = *_vm->_screen;
+	Common::String msg = Common::String::format("\r\x03c%s", _paramText.c_str());
+
+	screen._windows[12].close();
+	if (screen._windows[38]._enabled)
+		screen._windows[38].open();
+	screen._windows[38].writeString(msg);
+	screen._windows[38].update();
+
+	_var4F = true;
+	cmdNoAction(params);
+}
+
+/**
+ * Displays a door text message using the small font
+ */
+void Scripts::cmdDoorTextSml(Common::Array<byte> &params) {
+	Interface &intf = *_vm->_interface;
+	intf._screenText = Common::String::format("\x02\f08\x03c\t116\v025%s\x03l\fd\x01",
+		_paramText.c_str());
+	intf._upDoorText = true;
+	intf.draw3d(true);
+	_var4F = true;
+
+	cmdNoAction(params);
+}
+
+/**
+ * Displays a door text message using the large font
+ */
+void Scripts::cmdDoorTextLrg(Common::Array<byte> &params) {
+	Interface &intf = *_vm->_interface;
+	intf._screenText = Common::String::format("\f04\x03c\t116\v030%s\x03l\fd",
+		_paramText.c_str());
+	intf._upDoorText = true;
+	intf.draw3d(true);
+	_var4F = true;
+
+	cmdNoAction(params);
+}
+
 void Scripts::cmdSignText(Common::Array<byte> &params) {}
 void Scripts::cmdNPC(Common::Array<byte> &params) {}
 void Scripts::cmdPlayFX(Common::Array<byte> &params) {}
-void Scripts::cmdTeleportAndExit(Common::Array<byte> &params) {}
-void Scripts::cmdIf1(Common::Array<byte> &params) {}
-void Scripts::cmdIf2(Common::Array<byte> &params) {}
-void Scripts::cmdIf3(Common::Array<byte> &params) {}
+void Scripts::cmdTeleport(Common::Array<byte> &params) {}
+void Scripts::cmdIf(Common::Array<byte> &params) {}
 void Scripts::cmdMoveObj(Common::Array<byte> &params) {}
 void Scripts::cmdTakeOrGive(Common::Array<byte> &params) {}
-void Scripts::cmdNoAction(Common::Array<byte> &params) {}
+
+void Scripts::cmdNoAction(Common::Array<byte> &params) {
+	// Move to next line
+	_lineNum = _vm->_party->_partyDead ? -1 : _lineNum + 1;
+}
+
 void Scripts::cmdRemove(Common::Array<byte> &params) {}
 void Scripts::cmdSetChar(Common::Array<byte> &params) {}
 void Scripts::cmdSpawn(Common::Array<byte> &params) {}
@@ -206,17 +255,13 @@ void Scripts::cmdAfterEvent(Common::Array<byte> &params) {}
 void Scripts::cmdCallEvent(Common::Array<byte> &params) {}
 void Scripts::cmdReturn(Common::Array<byte> &params) {}
 void Scripts::cmdSetVar(Common::Array<byte> &params) {}
-void Scripts::cmdTakeOrGive2(Common::Array<byte> &params) {}
-void Scripts::cmdTakeOrGive3(Common::Array<byte> &params) {}
 void Scripts::cmdCutsceneEndClouds(Common::Array<byte> &params) {}
-void Scripts::cmdTeleportAndContinue(Common::Array<byte> &params) {}
 void Scripts::cmdWhoWill(Common::Array<byte> &params) {}
 void Scripts::cmdRndDamage(Common::Array<byte> &params) {}
 void Scripts::cmdMoveWallObj(Common::Array<byte> &params) {}
 void Scripts::cmdAlterCellFlag(Common::Array<byte> &params) {}
 void Scripts::cmdAlterHed(Common::Array<byte> &params) {}
 void Scripts::cmdDisplayStat(Common::Array<byte> &params) {}
-void Scripts::cmdTakeOrGive4(Common::Array<byte> &params) {}
 void Scripts::cmdSeatTextSml(Common::Array<byte> &params) {}
 void Scripts::cmdPlayEventVoc(Common::Array<byte> &params) {}
 void Scripts::cmdDisplayBottom(Common::Array<byte> &params) {}
diff --git a/engines/xeen/scripts.h b/engines/xeen/scripts.h
index 2fbcf78..9690887 100644
--- a/engines/xeen/scripts.h
+++ b/engines/xeen/scripts.h
@@ -126,22 +126,22 @@ private:
 	int _treasureItems;
 	int _treasureGold;
 	int _treasureGems;
+	int _lineNum;
 
 	int _v2;
+	int _var4F;
 	int _nEdamageType;
+	Common::String _paramText;
 
 	void doOpcode(Opcode opcode, Common::Array<byte> &params);
-	void cmdNone(Common::Array<byte> &params);
-	void cmdDisplay0x01(Common::Array<byte> &params);
+	void cmdDisplay1(Common::Array<byte> &params);
 	void cmdDoorTextSml(Common::Array<byte> &params);
 	void cmdDoorTextLrg(Common::Array<byte> &params);
 	void cmdSignText(Common::Array<byte> &params);
 	void cmdNPC(Common::Array<byte> &params);
 	void cmdPlayFX(Common::Array<byte> &params);
-	void cmdTeleportAndExit(Common::Array<byte> &params);
-	void cmdIf1(Common::Array<byte> &params);
-	void cmdIf2(Common::Array<byte> &params);
-	void cmdIf3(Common::Array<byte> &params);
+	void cmdTeleport(Common::Array<byte> &params);
+	void cmdIf(Common::Array<byte> &params);
 	void cmdMoveObj(Common::Array<byte> &params);
 	void cmdTakeOrGive(Common::Array<byte> &params);
 	void cmdNoAction(Common::Array<byte> &params);
@@ -159,17 +159,13 @@ private:
 	void cmdCallEvent(Common::Array<byte> &params);
 	void cmdReturn(Common::Array<byte> &params);
 	void cmdSetVar(Common::Array<byte> &params);
-	void cmdTakeOrGive2(Common::Array<byte> &params);
-	void cmdTakeOrGive3(Common::Array<byte> &params);
 	void cmdCutsceneEndClouds(Common::Array<byte> &params);
-	void cmdTeleportAndContinue(Common::Array<byte> &params);
 	void cmdWhoWill(Common::Array<byte> &params);
 	void cmdRndDamage(Common::Array<byte> &params);
 	void cmdMoveWallObj(Common::Array<byte> &params);
 	void cmdAlterCellFlag(Common::Array<byte> &params);
 	void cmdAlterHed(Common::Array<byte> &params);
 	void cmdDisplayStat(Common::Array<byte> &params);
-	void cmdTakeOrGive4(Common::Array<byte> &params);
 	void cmdSeatTextSml(Common::Array<byte> &params);
 	void cmdPlayEventVoc(Common::Array<byte> &params);
 	void cmdDisplayBottom(Common::Array<byte> &params);


Commit: 16a5a99c3aa615f5b69a8c4c1df987c906973990
    https://github.com/scummvm/scummvm/commit/16a5a99c3aa615f5b69a8c4c1df987c906973990
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-01-21T22:09:12-05:00

Commit Message:
XEEN: Fix strings used by newly added script commands

Changed paths:
    engines/xeen/scripts.cpp



diff --git a/engines/xeen/scripts.cpp b/engines/xeen/scripts.cpp
index 44b5cb3..3bf7a31 100644
--- a/engines/xeen/scripts.cpp
+++ b/engines/xeen/scripts.cpp
@@ -188,7 +188,7 @@ void Scripts::doOpcode(Opcode opcode, Common::Array<byte> &params) {
  */
 void Scripts::cmdDisplay1(Common::Array<byte> &params) {
 	Screen &screen = *_vm->_screen;
-	Common::String msg = Common::String::format("\r\x03c%s", _paramText.c_str());
+	Common::String msg = Common::String::format("\r\x03""c%s", _paramText.c_str());
 
 	screen._windows[12].close();
 	if (screen._windows[38]._enabled)
@@ -205,7 +205,7 @@ void Scripts::cmdDisplay1(Common::Array<byte> &params) {
  */
 void Scripts::cmdDoorTextSml(Common::Array<byte> &params) {
 	Interface &intf = *_vm->_interface;
-	intf._screenText = Common::String::format("\x02\f08\x03c\t116\v025%s\x03l\fd\x01",
+	intf._screenText = Common::String::format("\x02\f""08\x03""c\t116\v025%s\x03""l\fd""\x01", 
 		_paramText.c_str());
 	intf._upDoorText = true;
 	intf.draw3d(true);
@@ -219,7 +219,7 @@ void Scripts::cmdDoorTextSml(Common::Array<byte> &params) {
  */
 void Scripts::cmdDoorTextLrg(Common::Array<byte> &params) {
 	Interface &intf = *_vm->_interface;
-	intf._screenText = Common::String::format("\f04\x03c\t116\v030%s\x03l\fd",
+	intf._screenText = Common::String::format("\f04\x03""c\t116\v030%s\x03""l\fd",
 		_paramText.c_str());
 	intf._upDoorText = true;
 	intf.draw3d(true);


Commit: 4c0c40c25df79d9cbed6f401b83165d90ae3b4cd
    https://github.com/scummvm/scummvm/commit/4c0c40c25df79d9cbed6f401b83165d90ae3b4cd
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-01-22T07:53:33-05:00

Commit Message:
XEEN: Shifted more logic for 3d view drawing from Interface to InterfaceMap

Changed paths:
    engines/xeen/interface.cpp
    engines/xeen/interface.h
    engines/xeen/interface_map.cpp
    engines/xeen/interface_map.h
    engines/xeen/scripts.cpp
    engines/xeen/scripts.h



diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp
index 4b4e88a..31fe00b 100644
--- a/engines/xeen/interface.cpp
+++ b/engines/xeen/interface.cpp
@@ -29,24 +29,9 @@ namespace Xeen {
 
 Interface::Interface(XeenEngine *vm) : ButtonContainer(), InterfaceMap(vm), _vm(vm) {
 	Common::fill(&_partyFaces[0], &_partyFaces[MAX_ACTIVE_PARTY], (SpriteResource *)nullptr);
-	_batUIFrame = 0;
-	_spotDoorsUIFrame = 0;
-	_dangerSenseUIFrame = 0;
-	_face1UIFrame = 0;
-	_face2UIFrame = 0;
-	_blessedUIFrame = 0;
-	_powerShieldUIFrame = 0;
-	_holyBonusUIFrame = 0;
-	_heroismUIFrame = 0;
-	_flipUIFrame = 0;
 	_buttonsLoaded = false;
 	_hiliteChar = -1;
 	_intrIndex1 = 0;
-	_flag1 = false;
-	_isAnimReset = false;
-	_tillMove = 0;
-	_overallFrame = 0;
-	_upDoorText = false;
 	_steppingFX = 0;
 
 	Common::fill(&_combatCharIds[0], &_combatCharIds[8], 0);
@@ -79,15 +64,10 @@ void Interface::initDrawStructs() {
 }
 
 void Interface::setup() {
-	_globalSprites.load("global.icn");
-	_borderSprites.load("border.icn");
-	_spellFxSprites.load("spellfx.icn");
-	_fecpSprites.load("fecp.brd");
-	_blessSprites.load("bless.icn");
+	InterfaceMap::setup();
 	_restoreSprites.load("restorex.icn");
 	_hpSprites.load("hpbars.icn");
 	_uiSprites.load("inn.icn");
-	_charPowSprites.load("charpow.icn");
 
 	// Get mappings to the active characters in the party
 	_vm->_party->_activeParty.resize(_vm->_party->_partyCount);
@@ -277,14 +257,6 @@ start:
 
 	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() {
@@ -307,114 +279,6 @@ void Interface::setupBackground() {
 	assembleBorder();
 }
 
-void Interface::assembleBorder() {
-	Screen &screen = *_vm->_screen;
-
-	// Draw the outer frame
-	_globalSprites.draw(screen._windows[0], 0, Common::Point(8, 8));
-
-	// Draw the animating bat character used to show when levitate is active
-	_borderSprites.draw(screen._windows[0], _vm->_party->_levitateActive ? _batUIFrame + 16 : 16,
-		Common::Point(0, 82));
-	_batUIFrame = (_batUIFrame + 1) % 12;
-
-	// Draw UI element to indicate whether can spot hidden doors
-	_borderSprites.draw(screen,
-		(_thinWall && _vm->_party->checkSkill(SPOT_DOORS)) ? _spotDoorsUIFrame + 28 : 28,
-		Common::Point(194, 91));
-	_spotDoorsUIFrame = (_spotDoorsUIFrame + 1) % 12;
-
-	// Draw UI element to indicate whether can sense danger
-	_borderSprites.draw(screen,
-		(_vm->_dangerSenseAllowed && _vm->_party->checkSkill(DANGER_SENSE)) ? _spotDoorsUIFrame + 40 : 40,
-		Common::Point(107, 9));
-	_dangerSenseUIFrame = (_dangerSenseUIFrame + 1) % 12;
-
-	// Handle the face UI elements for indicating clairvoyance status
-	_face1UIFrame = (_face1UIFrame + 1) % 4;
-	if (_vm->_face1State == 0)
-		_face1UIFrame += 4;
-	else if (_vm->_face1State == 2)
-		_face1UIFrame = 0;
-
-	_face2UIFrame = (_face2UIFrame + 1) % 4 + 12;
-	if (_vm->_face2State == 0)
-		_face2UIFrame += 252;
-	else if (_vm->_face2State == 2)
-		_face2UIFrame = 0;
-
-	if (!_vm->_party->_clairvoyanceActive) {
-		_face1UIFrame = 0;
-		_face2UIFrame = 8;
-	}
-
-	_borderSprites.draw(screen, _face1UIFrame, Common::Point(0, 32));
-	_borderSprites.draw(screen,
-		screen._windows[10]._enabled || screen._windows[2]._enabled ?
-		52 : _face2UIFrame,
-		Common::Point(215, 32));
-
-	// Draw resistence indicators
-	if (!screen._windows[10]._enabled && !screen._windows[2]._enabled
-		&& screen._windows[38]._enabled) {
-		_fecpSprites.draw(screen, _vm->_party->_fireResistence ? 1 : 0,
-			Common::Point(2, 2));
-		_fecpSprites.draw(screen, _vm->_party->_electricityResistence ? 3 : 2,
-			Common::Point(219, 2));
-		_fecpSprites.draw(screen, _vm->_party->_coldResistence ? 5 : 4,
-			Common::Point(2, 134));
-		_fecpSprites.draw(screen, _vm->_party->_poisonResistence ? 7 : 6,
-			Common::Point(219, 134));
-	} else {
-		_fecpSprites.draw(screen, _vm->_party->_fireResistence ? 9 : 8,
-			Common::Point(8, 8));
-		_fecpSprites.draw(screen, _vm->_party->_electricityResistence ? 10 : 11,
-			Common::Point(219, 8));
-		_fecpSprites.draw(screen, _vm->_party->_coldResistence ? 12 : 13,
-			Common::Point(8, 134));
-		_fecpSprites.draw(screen, _vm->_party->_poisonResistence ? 14 : 15,
-			Common::Point(219, 134));
-	}
-
-	// Draw UI element for blessed
-	_blessSprites.draw(screen, 16, Common::Point(33, 137));
-	if (_vm->_party->_blessedActive) {
-		_blessedUIFrame = (_blessedUIFrame + 1) % 4;
-		_blessSprites.draw(screen, _blessedUIFrame, Common::Point(33, 137));
-	}
-
-	// Draw UI element for power shield
-	if (_vm->_party->_powerShieldActive) {
-		_powerShieldUIFrame = (_powerShieldUIFrame + 1) % 4;
-		_blessSprites.draw(screen, _powerShieldUIFrame + 4,
-			Common::Point(55, 137));
-	}
-
-	// Draw UI element for holy bonus
-	if (_vm->_party->_holyBonusActive) {
-		_holyBonusUIFrame = (_holyBonusUIFrame + 1) % 4;
-		_blessSprites.draw(screen, _holyBonusUIFrame + 8, Common::Point(160, 137));
-	}
-
-	// Draw UI element for heroism
-	if (_vm->_party->_heroismActive) {
-		_heroismUIFrame = (_heroismUIFrame + 1) % 4;
-		_blessSprites.draw(screen, _heroismUIFrame + 12, Common::Point(182, 137));
-	}
-
-	// Draw direction character if direction sense is active
-	if (_vm->_party->checkSkill(DIRECTION_SENSE) && !_vm->_noDirectionSense) {
-		const char *dirText = DIRECTION_TEXT[_vm->_party->_mazeDirection];
-		Common::String msg = Common::String::format(
-			"\002""08\003""c\013""139\011""116%c\014""d\001", *dirText);
-		screen._windows[0].writeString(msg);
-	}
-
-	// Draw view frame
-	if (screen._windows[12]._enabled)
-		screen._windows[12].frame();
-}
-
 void Interface::setupFaces(int charIndex, Common::Array<int> xeenSideChars, bool updateFlag) {
 	Common::String playerNames[4];
 	Common::String playerRaces[4];
@@ -535,228 +399,6 @@ void Interface::moveCharacterToRoster() {
 	error("TODO");
 }
 
-void Interface::draw3d(bool updateFlag) {
-	Combat &combat = *_vm->_combat;
-	EventsManager &events = *_vm->_events;
-	Map &map = *_vm->_map;
-	Party &party = *_vm->_party;
-	Screen &screen = *_vm->_screen;
-	Scripts &scripts = *_vm->_scripts;
-
-	if (screen._windows[11]._enabled)
-		return;
-
-	_flipUIFrame = (_flipUIFrame + 1) % 4;
-	if (_flipUIFrame == 0)
-		_flipWater = !_flipWater;
-	if (_tillMove && (_vm->_mode == MODE_1 || _vm->_mode == MODE_2) &&
-			!_flag1 && _vm->_moveMonsters) {
-		if (--_tillMove == 0)
-			moveMonsters();
-	}
-
-	MazeObject &objObject = map._mobData._objects[_objNumber];
-	Direction partyDirection = _vm->_party->_mazeDirection;
-	int objNum = _objNumber - 1;
-
-	// Loop to update the frame numbers for each maze object, applying the animation frame
-	// limits as specified by the map's _animationInfo listing
-	for (uint idx = 0; idx < map._mobData._objects.size(); ++idx) {
-		MazeObject &mazeObject = map._mobData._objects[idx];
-		AnimationEntry &animEntry = map._animationInfo[mazeObject._spriteId];
-		int directionIndex = DIRECTION_ANIM_POSITIONS[mazeObject._direction][partyDirection];
-
-		if (_isAnimReset) {
-			mazeObject._frame = animEntry._frame1._frames[directionIndex];
-		} else {
-			++mazeObject._frame;
-			if ((int)idx == objNum && scripts._animCounter > 0 && (
-					objObject._spriteId == (_vm->_files->_isDarkCc ? 15 : 16) ||
-					objObject._spriteId == 58 || objObject._spriteId == 73)) {
-				if (mazeObject._frame > 4 || mazeObject._spriteId == 58)
-					mazeObject._frame = 1;
-			} else if (mazeObject._frame >= animEntry._frame2._frames[directionIndex]) {
-				mazeObject._frame = animEntry._frame1._frames[directionIndex];
-			}
-		}
-
-		mazeObject._flipped = animEntry._flipped._flags[directionIndex];
-	}
-
-	if (map._isOutdoors) {
-		error("TODO: draw3d outdoors handling");
-	} else {
-		// Default all the parts of draw struct not to be drawn by default
-		for (int idx = 3; idx < _indoorList.size(); ++idx)
-			_indoorList[idx]._frame = -1;
-
-		if (_flag1) {
-			for (int idx = 0; idx < 96; ++idx) {
-				if (_indoorList[79 + idx]._sprites != nullptr) {
-					_indoorList[79 + idx]._frame = 0;
-				} else if (_indoorList[111 + idx]._sprites != nullptr) {
-					_indoorList[111 + idx]._frame = 1;
-				} else if (_indoorList[135 + idx]._sprites != nullptr) {
-					_indoorList[135 + idx]._frame = 2;
-				} else if (_indoorList[162 + idx]._sprites != nullptr) {
-					_indoorList[162 + idx]._frame = 0;
-				}
-			}
-		} else if (_charsShooting) {
-			for (int idx = 0; idx < 96; ++idx) {
-				if (_indoorList[162 + idx]._sprites != nullptr) {
-					_indoorList[162 + idx]._frame = 0;
-				} else if (_indoorList[135 + idx]._sprites != nullptr) {
-					_indoorList[135 + idx]._frame = 1;
-				} else if (_indoorList[111 + idx]._sprites != nullptr) {
-					_indoorList[111 + idx]._frame = 2;
-				} else if (_indoorList[79 + idx]._sprites != nullptr) {
-					_indoorList[79 + idx]._frame = 0;
-				}
-			}
-		}
-
-		setMazeBits();
-		_isAnimReset = false;
-		const int INDOOR_INDEXES[3] = { 157, 151, 154 };
-		const int INDOOR_COMBAT_POS[3][2] = { { 102, 134 }, { 36, 67 }, { 161, 161 } };
-		const int INDOOR_COMBAT_POS2[4] = { 8, 6, 4, 2 };
-
-		// Double check this, since it's not being used?
-		//MazeObject &objObject = map._mobData._objects[_objNumber - 1];
-
-		for (int idx = 0; idx < 3; ++idx) {
-			DrawStruct &ds1 = _indoorList[INDOOR_INDEXES[idx]];
-			DrawStruct &ds2 = _indoorList[INDOOR_INDEXES[idx] + 1];
-			ds1._sprites = nullptr;
-			ds2._sprites = nullptr;
-
-			if (combat._charsArray1[idx]) {
-				int posIndex= combat._attackMonsters[1] && !combat._attackMonsters[2] ? 1 : 0;
-				--combat._charsArray1[idx];
-
-				if (combat._monPow[idx]) {
-					ds1._x = INDOOR_COMBAT_POS[idx][0];
-					ds1._frame = 0;
-					ds1._scale = combat._monsterScale[idx];
-					if (ds1._scale == 0x8000) {
-						ds1._x /= 3;
-						ds1._y = 60;
-					} else {
-						ds1._y = 73;
-					}
-
-					ds1._flags = SPRFLAG_4000 | SPRFLAG_2000;
-					ds1._sprites = &_charPowSprites;
-				}
-
-				if (combat._elemPow[idx]) {
-					ds2._x = INDOOR_COMBAT_POS[idx][posIndex] + INDOOR_COMBAT_POS2[idx];
-					ds2._frame = combat._elemPow[idx];
-					ds2._scale = combat._elemScale[idx];
-					if (ds2._scale == 0x8000)
-						ds2._x /= 3;
-					ds2._flags = SPRFLAG_4000 | SPRFLAG_2000;
-					ds2._sprites = &_charPowSprites;
-				}
-			}
-		}
-
-		setIndoorsMonsters();
-		setIndoorsObjects();
-		setIndoorsWallPics();
-
-		_indoorList[161]._sprites = nullptr;
-		_indoorList[160]._sprites = nullptr;
-		_indoorList[159]._sprites = nullptr;
-
-		// Handle attacking monsters
-		int monsterIndex = 0;
-		if (combat._attackMonsters[0] != -1 && map._mobData._monsters[combat._attackMonsters[0]]._frame >= 0) {
-			_indoorList[159] = _indoorList[156];
-			_indoorList[160] = _indoorList[157];
-			_indoorList[161] = _indoorList[158];
-			_indoorList[158]._sprites = nullptr;
-			_indoorList[156]._sprites = nullptr;
-			_indoorList[157]._sprites = nullptr;
-			monsterIndex = 1;
-		} else if (combat._attackMonsters[1] != -1 && map._mobData._monsters[combat._attackMonsters[1]]._frame >= 0) {
-			_indoorList[159] = _indoorList[150];
-			_indoorList[160] = _indoorList[151];
-			_indoorList[161] = _indoorList[152];
-			_indoorList[152]._sprites = nullptr;
-			_indoorList[151]._sprites = nullptr;
-			_indoorList[150]._sprites = nullptr;
-			monsterIndex = 2;
-		} else if (combat._attackMonsters[2] != -1 &&  map._mobData._monsters[combat._attackMonsters[2]]._frame >= 0) {
-			_indoorList[159] = _indoorList[153];
-			_indoorList[160] = _indoorList[154];
-			_indoorList[161] = _indoorList[155];
-			_indoorList[153]._sprites = nullptr;
-			_indoorList[154]._sprites = nullptr;
-			_indoorList[155]._sprites = nullptr;
-			monsterIndex = 3;
-		}
-
-		drawIndoors();
-
-		switch (monsterIndex) {
-		case 1:
-			_indoorList[156] = _indoorList[159];
-			_indoorList[157] = _indoorList[160];
-			_indoorList[158] = _indoorList[161];
-			break;
-		case 2:
-			_indoorList[150] = _indoorList[159];
-			_indoorList[151] = _indoorList[160];
-			_indoorList[152] = _indoorList[161];
-			break;
-		case 3:
-			_indoorList[153] = _indoorList[159];
-			_indoorList[154] = _indoorList[160];
-			_indoorList[155] = _indoorList[161];
-			break;
-		default:
-			break;
-		}
-	}
-
-	animate3d();
-	drawMiniMap();
-
-	if (party._falling == 1) {
-		error("TODO: Indoor falling");
-	}
-
-	if (party._falling == 2) {
-		screen.saveBackground(1);
-	}
-
-	assembleBorder();
-
-	// Draw any on-screen text if flagged to do so
-	if (_upDoorText && combat._attackMonsters[0] == -1) {
-		screen._windows[3].writeString(_screenText);
-	}
-
-	if (updateFlag) {
-		screen._windows[1].update();
-		screen._windows[3].update();
-	}
-
-	// TODO: more stuff
-
-	_vm->_party->_stepped = false;
-	if (_vm->_mode == MODE_9) {
-		// TODO
-	}
-	events.wait(2);
-}
-
-void Interface::animate3d() {
-
-}
-
 void Interface::startup() {
 	Screen &screen = *_vm->_screen;
 	loadCharIcons();
@@ -792,10 +434,6 @@ void Interface::mainIconsPrint() {
 	screen._windows[34].update();
 }
 
-void Interface::moveMonsters() {
-
-}
-
 void Interface::setMainButtons() {
 	clearButtons();
 
@@ -821,381 +459,6 @@ void Interface::setMainButtons() {
 	addButton(Common::Rect(239, 47, 312, 57), Common::KEYCODE_3, &_iconSprites, false);
 }
 
-void Interface::drawMiniMap() {
-	Map &map = *_vm->_map;
-	Party &party = *_vm->_party;
-	Screen &screen = *_vm->_screen;
-	Window &window1 = screen._windows[1];
-
-	if (screen._windows[2]._enabled || screen._windows[10]._enabled)
-		return;
-	if (!party._automapOn && !party._wizardEyeActive) {
-		// Draw the Might & Magic logo
-		_globalSprites.draw(window1, 5, Common::Point(232, 9));
-		return;
-	}
-
-	int v, frame;
-	int frame2 = _overallFrame * 2;
-	bool eyeActive = party._wizardEyeActive;
-	if (party._automapOn)
-		party._wizardEyeActive = false;
-
-	if (map._isOutdoors) {
-		_globalSprites.draw(window1, 15, Common::Point(237, 12));
-
-		for (int rowNum = 0, yp = 12, yDiff = 3; rowNum < MINIMAP_SIZE; ++rowNum, yp += 8, --yDiff) {
-			for (int colNum = 0, xp = 237, xDiff = -3; colNum < MINIMAP_SIZE; ++colNum, xp += 10, ++xDiff) {
-				v = map.mazeLookup(
-					Common::Point(party._mazePosition.x + xDiff, party._mazePosition.y + yDiff),
-					4);
-				frame = map.mazeDataCurrent()._surfaceTypes[v];
-
-				if (frame != -1 && (map._currentSteppedOn || party._wizardEyeActive)) {
-					map._tileSprites.draw(window1, frame, Common::Point(xp, yp));
-				}
-			}
-		}
-
-		for (int rowNum = 0, yp = 12, yDiff = 3; rowNum < MINIMAP_SIZE; ++rowNum, yp += 8, --yDiff) {
-			for (int colNum = 0, xp = 237, xDiff = -3; colNum < MINIMAP_SIZE; ++colNum, xp += 10, ++xDiff) {
-				v = map.mazeLookup(
-					Common::Point(party._mazePosition.x + xDiff, party._mazePosition.y + yDiff),
-					4);
-				frame = map.mazeData()._wallTypes[v];
-
-				if (frame != -1 && (map._currentSteppedOn || party._wizardEyeActive)) {
-					map._tileSprites.draw(window1, frame + 16, Common::Point(xp, yp));
-				}
-			}
-		}
-
-		for (int rowNum = 0, yp = 12, yDiff = 3; rowNum < MINIMAP_SIZE; ++rowNum, yp += 8, --yDiff) {
-			for (int colNum = 0, xp = 237, xDiff = -3; colNum < MINIMAP_SIZE; ++colNum, xp += 10, ++xDiff) {
-				v = map.mazeLookup(
-					Common::Point(party._mazePosition.x + xDiff, party._mazePosition.y + yDiff),
-					4);
-
-				if (v != -1 && (map._currentSteppedOn || party._wizardEyeActive)) {
-					map._tileSprites.draw(window1, v + 32, Common::Point(xp, yp));
-				}
-			}
-		}
-		
-		// Draw the direction arrow
-		_globalSprites.draw(window1, party._mazeDirection + 1,
-			Common::Point(267, 36));
-	} else {
-		frame2 = (frame2 + 2) % 8;
-
-		// First draw the default surface bases for each cell to show
-		for (int rowNum = 0, yp = 12, yDiff = 3; rowNum < MINIMAP_SIZE; ++rowNum, yp += 8, --yDiff) {
-			for (int colNum = 0, xp = 237, xDiff = -3; colNum < MINIMAP_SIZE; ++colNum, xp += 10, ++xDiff) {
-				v = map.mazeLookup(
-					Common::Point(party._mazePosition.x + xDiff, party._mazePosition.y + yDiff),
-					0, 0xffff);
-
-				if (v != INVALID_CELL && (map._currentSteppedOn || party._wizardEyeActive)) {
-					map._tileSprites.draw(window1, 0, Common::Point(xp, yp));
-				}
-			}
-		}
-		
-		// Draw correct surface bases for revealed tiles
-		for (int rowNum = 0, yp = 17, yDiff = 3; rowNum < MINIMAP_SIZE; ++rowNum, yp += 8, --yDiff) {
-			for (int colNum = 0, xp = 242, xDiff = -3; colNum < MINIMAP_SIZE; ++colNum, xp += 10, ++xDiff) {
-				v = map.mazeLookup(
-					Common::Point(party._mazePosition.x + xDiff, party._mazePosition.y + yDiff),
-					0, 0xffff);
-				int surfaceId = map.mazeData()._surfaceTypes[map._currentSurfaceId];
-
-				if (v != INVALID_CELL && map._currentSurfaceId &&
-						(map._currentSteppedOn || party._wizardEyeActive)) {
-					map._tileSprites.draw(window1, surfaceId + 36, Common::Point(xp, yp));
-				}
-			}
-		}
-		
-		v = map.mazeLookup(Common::Point(party._mazePosition.x - 4, party._mazePosition.y + 4), 0xffff, 0);
-		if (v != INVALID_CELL && map._currentSurfaceId &&
-				(map._currentSteppedOn || party._wizardEyeActive)) {
-			map._tileSprites.draw(window1,
-				map.mazeData()._surfaceTypes[map._currentSurfaceId] + 36,
-				Common::Point(232, 9));
-		}
-		
-		// Handle drawing surface sprites partially clipped at the left edge
-		for (int rowNum = 0, yp = 17, yDiff = 3; rowNum < MINIMAP_SIZE; ++rowNum, --yDiff, yp += 8) {
-			v = map.mazeLookup(
-					Common::Point(party._mazePosition.x - 4, party._mazePosition.y + yDiff),
-					0, 0xffff);
-
-			if (v != INVALID_CELL && map._currentSurfaceId &&
-					(map._currentSteppedOn || party._wizardEyeActive)) {
-				map._tileSprites.draw(window1,
-					map.mazeData()._surfaceTypes[map._currentSurfaceId] + 36,
-					Common::Point(232, yp));
-			}
-		}
-
-		// Handle drawing surface sprites partially clipped at the top edge
-		for (int colNum = 0, xp = 242, xDiff = -3; colNum < MINIMAP_SIZE; ++colNum, ++xDiff, xp += 8) {
-			v = map.mazeLookup(
-				Common::Point(party._mazePosition.x + xDiff, party._mazePosition.y + 4),
-				0, 0xffff);
-
-			if (v != INVALID_CELL && map._currentSurfaceId &&
-					(map._currentSteppedOn || party._wizardEyeActive)) {
-				map._tileSprites.draw(window1,
-					map.mazeData()._surfaceTypes[map._currentSurfaceId] + 36,
-					Common::Point(xp, 9));
-			}
-		}
-		
-		//
-		for (int idx = 0, xp = 237, yp = 60, xDiff = -3; idx < MINIMAP_SIZE; 
-				++idx, ++xDiff, xp += 10, yp -= 8) {
-			v = map.mazeLookup(
-				Common::Point(party._mazePosition.x - 4, party._mazePosition.y - 3 + idx),
-				12, 0xffff);
-
-			switch (v) {
-			case 1:
-				frame = 18;
-				break;
-			case 3:
-				frame = 22;
-				break;
-			case 4:
-			case 13:
-				frame = 16;
-				break;
-			case 5:
-			case 8:
-				frame = 2;
-				break;
-			case 6:
-				frame = 30;
-				break;
-			case 7:
-				frame = 32;
-				break;
-			case 9:
-				frame = 24;
-				break;
-			case 10:
-				frame = 28;
-				break;
-			case 11:
-				frame = 14;
-				break;
-			case 12:
-				frame = frame2 + 4;
-				break;
-			case 14:
-				frame = 24;
-				break;
-			case 15:
-				frame = 26;
-				break;
-			default:
-				frame = -1;
-				break;
-			}
-
-			if (frame != -1 && (map._currentSteppedOn || party._wizardEyeActive))
-				map._tileSprites.draw(window1, frame, Common::Point(222, yp));
-
-			v = map.mazeLookup(
-				Common::Point(party._mazePosition.x - 3 + idx, party._mazePosition.y + 4),
-				0);
-
-			switch (v) {
-			case 1:
-				frame = 19;
-				break;
-			case 2:
-				frame = 35;
-				break;
-			case 3:
-				frame = 23;
-				break;
-			case 4:
-			case 13:
-				frame = 17;
-				break;
-			case 5:
-			case 8:
-				frame = 3;
-				break;
-			case 6:
-				frame = 31;
-				break;
-			case 7:
-				frame = 33;
-				break;
-			case 9:
-				frame = 21;
-				break;
-			case 10:
-				frame = 29;
-				break;
-			case 11:
-				frame = 15;
-				break;
-			case 12:
-				frame = frame2 + 5;
-				break;
-			case 14:
-				frame = 25;
-				break;
-			case 15:
-				frame = 27;
-				break;
-			default:
-				frame = -1;
-				break;
-			}
-
-			if (frame != -1 && (map._currentSteppedOn || party._wizardEyeActive))
-				map._tileSprites.draw(window1, frame, Common::Point(xp, 4));
-		}
-
-		// Draw the front/back walls of cells in the minimap
-		for (int rowNum = 0, yp = 12, yDiff = 3; rowNum < MINIMAP_SIZE;
-				++rowNum, --yDiff, yp += 8) {
-			for (int colNum = 0, xp = 237, xDiff = -3; colNum < MINIMAP_SIZE;
-					++colNum, ++xDiff, xp += 10) {
-				if (colNum == 4 && rowNum == 4) {
-					// Center of the minimap. Draw the direction arrow
-					_globalSprites.draw(window1, party._mazeDirection + 1,
-						Common::Point(272, 40));
-				}
-
-				v = map.mazeLookup(Common::Point(party._mazePosition.x + xDiff,
-					party._mazePosition.y + yDiff), 12, 0xffff);
-				switch (v) {
-				case 1:
-					frame = 18;
-					break;
-				case 3:
-					frame = 22;
-					break;
-				case 4:
-				case 13:
-					frame = 16;
-					break;
-				case 5:
-				case 8:
-					frame = 2;
-					break;
-				case 6:
-					frame = 30;
-					break;
-				case 7:
-					frame = 32;
-					break;
-				case 9:
-					frame = 20;
-					break;
-				case 10:
-					frame = 28;
-					break;
-				case 11:
-					frame = 14;
-					break;
-				case 12:
-					frame = frame2 + 4;
-					break;
-				case 14:
-					frame = 24;
-					break;
-				case 15:
-					frame = 26;
-					break;
-				default:
-					frame = -1;
-					break;
-				}
-
-				if (frame != -1 && (map._currentSteppedOn || party._wizardEyeActive)) {
-					map._tileSprites.draw(window1, frame, Common::Point(xp, yp));
-				}
-
-				v = map.mazeLookup(Common::Point(party._mazePosition.x + xDiff,
-					party._mazePosition.y + yDiff), 12, 0xffff);
-				switch (v) {
-				case 1:
-					frame = 19;
-					break;
-				case 2:
-					frame = 35;
-					break;
-				case 3:
-					frame = 23;
-					break;
-				case 4:
-				case 13:
-					frame = 17;
-					break;
-				case 5:
-				case 8:
-					frame = 3;
-					break;
-				case 6:
-					frame = 31;
-					break;
-				case 7:
-					frame = 33;
-					break;
-				case 9:
-					frame = 21;
-					break;
-				case 10:
-					frame = 29;
-					break;
-				case 11:
-					frame = 15;
-					break;
-				case 12:
-					frame = frame2 + 5;
-					break;
-				case 14:
-					frame = 25;
-					break;
-				case 15:
-					frame = 27;
-					break;
-				default:
-					frame = -1;
-					break;
-				}
-
-				if (v == -1 && (map._currentSteppedOn || party._wizardEyeActive)) {
-					map._tileSprites.draw(window1, frame, Common::Point(xp, yp));
-				}
-			}
-		}
-
-		// Draw the top of blocked/wall cells on the map
-		for (int rowNum = 0, yp = 12, yDiff = 3; rowNum < MINIMAP_SIZE; ++rowNum, yp += 8, --yDiff) {
-			for (int colNum = 0, xp = 237, xDiff = -3; colNum < MINIMAP_SIZE; ++colNum, xp += 10, ++xDiff) {
-				v = map.mazeLookup(
-					Common::Point(party._mazePosition.x + xDiff, party._mazePosition.y + yDiff),
-					0, 0xffff);
-
-				if (v == INVALID_CELL || (!map._currentSteppedOn && !party._wizardEyeActive)) {
-					map._tileSprites.draw(window1, 1, Common::Point(xp, yp));
-				}
-			}
-		}
-	}
-
-	// Draw outer rectangle around the automap
-	_globalSprites.draw(window1, 6, Common::Point(223, 3));
-	party._wizardEyeActive = eyeActive;
-}
-
 /**
  * Waits for a keypress or click, whilst still allowing the game scene to
  * be animated.
diff --git a/engines/xeen/interface.h b/engines/xeen/interface.h
index 87edb02..28f2bbe 100644
--- a/engines/xeen/interface.h
+++ b/engines/xeen/interface.h
@@ -38,39 +38,19 @@ class XeenEngine;
 class Interface: public ButtonContainer, public InterfaceMap {
 private:
 	XeenEngine *_vm;
-	SpriteResource _dseFace;
-	SpriteResource _globalSprites;
-	SpriteResource _borderSprites;
-	SpriteResource _spellFxSprites;
-	SpriteResource _fecpSprites;
-	SpriteResource _blessSprites;
 	SpriteResource _restoreSprites;
+	SpriteResource _dseFace;
 	SpriteResource _hpSprites;
 	SpriteResource _uiSprites;
 	SpriteResource _iconSprites;
-	SpriteResource _charPowSprites;
 	SpriteResource _charFaces[TOTAL_CHARACTERS];
 	SpriteResource *_partyFaces[MAX_ACTIVE_PARTY];
 	DrawStruct _faceDrawStructs[4];
 	DrawStruct _mainList[16];
 	int _combatCharIds[8];
 
-	int _batUIFrame;
-	int _spotDoorsUIFrame;
-	int _dangerSenseUIFrame;
-	int _face1UIFrame;
-	int _face2UIFrame;
-	int _blessedUIFrame;
-	int _powerShieldUIFrame;
-	int _holyBonusUIFrame;
-	int _heroismUIFrame;
-	int _flipUIFrame;
 	bool _buttonsLoaded;
 	int _hiliteChar;
-	bool _flag1;
-	bool _isAnimReset;
-	byte _tillMove;
-	int _overallFrame;
 	int _steppingFX;
 	Common::String _interfaceText;
 
@@ -78,8 +58,6 @@ private:
 
 	void loadSprites();
 
-	void assembleBorder();
-
 	void setupBackground();
 
 	void setupFaces(int charIndex, Common::Array<int> xeenSideChars, bool updateFlag);
@@ -88,14 +66,8 @@ private:
 
 	void moveCharacterToRoster();
 
-	void animate3d();
-
-	void moveMonsters();
-
 	void setMainButtons();
 
-	void drawMiniMap();
-
 	void chargeStep();
 
 	void stepTime();
@@ -105,12 +77,12 @@ private:
 	bool checkMoveDirection(int key);
 public:
 	int _intrIndex1;
-	Common::String _screenText;
-	bool _upDoorText;
 public:
 	Interface(XeenEngine *vm);
 
-	void setup();
+	virtual ~Interface() {}
+
+	virtual void setup();
 
 	void manageCharacters(bool soundPlayed);
 
@@ -118,8 +90,6 @@ public:
 
 	void loadPartyIcons();
 
-	void draw3d(bool updateFlag);
-
 	void startup();
 
 	void mainIconsPrint();
diff --git a/engines/xeen/interface_map.cpp b/engines/xeen/interface_map.cpp
index 4ff64b3..be344ae 100644
--- a/engines/xeen/interface_map.cpp
+++ b/engines/xeen/interface_map.cpp
@@ -374,9 +374,266 @@ InterfaceMap::InterfaceMap(XeenEngine *vm): _vm(vm) {
 	_objNumber = 0;
 	_combatFloatCounter = 0;
 	_thinWall = false;
+	_isAnimReset = false;
+	_upDoorText = false;
+	_batUIFrame = 0;
+	_spotDoorsUIFrame = 0;
+	_dangerSenseUIFrame = 0;
+	_face1UIFrame = 0;
+	_face2UIFrame = 0;
+	_blessedUIFrame = 0;
+	_powerShieldUIFrame = 0;
+	_holyBonusUIFrame = 0;
+	_heroismUIFrame = 0;
+	_flipUIFrame = 0;
+	_tillMove = 0;
+	_flag1 = false;
+	_overallFrame = 0;
+}
+
+void InterfaceMap::setup() {
+	_globalSprites.load("global.icn");
+	_borderSprites.load("border.icn");
+	_spellFxSprites.load("spellfx.icn");
+	_fecpSprites.load("fecp.brd");
+	_blessSprites.load("bless.icn");
+	_charPowSprites.load("charpow.icn");
 }
 
+void InterfaceMap::draw3d(bool updateFlag) {
+	Combat &combat = *_vm->_combat;
+	EventsManager &events = *_vm->_events;
+	Map &map = *_vm->_map;
+	Party &party = *_vm->_party;
+	Screen &screen = *_vm->_screen;
+	Scripts &scripts = *_vm->_scripts;
+
+	if (screen._windows[11]._enabled)
+		return;
+
+	_flipUIFrame = (_flipUIFrame + 1) % 4;
+	if (_flipUIFrame == 0)
+		_flipWater = !_flipWater;
+	if (_tillMove && (_vm->_mode == MODE_1 || _vm->_mode == MODE_2) &&
+		!_flag1 && _vm->_moveMonsters) {
+		if (--_tillMove == 0)
+			moveMonsters();
+	}
+
+	MazeObject &objObject = map._mobData._objects[_objNumber];
+	Direction partyDirection = _vm->_party->_mazeDirection;
+	int objNum = _objNumber - 1;
+
+	// Loop to update the frame numbers for each maze object, applying the animation frame
+	// limits as specified by the map's _animationInfo listing
+	for (uint idx = 0; idx < map._mobData._objects.size(); ++idx) {
+		MazeObject &mazeObject = map._mobData._objects[idx];
+		AnimationEntry &animEntry = map._animationInfo[mazeObject._spriteId];
+		int directionIndex = DIRECTION_ANIM_POSITIONS[mazeObject._direction][partyDirection];
+
+		if (_isAnimReset) {
+			mazeObject._frame = animEntry._frame1._frames[directionIndex];
+		}
+		else {
+			++mazeObject._frame;
+			if ((int)idx == objNum && scripts._animCounter > 0 && (
+				objObject._spriteId == (_vm->_files->_isDarkCc ? 15 : 16) ||
+				objObject._spriteId == 58 || objObject._spriteId == 73)) {
+				if (mazeObject._frame > 4 || mazeObject._spriteId == 58)
+					mazeObject._frame = 1;
+			}
+			else if (mazeObject._frame >= animEntry._frame2._frames[directionIndex]) {
+				mazeObject._frame = animEntry._frame1._frames[directionIndex];
+			}
+		}
+
+		mazeObject._flipped = animEntry._flipped._flags[directionIndex];
+	}
+
+	if (map._isOutdoors) {
+		error("TODO: draw3d outdoors handling");
+	}
+	else {
+		// Default all the parts of draw struct not to be drawn by default
+		for (int idx = 3; idx < _indoorList.size(); ++idx)
+			_indoorList[idx]._frame = -1;
+
+		if (_flag1) {
+			for (int idx = 0; idx < 96; ++idx) {
+				if (_indoorList[79 + idx]._sprites != nullptr) {
+					_indoorList[79 + idx]._frame = 0;
+				}
+				else if (_indoorList[111 + idx]._sprites != nullptr) {
+					_indoorList[111 + idx]._frame = 1;
+				}
+				else if (_indoorList[135 + idx]._sprites != nullptr) {
+					_indoorList[135 + idx]._frame = 2;
+				}
+				else if (_indoorList[162 + idx]._sprites != nullptr) {
+					_indoorList[162 + idx]._frame = 0;
+				}
+			}
+		}
+		else if (_charsShooting) {
+			for (int idx = 0; idx < 96; ++idx) {
+				if (_indoorList[162 + idx]._sprites != nullptr) {
+					_indoorList[162 + idx]._frame = 0;
+				}
+				else if (_indoorList[135 + idx]._sprites != nullptr) {
+					_indoorList[135 + idx]._frame = 1;
+				}
+				else if (_indoorList[111 + idx]._sprites != nullptr) {
+					_indoorList[111 + idx]._frame = 2;
+				}
+				else if (_indoorList[79 + idx]._sprites != nullptr) {
+					_indoorList[79 + idx]._frame = 0;
+				}
+			}
+		}
+
+		setMazeBits();
+		_isAnimReset = false;
+		const int INDOOR_INDEXES[3] = { 157, 151, 154 };
+		const int INDOOR_COMBAT_POS[3][2] = { { 102, 134 }, { 36, 67 }, { 161, 161 } };
+		const int INDOOR_COMBAT_POS2[4] = { 8, 6, 4, 2 };
+
+		// Double check this, since it's not being used?
+		//MazeObject &objObject = map._mobData._objects[_objNumber - 1];
+
+		for (int idx = 0; idx < 3; ++idx) {
+			DrawStruct &ds1 = _indoorList[INDOOR_INDEXES[idx]];
+			DrawStruct &ds2 = _indoorList[INDOOR_INDEXES[idx] + 1];
+			ds1._sprites = nullptr;
+			ds2._sprites = nullptr;
+
+			if (combat._charsArray1[idx]) {
+				int posIndex = combat._attackMonsters[1] && !combat._attackMonsters[2] ? 1 : 0;
+				--combat._charsArray1[idx];
+
+				if (combat._monPow[idx]) {
+					ds1._x = INDOOR_COMBAT_POS[idx][0];
+					ds1._frame = 0;
+					ds1._scale = combat._monsterScale[idx];
+					if (ds1._scale == 0x8000) {
+						ds1._x /= 3;
+						ds1._y = 60;
+					}
+					else {
+						ds1._y = 73;
+					}
+
+					ds1._flags = SPRFLAG_4000 | SPRFLAG_2000;
+					ds1._sprites = &_charPowSprites;
+				}
 
+				if (combat._elemPow[idx]) {
+					ds2._x = INDOOR_COMBAT_POS[idx][posIndex] + INDOOR_COMBAT_POS2[idx];
+					ds2._frame = combat._elemPow[idx];
+					ds2._scale = combat._elemScale[idx];
+					if (ds2._scale == 0x8000)
+						ds2._x /= 3;
+					ds2._flags = SPRFLAG_4000 | SPRFLAG_2000;
+					ds2._sprites = &_charPowSprites;
+				}
+			}
+		}
+
+		setIndoorsMonsters();
+		setIndoorsObjects();
+		setIndoorsWallPics();
+
+		_indoorList[161]._sprites = nullptr;
+		_indoorList[160]._sprites = nullptr;
+		_indoorList[159]._sprites = nullptr;
+
+		// Handle attacking monsters
+		int monsterIndex = 0;
+		if (combat._attackMonsters[0] != -1 && map._mobData._monsters[combat._attackMonsters[0]]._frame >= 0) {
+			_indoorList[159] = _indoorList[156];
+			_indoorList[160] = _indoorList[157];
+			_indoorList[161] = _indoorList[158];
+			_indoorList[158]._sprites = nullptr;
+			_indoorList[156]._sprites = nullptr;
+			_indoorList[157]._sprites = nullptr;
+			monsterIndex = 1;
+		}
+		else if (combat._attackMonsters[1] != -1 && map._mobData._monsters[combat._attackMonsters[1]]._frame >= 0) {
+			_indoorList[159] = _indoorList[150];
+			_indoorList[160] = _indoorList[151];
+			_indoorList[161] = _indoorList[152];
+			_indoorList[152]._sprites = nullptr;
+			_indoorList[151]._sprites = nullptr;
+			_indoorList[150]._sprites = nullptr;
+			monsterIndex = 2;
+		}
+		else if (combat._attackMonsters[2] != -1 && map._mobData._monsters[combat._attackMonsters[2]]._frame >= 0) {
+			_indoorList[159] = _indoorList[153];
+			_indoorList[160] = _indoorList[154];
+			_indoorList[161] = _indoorList[155];
+			_indoorList[153]._sprites = nullptr;
+			_indoorList[154]._sprites = nullptr;
+			_indoorList[155]._sprites = nullptr;
+			monsterIndex = 3;
+		}
+
+		drawIndoors();
+
+		switch (monsterIndex) {
+		case 1:
+			_indoorList[156] = _indoorList[159];
+			_indoorList[157] = _indoorList[160];
+			_indoorList[158] = _indoorList[161];
+			break;
+		case 2:
+			_indoorList[150] = _indoorList[159];
+			_indoorList[151] = _indoorList[160];
+			_indoorList[152] = _indoorList[161];
+			break;
+		case 3:
+			_indoorList[153] = _indoorList[159];
+			_indoorList[154] = _indoorList[160];
+			_indoorList[155] = _indoorList[161];
+			break;
+		default:
+			break;
+		}
+	}
+
+	animate3d();
+	drawMiniMap();
+
+	if (party._falling == 1) {
+		error("TODO: Indoor falling");
+	}
+
+	if (party._falling == 2) {
+		screen.saveBackground(1);
+	}
+
+	assembleBorder();
+
+	// Draw any on-screen text if flagged to do so
+	if (_upDoorText && combat._attackMonsters[0] == -1) {
+		screen._windows[3].writeString(_screenText);
+	}
+
+	if (updateFlag) {
+		screen._windows[1].update();
+		screen._windows[3].update();
+	}
+
+	// TODO: more stuff
+
+	_vm->_party->_stepped = false;
+	if (_vm->_mode == MODE_9) {
+		// TODO
+	}
+	events.wait(2);
+}
+
+void InterfaceMap::animate3d() {
+
+}
 void InterfaceMap::setMazeBits() {
 	Common::fill(&_wo[0], &_wo[308], 0);
 
@@ -3453,4 +3710,491 @@ void InterfaceMap::drawIndoors() {
 	_charsShooting = _isShooting;
 }
 
+void InterfaceMap::moveMonsters() {
+	// TODO
+}
+
+void InterfaceMap::assembleBorder() {
+	Screen &screen = *_vm->_screen;
+
+	// Draw the outer frame
+	_globalSprites.draw(screen._windows[0], 0, Common::Point(8, 8));
+
+	// Draw the animating bat character used to show when levitate is active
+	_borderSprites.draw(screen._windows[0], _vm->_party->_levitateActive ? _batUIFrame + 16 : 16,
+		Common::Point(0, 82));
+	_batUIFrame = (_batUIFrame + 1) % 12;
+
+	// Draw UI element to indicate whether can spot hidden doors
+	_borderSprites.draw(screen,
+		(_thinWall && _vm->_party->checkSkill(SPOT_DOORS)) ? _spotDoorsUIFrame + 28 : 28,
+		Common::Point(194, 91));
+	_spotDoorsUIFrame = (_spotDoorsUIFrame + 1) % 12;
+
+	// Draw UI element to indicate whether can sense danger
+	_borderSprites.draw(screen,
+		(_vm->_dangerSenseAllowed && _vm->_party->checkSkill(DANGER_SENSE)) ? _spotDoorsUIFrame + 40 : 40,
+		Common::Point(107, 9));
+	_dangerSenseUIFrame = (_dangerSenseUIFrame + 1) % 12;
+
+	// Handle the face UI elements for indicating clairvoyance status
+	_face1UIFrame = (_face1UIFrame + 1) % 4;
+	if (_vm->_face1State == 0)
+		_face1UIFrame += 4;
+	else if (_vm->_face1State == 2)
+		_face1UIFrame = 0;
+
+	_face2UIFrame = (_face2UIFrame + 1) % 4 + 12;
+	if (_vm->_face2State == 0)
+		_face2UIFrame += 252;
+	else if (_vm->_face2State == 2)
+		_face2UIFrame = 0;
+
+	if (!_vm->_party->_clairvoyanceActive) {
+		_face1UIFrame = 0;
+		_face2UIFrame = 8;
+	}
+
+	_borderSprites.draw(screen, _face1UIFrame, Common::Point(0, 32));
+	_borderSprites.draw(screen,
+		screen._windows[10]._enabled || screen._windows[2]._enabled ?
+		52 : _face2UIFrame,
+		Common::Point(215, 32));
+
+	// Draw resistence indicators
+	if (!screen._windows[10]._enabled && !screen._windows[2]._enabled
+		&& screen._windows[38]._enabled) {
+		_fecpSprites.draw(screen, _vm->_party->_fireResistence ? 1 : 0,
+			Common::Point(2, 2));
+		_fecpSprites.draw(screen, _vm->_party->_electricityResistence ? 3 : 2,
+			Common::Point(219, 2));
+		_fecpSprites.draw(screen, _vm->_party->_coldResistence ? 5 : 4,
+			Common::Point(2, 134));
+		_fecpSprites.draw(screen, _vm->_party->_poisonResistence ? 7 : 6,
+			Common::Point(219, 134));
+	} else {
+		_fecpSprites.draw(screen, _vm->_party->_fireResistence ? 9 : 8,
+			Common::Point(8, 8));
+		_fecpSprites.draw(screen, _vm->_party->_electricityResistence ? 10 : 11,
+			Common::Point(219, 8));
+		_fecpSprites.draw(screen, _vm->_party->_coldResistence ? 12 : 13,
+			Common::Point(8, 134));
+		_fecpSprites.draw(screen, _vm->_party->_poisonResistence ? 14 : 15,
+			Common::Point(219, 134));
+	}
+
+	// Draw UI element for blessed
+	_blessSprites.draw(screen, 16, Common::Point(33, 137));
+	if (_vm->_party->_blessedActive) {
+		_blessedUIFrame = (_blessedUIFrame + 1) % 4;
+		_blessSprites.draw(screen, _blessedUIFrame, Common::Point(33, 137));
+	}
+
+	// Draw UI element for power shield
+	if (_vm->_party->_powerShieldActive) {
+		_powerShieldUIFrame = (_powerShieldUIFrame + 1) % 4;
+		_blessSprites.draw(screen, _powerShieldUIFrame + 4,
+			Common::Point(55, 137));
+	}
+
+	// Draw UI element for holy bonus
+	if (_vm->_party->_holyBonusActive) {
+		_holyBonusUIFrame = (_holyBonusUIFrame + 1) % 4;
+		_blessSprites.draw(screen, _holyBonusUIFrame + 8, Common::Point(160, 137));
+	}
+
+	// Draw UI element for heroism
+	if (_vm->_party->_heroismActive) {
+		_heroismUIFrame = (_heroismUIFrame + 1) % 4;
+		_blessSprites.draw(screen, _heroismUIFrame + 12, Common::Point(182, 137));
+	}
+
+	// Draw direction character if direction sense is active
+	if (_vm->_party->checkSkill(DIRECTION_SENSE) && !_vm->_noDirectionSense) {
+		const char *dirText = DIRECTION_TEXT[_vm->_party->_mazeDirection];
+		Common::String msg = Common::String::format(
+			"\002""08\003""c\013""139\011""116%c\014""d\001", *dirText);
+		screen._windows[0].writeString(msg);
+	}
+
+	// Draw view frame
+	if (screen._windows[12]._enabled)
+		screen._windows[12].frame();
+}
+
+void InterfaceMap::drawMiniMap() {
+	Map &map = *_vm->_map;
+	Party &party = *_vm->_party;
+	Screen &screen = *_vm->_screen;
+	Window &window1 = screen._windows[1];
+
+	if (screen._windows[2]._enabled || screen._windows[10]._enabled)
+		return;
+	if (!party._automapOn && !party._wizardEyeActive) {
+		// Draw the Might & Magic logo
+		_globalSprites.draw(window1, 5, Common::Point(232, 9));
+		return;
+	}
+
+	int v, frame;
+	int frame2 = _overallFrame * 2;
+	bool eyeActive = party._wizardEyeActive;
+	if (party._automapOn)
+		party._wizardEyeActive = false;
+
+	if (map._isOutdoors) {
+		_globalSprites.draw(window1, 15, Common::Point(237, 12));
+
+		for (int rowNum = 0, yp = 12, yDiff = 3; rowNum < MINIMAP_SIZE; ++rowNum, yp += 8, --yDiff) {
+			for (int colNum = 0, xp = 237, xDiff = -3; colNum < MINIMAP_SIZE; ++colNum, xp += 10, ++xDiff) {
+				v = map.mazeLookup(
+					Common::Point(party._mazePosition.x + xDiff, party._mazePosition.y + yDiff),
+					4);
+				frame = map.mazeDataCurrent()._surfaceTypes[v];
+
+				if (frame != -1 && (map._currentSteppedOn || party._wizardEyeActive)) {
+					map._tileSprites.draw(window1, frame, Common::Point(xp, yp));
+				}
+			}
+		}
+
+		for (int rowNum = 0, yp = 12, yDiff = 3; rowNum < MINIMAP_SIZE; ++rowNum, yp += 8, --yDiff) {
+			for (int colNum = 0, xp = 237, xDiff = -3; colNum < MINIMAP_SIZE; ++colNum, xp += 10, ++xDiff) {
+				v = map.mazeLookup(
+					Common::Point(party._mazePosition.x + xDiff, party._mazePosition.y + yDiff),
+					4);
+				frame = map.mazeData()._wallTypes[v];
+
+				if (frame != -1 && (map._currentSteppedOn || party._wizardEyeActive)) {
+					map._tileSprites.draw(window1, frame + 16, Common::Point(xp, yp));
+				}
+			}
+		}
+
+		for (int rowNum = 0, yp = 12, yDiff = 3; rowNum < MINIMAP_SIZE; ++rowNum, yp += 8, --yDiff) {
+			for (int colNum = 0, xp = 237, xDiff = -3; colNum < MINIMAP_SIZE; ++colNum, xp += 10, ++xDiff) {
+				v = map.mazeLookup(
+					Common::Point(party._mazePosition.x + xDiff, party._mazePosition.y + yDiff),
+					4);
+
+				if (v != -1 && (map._currentSteppedOn || party._wizardEyeActive)) {
+					map._tileSprites.draw(window1, v + 32, Common::Point(xp, yp));
+				}
+			}
+		}
+		
+		// Draw the direction arrow
+		_globalSprites.draw(window1, party._mazeDirection + 1,
+			Common::Point(267, 36));
+	} else {
+		frame2 = (frame2 + 2) % 8;
+
+		// First draw the default surface bases for each cell to show
+		for (int rowNum = 0, yp = 12, yDiff = 3; rowNum < MINIMAP_SIZE; ++rowNum, yp += 8, --yDiff) {
+			for (int colNum = 0, xp = 237, xDiff = -3; colNum < MINIMAP_SIZE; ++colNum, xp += 10, ++xDiff) {
+				v = map.mazeLookup(
+					Common::Point(party._mazePosition.x + xDiff, party._mazePosition.y + yDiff),
+					0, 0xffff);
+
+				if (v != INVALID_CELL && (map._currentSteppedOn || party._wizardEyeActive)) {
+					map._tileSprites.draw(window1, 0, Common::Point(xp, yp));
+				}
+			}
+		}
+		
+		// Draw correct surface bases for revealed tiles
+		for (int rowNum = 0, yp = 17, yDiff = 3; rowNum < MINIMAP_SIZE; ++rowNum, yp += 8, --yDiff) {
+			for (int colNum = 0, xp = 242, xDiff = -3; colNum < MINIMAP_SIZE; ++colNum, xp += 10, ++xDiff) {
+				v = map.mazeLookup(
+					Common::Point(party._mazePosition.x + xDiff, party._mazePosition.y + yDiff),
+					0, 0xffff);
+				int surfaceId = map.mazeData()._surfaceTypes[map._currentSurfaceId];
+
+				if (v != INVALID_CELL && map._currentSurfaceId &&
+						(map._currentSteppedOn || party._wizardEyeActive)) {
+					map._tileSprites.draw(window1, surfaceId + 36, Common::Point(xp, yp));
+				}
+			}
+		}
+		
+		v = map.mazeLookup(Common::Point(party._mazePosition.x - 4, party._mazePosition.y + 4), 0xffff, 0);
+		if (v != INVALID_CELL && map._currentSurfaceId &&
+				(map._currentSteppedOn || party._wizardEyeActive)) {
+			map._tileSprites.draw(window1,
+				map.mazeData()._surfaceTypes[map._currentSurfaceId] + 36,
+				Common::Point(232, 9));
+		}
+		
+		// Handle drawing surface sprites partially clipped at the left edge
+		for (int rowNum = 0, yp = 17, yDiff = 3; rowNum < MINIMAP_SIZE; ++rowNum, --yDiff, yp += 8) {
+			v = map.mazeLookup(
+					Common::Point(party._mazePosition.x - 4, party._mazePosition.y + yDiff),
+					0, 0xffff);
+
+			if (v != INVALID_CELL && map._currentSurfaceId &&
+					(map._currentSteppedOn || party._wizardEyeActive)) {
+				map._tileSprites.draw(window1,
+					map.mazeData()._surfaceTypes[map._currentSurfaceId] + 36,
+					Common::Point(232, yp));
+			}
+		}
+
+		// Handle drawing surface sprites partially clipped at the top edge
+		for (int colNum = 0, xp = 242, xDiff = -3; colNum < MINIMAP_SIZE; ++colNum, ++xDiff, xp += 8) {
+			v = map.mazeLookup(
+				Common::Point(party._mazePosition.x + xDiff, party._mazePosition.y + 4),
+				0, 0xffff);
+
+			if (v != INVALID_CELL && map._currentSurfaceId &&
+					(map._currentSteppedOn || party._wizardEyeActive)) {
+				map._tileSprites.draw(window1,
+					map.mazeData()._surfaceTypes[map._currentSurfaceId] + 36,
+					Common::Point(xp, 9));
+			}
+		}
+		
+		//
+		for (int idx = 0, xp = 237, yp = 60, xDiff = -3; idx < MINIMAP_SIZE; 
+				++idx, ++xDiff, xp += 10, yp -= 8) {
+			v = map.mazeLookup(
+				Common::Point(party._mazePosition.x - 4, party._mazePosition.y - 3 + idx),
+				12, 0xffff);
+
+			switch (v) {
+			case 1:
+				frame = 18;
+				break;
+			case 3:
+				frame = 22;
+				break;
+			case 4:
+			case 13:
+				frame = 16;
+				break;
+			case 5:
+			case 8:
+				frame = 2;
+				break;
+			case 6:
+				frame = 30;
+				break;
+			case 7:
+				frame = 32;
+				break;
+			case 9:
+				frame = 24;
+				break;
+			case 10:
+				frame = 28;
+				break;
+			case 11:
+				frame = 14;
+				break;
+			case 12:
+				frame = frame2 + 4;
+				break;
+			case 14:
+				frame = 24;
+				break;
+			case 15:
+				frame = 26;
+				break;
+			default:
+				frame = -1;
+				break;
+			}
+
+			if (frame != -1 && (map._currentSteppedOn || party._wizardEyeActive))
+				map._tileSprites.draw(window1, frame, Common::Point(222, yp));
+
+			v = map.mazeLookup(
+				Common::Point(party._mazePosition.x - 3 + idx, party._mazePosition.y + 4),
+				0);
+
+			switch (v) {
+			case 1:
+				frame = 19;
+				break;
+			case 2:
+				frame = 35;
+				break;
+			case 3:
+				frame = 23;
+				break;
+			case 4:
+			case 13:
+				frame = 17;
+				break;
+			case 5:
+			case 8:
+				frame = 3;
+				break;
+			case 6:
+				frame = 31;
+				break;
+			case 7:
+				frame = 33;
+				break;
+			case 9:
+				frame = 21;
+				break;
+			case 10:
+				frame = 29;
+				break;
+			case 11:
+				frame = 15;
+				break;
+			case 12:
+				frame = frame2 + 5;
+				break;
+			case 14:
+				frame = 25;
+				break;
+			case 15:
+				frame = 27;
+				break;
+			default:
+				frame = -1;
+				break;
+			}
+
+			if (frame != -1 && (map._currentSteppedOn || party._wizardEyeActive))
+				map._tileSprites.draw(window1, frame, Common::Point(xp, 4));
+		}
+
+		// Draw the front/back walls of cells in the minimap
+		for (int rowNum = 0, yp = 12, yDiff = 3; rowNum < MINIMAP_SIZE;
+				++rowNum, --yDiff, yp += 8) {
+			for (int colNum = 0, xp = 237, xDiff = -3; colNum < MINIMAP_SIZE;
+					++colNum, ++xDiff, xp += 10) {
+				if (colNum == 4 && rowNum == 4) {
+					// Center of the minimap. Draw the direction arrow
+					_globalSprites.draw(window1, party._mazeDirection + 1,
+						Common::Point(272, 40));
+				}
+
+				v = map.mazeLookup(Common::Point(party._mazePosition.x + xDiff,
+					party._mazePosition.y + yDiff), 12, 0xffff);
+				switch (v) {
+				case 1:
+					frame = 18;
+					break;
+				case 3:
+					frame = 22;
+					break;
+				case 4:
+				case 13:
+					frame = 16;
+					break;
+				case 5:
+				case 8:
+					frame = 2;
+					break;
+				case 6:
+					frame = 30;
+					break;
+				case 7:
+					frame = 32;
+					break;
+				case 9:
+					frame = 20;
+					break;
+				case 10:
+					frame = 28;
+					break;
+				case 11:
+					frame = 14;
+					break;
+				case 12:
+					frame = frame2 + 4;
+					break;
+				case 14:
+					frame = 24;
+					break;
+				case 15:
+					frame = 26;
+					break;
+				default:
+					frame = -1;
+					break;
+				}
+
+				if (frame != -1 && (map._currentSteppedOn || party._wizardEyeActive)) {
+					map._tileSprites.draw(window1, frame, Common::Point(xp, yp));
+				}
+
+				v = map.mazeLookup(Common::Point(party._mazePosition.x + xDiff,
+					party._mazePosition.y + yDiff), 12, 0xffff);
+				switch (v) {
+				case 1:
+					frame = 19;
+					break;
+				case 2:
+					frame = 35;
+					break;
+				case 3:
+					frame = 23;
+					break;
+				case 4:
+				case 13:
+					frame = 17;
+					break;
+				case 5:
+				case 8:
+					frame = 3;
+					break;
+				case 6:
+					frame = 31;
+					break;
+				case 7:
+					frame = 33;
+					break;
+				case 9:
+					frame = 21;
+					break;
+				case 10:
+					frame = 29;
+					break;
+				case 11:
+					frame = 15;
+					break;
+				case 12:
+					frame = frame2 + 5;
+					break;
+				case 14:
+					frame = 25;
+					break;
+				case 15:
+					frame = 27;
+					break;
+				default:
+					frame = -1;
+					break;
+				}
+
+				if (v == -1 && (map._currentSteppedOn || party._wizardEyeActive)) {
+					map._tileSprites.draw(window1, frame, Common::Point(xp, yp));
+				}
+			}
+		}
+
+		// Draw the top of blocked/wall cells on the map
+		for (int rowNum = 0, yp = 12, yDiff = 3; rowNum < MINIMAP_SIZE; ++rowNum, yp += 8, --yDiff) {
+			for (int colNum = 0, xp = 237, xDiff = -3; colNum < MINIMAP_SIZE; ++colNum, xp += 10, ++xDiff) {
+				v = map.mazeLookup(
+					Common::Point(party._mazePosition.x + xDiff, party._mazePosition.y + yDiff),
+					0, 0xffff);
+
+				if (v == INVALID_CELL || (!map._currentSteppedOn && !party._wizardEyeActive)) {
+					map._tileSprites.draw(window1, 1, Common::Point(xp, yp));
+				}
+			}
+		}
+	}
+
+	// Draw outer rectangle around the automap
+	_globalSprites.draw(window1, 6, Common::Point(223, 3));
+	party._wizardEyeActive = eyeActive;
+}
+
 } // End of namespace Xeen
diff --git a/engines/xeen/interface_map.h b/engines/xeen/interface_map.h
index 189598b..12e5ac6 100644
--- a/engines/xeen/interface_map.h
+++ b/engines/xeen/interface_map.h
@@ -83,6 +83,11 @@ public:
 class InterfaceMap {
 private:
 	XeenEngine *_vm;
+	SpriteResource _borderSprites;
+	SpriteResource _spellFxSprites;
+	SpriteResource _fecpSprites;
+	SpriteResource _blessSprites;
+	SpriteResource _charPowSprites;
 	int _combatFloatCounter;
 
 	void initDrawStructs();
@@ -90,9 +95,9 @@ private:
 	void setMonsterSprite(DrawStruct &drawStruct, MazeMonster &monster, 
 		SpriteResource *sprites, int frame, int defaultY);
 protected:
+	SpriteResource _globalSprites;
 	int8 _wp[20];
 	byte _wo[308];
-	int _overallFrame;
 	bool _flipWater;
 	bool _flipGround;
 	bool _flipSky;
@@ -101,14 +106,44 @@ protected:
 	bool _charsShooting;
 	int _objNumber;
 	bool _thinWall;
+	bool _isAnimReset;
+	int _batUIFrame;
+	int _spotDoorsUIFrame;
+	int _dangerSenseUIFrame;
+	int _face1UIFrame;
+	int _face2UIFrame;
+	int _blessedUIFrame;
+	int _powerShieldUIFrame;
+	int _holyBonusUIFrame;
+	int _heroismUIFrame;
+	int _flipUIFrame;
+	byte _tillMove;
+	bool _flag1;
+	int _overallFrame;
 
 	void setMazeBits();
+
+	void animate3d();
+
+	void moveMonsters();
+
+	void drawMiniMap();
+
+	void assembleBorder();
+
+	virtual void setup();
 public:
 	OutdoorDrawList _outdoorList;
 	IndoorDrawList _indoorList;
+	bool _upDoorText;
+	Common::String _screenText;
 public:
 	InterfaceMap(XeenEngine *vm);
 
+	virtual ~InterfaceMap() {}
+
+	void draw3d(bool updateFlag);
+
 	void setIndoorsMonsters();
 
 	void setIndoorsObjects();
diff --git a/engines/xeen/scripts.cpp b/engines/xeen/scripts.cpp
index 3bf7a31..73c0445 100644
--- a/engines/xeen/scripts.cpp
+++ b/engines/xeen/scripts.cpp
@@ -129,7 +129,7 @@ void Scripts::checkEvents() {
 						_vm->_mode = MODE_9;
 						_paramText = event._parameters.size() == 0 ? "" :
 							map._events._text[event._parameters[0]];
-						doOpcode(event._opcode, event._parameters);
+						doOpcode(event);
 						break;
 					} else {
 						var50 = true;
@@ -154,7 +154,10 @@ void Scripts::openGrate(int v1, int v2) {
 
 typedef void(Scripts::*ScriptMethodPtr)(Common::Array<byte> &);
 
-void Scripts::doOpcode(Opcode opcode, Common::Array<byte> &params) {
+/**
+ * Handles executing a given script command
+ */
+void Scripts::doOpcode(MazeEvent &event) {
 	static const ScriptMethodPtr COMMAND_LIST[] = {
 		nullptr, &Scripts::cmdDisplay1, &Scripts::cmdDoorTextSml,
 		&Scripts::cmdDoorTextLrg, &Scripts::cmdSignText,
@@ -180,7 +183,8 @@ void Scripts::doOpcode(Opcode opcode, Common::Array<byte> &params) {
 		&Scripts::cmdCutsceneEdWorld, &Scripts::cmdFlipWorld, &Scripts::cmdPlayCD
 	};
 
-	(this->*COMMAND_LIST[opcode])(params);
+	_event = &event;
+	(this->*COMMAND_LIST[event._opcode])(event._parameters);
 }
 
 /**
@@ -209,8 +213,8 @@ void Scripts::cmdDoorTextSml(Common::Array<byte> &params) {
 		_paramText.c_str());
 	intf._upDoorText = true;
 	intf.draw3d(true);
-	_var4F = true;
 
+	_var4F = true;
 	cmdNoAction(params);
 }
 
@@ -223,16 +227,52 @@ void Scripts::cmdDoorTextLrg(Common::Array<byte> &params) {
 		_paramText.c_str());
 	intf._upDoorText = true;
 	intf.draw3d(true);
+
 	_var4F = true;
+	cmdNoAction(params);
+}
 
+void Scripts::cmdSignText(Common::Array<byte> &params) {
+	Interface &intf = *_vm->_interface;
+	intf._screenText = Common::String::format("\f08\x03""c\t120\v088%s\x03""l\fd",
+		_paramText.c_str());
+	intf._upDoorText = true;
+	intf.draw3d(true);
+
+	_var4F = true;
 	cmdNoAction(params);
 }
 
-void Scripts::cmdSignText(Common::Array<byte> &params) {}
-void Scripts::cmdNPC(Common::Array<byte> &params) {}
-void Scripts::cmdPlayFX(Common::Array<byte> &params) {}
-void Scripts::cmdTeleport(Common::Array<byte> &params) {}
-void Scripts::cmdIf(Common::Array<byte> &params) {}
+void Scripts::cmdNPC(Common::Array<byte> &params) {
+	warning("TODO: cmdNPC");
+}
+
+void Scripts::cmdPlayFX(Common::Array<byte> &params) {
+	_vm->_sound->playFX(params[0]);
+
+	_var4F = true;
+	cmdNoAction(params);
+}
+
+void Scripts::cmdTeleport(Common::Array<byte> &params) {
+}
+
+void Scripts::cmdIf(Common::Array<byte> &params) {
+	switch (params[0]) {
+	case 16:
+	case 34:
+	case 100:
+		break;
+	case 25:
+	case 35:
+	case 101:
+	case 106:
+		break;
+	default:
+		break;
+	}
+}
+
 void Scripts::cmdMoveObj(Common::Array<byte> &params) {}
 void Scripts::cmdTakeOrGive(Common::Array<byte> &params) {}
 
diff --git a/engines/xeen/scripts.h b/engines/xeen/scripts.h
index 9690887..808566a 100644
--- a/engines/xeen/scripts.h
+++ b/engines/xeen/scripts.h
@@ -132,8 +132,9 @@ private:
 	int _var4F;
 	int _nEdamageType;
 	Common::String _paramText;
+	MazeEvent *_event;
 
-	void doOpcode(Opcode opcode, Common::Array<byte> &params);
+	void doOpcode(MazeEvent &event);
 	void cmdDisplay1(Common::Array<byte> &params);
 	void cmdDoorTextSml(Common::Array<byte> &params);
 	void cmdDoorTextLrg(Common::Array<byte> &params);


Commit: b597d71bcdd7792df1cc53d8354f700b0dc4ab72
    https://github.com/scummvm/scummvm/commit/b597d71bcdd7792df1cc53d8354f700b0dc4ab72
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-01-22T19:41:55-05:00

Commit Message:
XEEN: Implemented animate3d

Changed paths:
    engines/xeen/combat.cpp
    engines/xeen/combat.h
    engines/xeen/interface_map.cpp
    engines/xeen/interface_map.h
    engines/xeen/map.cpp
    engines/xeen/map.h



diff --git a/engines/xeen/combat.cpp b/engines/xeen/combat.cpp
index 98dff4c..4d3cb53 100644
--- a/engines/xeen/combat.cpp
+++ b/engines/xeen/combat.cpp
@@ -32,7 +32,7 @@ Combat::Combat(XeenEngine *vm): _vm(vm) {
 	Common::fill(&_monsterScale[0], &_monsterScale[12], 0);
 	Common::fill(&_elemPow[0], &_elemPow[12], 0);
 	Common::fill(&_elemScale[0], &_elemScale[12], 0);
-	Common::fill(&_shooting[0], &_shooting[6], 0);
+	Common::fill(&_shooting[0], &_shooting[8], 0);
 }
 
 void Combat::clear() {
diff --git a/engines/xeen/combat.h b/engines/xeen/combat.h
index 8e54353..882f90e 100644
--- a/engines/xeen/combat.h
+++ b/engines/xeen/combat.h
@@ -57,7 +57,7 @@ public:
 	int _monsterScale[12];
 	int _elemPow[12];
 	int _elemScale[12];
-	bool _shooting[6];
+	bool _shooting[8];
 public:
 	Combat(XeenEngine *vm);
 
diff --git a/engines/xeen/interface_map.cpp b/engines/xeen/interface_map.cpp
index be344ae..70297be 100644
--- a/engines/xeen/interface_map.cpp
+++ b/engines/xeen/interface_map.cpp
@@ -27,7 +27,9 @@
 
 namespace Xeen {
 
-OutdoorDrawList::OutdoorDrawList() : _skySprite(_data[1]), _groundSprite(_data[2]) {
+OutdoorDrawList::OutdoorDrawList() : _skySprite(_data[1]), _groundSprite(_data[2]),
+	_combatImgs1(&_data[124]), _combatImgs2(&_data[95]),
+	_combatImgs3(&_data[76]), _combatImgs4(&_data[53]) {
 	_data[0] = DrawStruct(0, 8, 8);
 	_data[1] = DrawStruct(1, 8, 25);
 	_data[2] = DrawStruct(0, 8, 67);
@@ -185,7 +187,9 @@ IndoorDrawList::IndoorDrawList() :
 	_objects0(_data[149]), _objects1(_data[125]), _objects2(_data[126]),
 	_objects3(_data[127]), _objects4(_data[97]), _objects5(_data[98]),
 	_objects6(_data[99]), _objects7(_data[55]), _objects8(_data[56]),
-	_objects9(_data[58]), _objects10(_data[57]), _objects11(_data[59]) {
+	_objects9(_data[58]), _objects10(_data[57]), _objects11(_data[59]),
+	_combatImgs1(&_data[162]), _combatImgs2(&_data[135]),
+	_combatImgs3(&_data[111]), _combatImgs4(&_data[80]) {
 	// Setup draw structure positions
 	_data[0] = DrawStruct(0, 8, 8);
 	_data[1] = DrawStruct(1, 8, 25);
@@ -631,9 +635,118 @@ void InterfaceMap::draw3d(bool updateFlag) {
 	events.wait(2);
 }
 
+/**
+ * Handles animation of monsters, wall items, and combat within the 3d
+ * view by cycling the appropriate frame numbers
+ */
 void InterfaceMap::animate3d() {
+	Combat &combat = *_vm->_combat;
+	Map &map = *_vm->_map;
+	_overallFrame = (_overallFrame + 1) % 5;
+	_combatFloatCounter = (_combatFloatCounter + 1) % 8;
+
+	for (uint idx = 0; idx < map._mobData._monsters.size(); ++idx) {
+		MazeMonster &monster = map._mobData._monsters[idx];
+		if (!monster._field7) {
+			if (monster._frame < 8) {
+				MonsterStruct &monsterData = map._monsterData[monster._spriteId];
+				if (!monsterData._loopAnimation) {
+					// Monster isn't specially looped, so cycle through the 8 frames
+					monster._frame = (monster._frame + 1) % 8;
+				} else if (!monster._field9) {
+					monster._frame = (monster._frame + 1) % 8;
+					if (monster._frame == 0) {
+						monster._field9 ^= 1;
+						monster._frame = 6;
+					}
+				} else {
+					if (monster._frame)
+						--monster._frame;
+					if (monster._frame == 0)
+						monster._field9 = 0;
+				}
+			} else if (monster._frame == 11) {
+				--monster._fieldA;
+				if (monster._fieldA == 0)
+					monster._frame = 0;
+			} else {
+				++monster._frame;
+				if (monster._frame == 11) {
+					--monster._frame;
+					monster._frame = monster._fieldA ? 10 : 0;
+				}
+			}
+		}
 
+		// Block 2
+		if (monster._effect2) {
+			if (monster._effect1) {
+				if (monster._effect1 & 0x80) {
+					if (monster._effect3)
+						--monster._effect3;
+					if (monster._effect3 == 0)
+						monster._effect1 ^= 0x80;
+				} else {
+					monster._effect3 = (monster._effect3 + 1) % 3;
+					if (monster._effect3 == 0) {
+						monster._effect1 ^= 0x80;
+						monster._effect3 = 2;
+					}
+				}
+			}
+		} else {
+			monster._effect3 = (monster._effect3 + 1) % 8;
+			if (monster._effect3 == 0) {
+				MonsterStruct &monsterData = map._monsterData[monster._spriteId];
+				monster._effect1 = monster._effect2 = monsterData._animationEffect;
+			}
+		}
+	}
+
+	DrawStruct *combatImgs1 = map._isOutdoors ? _outdoorList._combatImgs1 : _indoorList._combatImgs1;
+	DrawStruct *combatImgs2 = map._isOutdoors ? _outdoorList._combatImgs2 : _indoorList._combatImgs2;
+	DrawStruct *combatImgs3 = map._isOutdoors ? _outdoorList._combatImgs3 : _indoorList._combatImgs3;
+	DrawStruct *combatImgs4 = map._isOutdoors ? _outdoorList._combatImgs4 : _indoorList._combatImgs4;
+
+	if (_flag1) {
+		for (int idx = 0; idx < 8; ++idx) {
+			if (combatImgs1[idx]._sprites) {
+				combatImgs1[idx]._sprites = nullptr;
+				combat._shooting[idx] = false;
+			} else if (combatImgs2[idx]._sprites) {
+				combatImgs1[idx]._sprites = combatImgs2[idx]._sprites;
+				combatImgs2[idx]._sprites = nullptr;
+			} else if (combatImgs3[idx]._sprites) {
+				combatImgs2[idx]._sprites = combatImgs3[idx]._sprites;
+				combatImgs3[idx]._sprites = nullptr;
+			} else if (combatImgs4[idx]._sprites) {
+				combatImgs3[idx]._sprites = combatImgs4[idx]._sprites;
+				combatImgs4[idx]._sprites = nullptr;
+			}
+		}
+	} else if (_charsShooting) {
+		for (int idx = 0; idx < 8; ++idx) {
+			if (combatImgs4[idx]._sprites) {
+				combatImgs4[idx]._sprites = nullptr;
+			} else if (combatImgs3[idx]._sprites) {
+				combatImgs4[idx]._sprites = combatImgs3[idx]._sprites;
+				combatImgs3[idx]._sprites = nullptr;
+			} else if (combatImgs2[idx]._sprites) {
+				combatImgs3[idx]._sprites = combatImgs2[idx]._sprites;
+				combatImgs2[idx]._sprites = nullptr;
+			} else if (combatImgs1[idx]._sprites) {
+				combatImgs2[idx]._sprites = combatImgs1[idx]._sprites;
+				combatImgs1[idx]._sprites = nullptr;
+			}
+		}
+	}
+
+	for (uint idx = 0; idx < map._mobData._wallItems.size(); ++idx) {
+		MazeWallItem &wallItem = map._mobData._wallItems[idx];
+		wallItem._frame = (wallItem._frame + 1) % wallItem._sprites->size();
+	}
 }
+
 void InterfaceMap::setMazeBits() {
 	Common::fill(&_wo[0], &_wo[308], 0);
 
diff --git a/engines/xeen/interface_map.h b/engines/xeen/interface_map.h
index 12e5ac6..0867907 100644
--- a/engines/xeen/interface_map.h
+++ b/engines/xeen/interface_map.h
@@ -36,6 +36,10 @@ public:
 	DrawStruct _data[132];
 	DrawStruct &_skySprite;
 	DrawStruct &_groundSprite;
+	DrawStruct * const _combatImgs1;
+	DrawStruct * const _combatImgs2;
+	DrawStruct * const _combatImgs3;
+	DrawStruct * const _combatImgs4;
 public:
 	OutdoorDrawList();
 
@@ -68,6 +72,10 @@ public:
 	DrawStruct &_objects0, &_objects1, &_objects2, &_objects3;
 	DrawStruct &_objects4, &_objects5, &_objects6, &_objects7;
 	DrawStruct &_objects8, &_objects9, &_objects10, &_objects11;
+	DrawStruct * const _combatImgs1;
+	DrawStruct * const _combatImgs2;
+	DrawStruct * const _combatImgs3;
+	DrawStruct * const _combatImgs4;
 public:
 	IndoorDrawList();
 
diff --git a/engines/xeen/map.cpp b/engines/xeen/map.cpp
index d2f4c5e..5c49e37 100644
--- a/engines/xeen/map.cpp
+++ b/engines/xeen/map.cpp
@@ -644,6 +644,9 @@ MazeMonster::MazeMonster() {
 	_id = 0;
 	_spriteId = 0;
 	_isAttacking = false;
+	_field7 = 0;
+	_field9 = 0;
+	_fieldA = 0;
 	_hp = 0;
 	_effect1 = _effect2 = 0;
 	_effect3 = 0;
diff --git a/engines/xeen/map.h b/engines/xeen/map.h
index 8735973..7815d14 100644
--- a/engines/xeen/map.h
+++ b/engines/xeen/map.h
@@ -236,6 +236,9 @@ struct MazeMonster {
 	int _id;
 	int _spriteId;
 	bool _isAttacking;
+	int _field7;
+	int _field9;
+	int _fieldA;
 	int _hp;
 	int _effect1, _effect2;
 	int _effect3;


Commit: 2b51d324f3cc2a58f2a703c23030ee19ba85836b
    https://github.com/scummvm/scummvm/commit/2b51d324f3cc2a58f2a703c23030ee19ba85836b
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-01-22T22:05:36-05:00

Commit Message:
XEEN: Implemented dialogs for Who Will and YesNo

Changed paths:
  A engines/xeen/dialogs_whowill.cpp
  A engines/xeen/dialogs_whowill.h
  A engines/xeen/dialogs_yesno.cpp
  A engines/xeen/dialogs_yesno.h
    engines/xeen/dialogs_error.h
    engines/xeen/interface.h
    engines/xeen/interface_map.cpp
    engines/xeen/interface_map.h
    engines/xeen/map.h
    engines/xeen/module.mk
    engines/xeen/party.cpp
    engines/xeen/party.h
    engines/xeen/resources.cpp
    engines/xeen/resources.h
    engines/xeen/scripts.cpp
    engines/xeen/scripts.h
    engines/xeen/xeen.cpp
    engines/xeen/xeen.h



diff --git a/engines/xeen/dialogs_error.h b/engines/xeen/dialogs_error.h
index 03a6f16..ba36f28 100644
--- a/engines/xeen/dialogs_error.h
+++ b/engines/xeen/dialogs_error.h
@@ -23,9 +23,6 @@
 #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 {
diff --git a/engines/xeen/dialogs_whowill.cpp b/engines/xeen/dialogs_whowill.cpp
new file mode 100644
index 0000000..402f5c6
--- /dev/null
+++ b/engines/xeen/dialogs_whowill.cpp
@@ -0,0 +1,104 @@
+/* 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 "xeen/dialogs_whowill.h"
+#include "xeen/resources.h"
+#include "xeen/xeen.h"
+
+namespace Xeen {
+
+int WhoWill::show(XeenEngine *vm, int message, int action, bool type) {
+	WhoWill *dlg = new WhoWill(vm);
+	int result = dlg->execute(message, action, type);
+	delete dlg;
+
+	return result;
+}
+
+int WhoWill::execute(int message, int action, bool type) {
+	EventsManager &events = *_vm->_events;
+	Interface &intf = *_vm->_interface;
+	Map &map = *_vm->_map;
+	Party &party = *_vm->_party;
+	Screen &screen = *_vm->_screen;
+	Scripts &scripts = *_vm->_scripts;
+	int numFrames;
+
+	if (party._partyCount <= 1)
+		// Unless there's at least two characters, just return the first one
+		return 1;
+
+	screen._windows[38].close();
+	screen._windows[12].close();
+
+	Common::String actionStr = type ? map._events._text[action] : WHO_WILL_ACTIONS[action];
+	Common::String msg = Common::String::format(WHO_WILL, actionStr.c_str(),
+		WHO_ACTIONS[message], party._partyCount);
+
+	screen._windows[36].open();
+	screen._windows[36].writeString(msg);
+	screen._windows[36].update();
+
+	intf._face1State = map._headData[party._mazePosition.y][party._mazePosition.x]._left;
+	intf._face2State = map._headData[party._mazePosition.y][party._mazePosition.x]._right;
+
+	while (!_vm->shouldQuit()) {
+		events.updateGameCounter();
+
+		if (screen._windows[11]._enabled) {
+			intf.drawTownAnim(0);
+			screen._windows[36].frame();
+			numFrames = 3;
+		} else {
+			intf.draw3d(false);
+			screen._windows[36].frame();
+			screen._windows[3].update();
+			numFrames = 1;
+		}
+
+		events.wait(numFrames, true);
+		if (!_buttonValue)
+			continue;
+
+		if (_buttonValue == 27) {
+			_buttonValue = 0;
+			break;
+		} else if (_buttonValue >= 201 && _buttonValue <= 206) {
+			_buttonValue -= 201;
+			if (_buttonValue > party._partyCount)
+				continue;
+
+			if (party._activeParty[_buttonValue - 1].noActions())
+				continue;
+
+			scripts._whoWill = _buttonValue;
+			break;
+		}
+	}
+
+
+	intf._face1State = intf._face2State = 2;
+	screen._windows[36].close();
+	return _buttonValue;
+}
+
+} // End of namespace Xeen
diff --git a/engines/xeen/dialogs_whowill.h b/engines/xeen/dialogs_whowill.h
new file mode 100644
index 0000000..8080c36
--- /dev/null
+++ b/engines/xeen/dialogs_whowill.h
@@ -0,0 +1,43 @@
+/* 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_WHOWHILL_H
+#define XEEN_DIALOGS_WHOWHILL_H
+
+#include "xeen/dialogs.h"
+
+namespace Xeen {
+
+class WhoWill : public ButtonContainer {
+private:
+	XeenEngine *_vm;
+
+	WhoWill(XeenEngine *vm) : ButtonContainer(), _vm(vm) {}
+
+	int execute(int message, int action, bool type);
+public:
+	static int show(XeenEngine *vm, int message, int action, bool type);
+};
+
+} // End of namespace Xeen
+
+#endif /* XEEN_DIALOGS_WHOWHILL_H */
diff --git a/engines/xeen/dialogs_yesno.cpp b/engines/xeen/dialogs_yesno.cpp
new file mode 100644
index 0000000..cefafa0
--- /dev/null
+++ b/engines/xeen/dialogs_yesno.cpp
@@ -0,0 +1,94 @@
+/* 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 "xeen/dialogs_yesno.h"
+#include "xeen/xeen.h"
+
+namespace Xeen {
+
+bool YesNo::show(XeenEngine *vm, bool type, int v2) {
+	YesNo *dlg = new YesNo(vm);
+	bool result = dlg->execute(type, v2);
+	delete dlg;
+
+	return result;
+}
+
+bool YesNo::execute(bool type, int v2) {
+	Screen &screen = *_vm->_screen;
+	EventsManager &events = *_vm->_events;
+	Interface &intf = *_vm->_interface;
+	Map &map = *_vm->_map;
+	Party &party = *_vm->_party;
+	SpriteResource confirmSprites;
+	int numFrames;
+	bool result = false;
+
+	Mode oldMode = _vm->_mode;
+	_vm->_mode = oldMode == MODE_7 ? MODE_8 : MODE_7;
+
+	if (!type) {
+		confirmSprites.load("confirm.icn");
+		intf._globalSprites.draw(screen, 7, Common::Point(232, 74));
+		confirmSprites.draw(screen, 0, Common::Point(235, 75));
+		confirmSprites.draw(screen, 2, Common::Point(260, 75));
+		screen._windows[34].update();
+
+		addButton(Common::Rect(235, 75, 259, 95), 'Y', &confirmSprites);
+		addButton(Common::Rect(260, 75, 284, 95), 'N', &confirmSprites);
+
+		intf._face1State = map._headData[party._mazePosition.y][party._mazePosition.x]._left;
+		intf._face2State = map._headData[party._mazePosition.y][party._mazePosition.x]._right;
+	}
+
+	while (!_vm->shouldQuit()) {
+		events.updateGameCounter();
+		
+		if (intf._townSprites[0].empty()) {
+			intf.draw3d(true);
+			numFrames = 1;
+		} else {
+			intf.drawTownAnim(v2);
+			numFrames = 3;
+		}
+
+		events.wait(3, true);
+		if (!_buttonValue)
+			continue;
+
+		if (type || _buttonValue == 'Y') {
+			result = true;
+			break;
+		} else if (_buttonValue == 'N' || _buttonValue == Common::KEYCODE_ESCAPE)
+			break;
+	}
+
+	intf._face1State = intf._face2State = 2;
+	_vm->_mode = oldMode;
+
+	if (!type)
+		intf.mainIconsPrint();
+
+	return result;
+}
+
+} // End of namespace Xeen
diff --git a/engines/xeen/dialogs_yesno.h b/engines/xeen/dialogs_yesno.h
new file mode 100644
index 0000000..82ac402
--- /dev/null
+++ b/engines/xeen/dialogs_yesno.h
@@ -0,0 +1,43 @@
+/* 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_YESNO_H
+#define XEEN_DIALOGS_YESNO_H
+
+#include "xeen/dialogs.h"
+
+namespace Xeen {
+
+class YesNo : public ButtonContainer {
+private:
+	XeenEngine *_vm;
+
+	YesNo(XeenEngine *vm) : ButtonContainer(), _vm(vm) {}
+
+	bool execute(bool type, int v2);
+public:
+	static bool show(XeenEngine *vm, bool type, int v2);
+};
+
+} // End of namespace Xeen
+
+#endif /* XEEN_DIALOGS_YESNO_H */
diff --git a/engines/xeen/interface.h b/engines/xeen/interface.h
index 28f2bbe..7879da5 100644
--- a/engines/xeen/interface.h
+++ b/engines/xeen/interface.h
@@ -76,6 +76,7 @@ private:
 
 	bool checkMoveDirection(int key);
 public:
+	SpriteResource _townSprites[8];
 	int _intrIndex1;
 public:
 	Interface(XeenEngine *vm);
diff --git a/engines/xeen/interface_map.cpp b/engines/xeen/interface_map.cpp
index 70297be..2d2fddf 100644
--- a/engines/xeen/interface_map.cpp
+++ b/engines/xeen/interface_map.cpp
@@ -393,6 +393,7 @@ InterfaceMap::InterfaceMap(XeenEngine *vm): _vm(vm) {
 	_tillMove = 0;
 	_flag1 = false;
 	_overallFrame = 0;
+	_face1State = _face2State = 0;
 }
 
 void InterfaceMap::setup() {
@@ -3852,15 +3853,15 @@ void InterfaceMap::assembleBorder() {
 
 	// Handle the face UI elements for indicating clairvoyance status
 	_face1UIFrame = (_face1UIFrame + 1) % 4;
-	if (_vm->_face1State == 0)
+	if (_face1State == 0)
 		_face1UIFrame += 4;
-	else if (_vm->_face1State == 2)
+	else if (_face1State == 2)
 		_face1UIFrame = 0;
 
 	_face2UIFrame = (_face2UIFrame + 1) % 4 + 12;
-	if (_vm->_face2State == 0)
+	if (_face2State == 0)
 		_face2UIFrame += 252;
-	else if (_vm->_face2State == 2)
+	else if (_face2State == 2)
 		_face2UIFrame = 0;
 
 	if (!_vm->_party->_clairvoyanceActive) {
@@ -4310,4 +4311,8 @@ void InterfaceMap::drawMiniMap() {
 	party._wizardEyeActive = eyeActive;
 }
 
+void InterfaceMap::drawTownAnim(int v) {
+	warning("TODO");
+}
+
 } // End of namespace Xeen
diff --git a/engines/xeen/interface_map.h b/engines/xeen/interface_map.h
index 0867907..51b82a9 100644
--- a/engines/xeen/interface_map.h
+++ b/engines/xeen/interface_map.h
@@ -103,7 +103,6 @@ private:
 	void setMonsterSprite(DrawStruct &drawStruct, MazeMonster &monster, 
 		SpriteResource *sprites, int frame, int defaultY);
 protected:
-	SpriteResource _globalSprites;
 	int8 _wp[20];
 	byte _wo[308];
 	bool _flipWater;
@@ -143,8 +142,11 @@ protected:
 public:
 	OutdoorDrawList _outdoorList;
 	IndoorDrawList _indoorList;
+	SpriteResource _globalSprites;
 	bool _upDoorText;
 	Common::String _screenText;
+	int _face1State;
+	int _face2State;
 public:
 	InterfaceMap(XeenEngine *vm);
 
@@ -163,6 +165,8 @@ public:
 	void setOutdoorsMonsters();
 
 	void setOutdoorsObjects();
+
+	void drawTownAnim(int v);
 };
 
 } // End of namespace Xeen
diff --git a/engines/xeen/map.h b/engines/xeen/map.h
index 7815d14..58e3aaa 100644
--- a/engines/xeen/map.h
+++ b/engines/xeen/map.h
@@ -309,6 +309,8 @@ public:
 	HeadData();
 
 	void synchronize(Common::SeekableReadStream &s);
+
+	HeadEntry *operator[](int y) { return &_data[y][0]; }
 };
 
 struct AnimationFrame { int _front, _left, _back, _right; };
diff --git a/engines/xeen/module.mk b/engines/xeen/module.mk
index 6362ffe..05a9b23 100644
--- a/engines/xeen/module.mk
+++ b/engines/xeen/module.mk
@@ -10,6 +10,8 @@ MODULE_OBJS := \
 	dialogs.o \
 	dialogs_error.o \
 	dialogs_options.o \
+	dialogs_whowill.o \
+	dialogs_yesno.o \
 	events.o \
 	files.o \
 	font.o \
diff --git a/engines/xeen/party.cpp b/engines/xeen/party.cpp
index d465cc9..c1c4062 100644
--- a/engines/xeen/party.cpp
+++ b/engines/xeen/party.cpp
@@ -167,6 +167,12 @@ bool PlayerStruct::charSavingThrow() {
 	return false;
 }
 
+bool PlayerStruct::noActions() {
+	// TODO
+	return false;
+}
+
+
 /*------------------------------------------------------------------------*/
 
 void Roster::synchronize(Common::Serializer &s) {
diff --git a/engines/xeen/party.h b/engines/xeen/party.h
index c598e8c..1937683 100644
--- a/engines/xeen/party.h
+++ b/engines/xeen/party.h
@@ -139,6 +139,8 @@ public:
 	int getStat(int statNum, int v2);
 
 	bool charSavingThrow();
+
+	bool noActions();
 };
 
 class Roster: public Common::Array<PlayerStruct> {
diff --git a/engines/xeen/resources.cpp b/engines/xeen/resources.cpp
index 085f84a..994762b 100644
--- a/engines/xeen/resources.cpp
+++ b/engines/xeen/resources.cpp
@@ -68,6 +68,9 @@ const char *const OPTIONS_TITLE =
 
 const char *const THE_PARTY_NEEDS_REST = "\x0B""012The Party needs rest!";
 
+const char *const WHO_WILL = "\X03""c\X0B""000\x09""000%s\x0A\x0A"
+	"Who will\x0A%s?\x0A\x0B""055F1 - F%d";
+
 const char *const TERRAIN_TYPES[6] = {
 	"town", "cave", "towr", "cstl", "dung", "scfi"
 };
@@ -85,6 +88,17 @@ const char *const SURFACE_NAMES[16] = {
 	"space.srf"
 };
 
+const char *const WHO_ACTIONS[32] = {
+	"aSearch", "aOpen", "aDrink", "aMine", "aTouch", "aRead", "aLearn", "aTake",
+	"aBang", "aSteal", "aBribe", "aPay", "aSit", "aTry", "aTurn", "aBathe",
+	"aDestroy", "aPull", "aDescend", "aTossACoin", "aPray", "aJoin", "aAct",
+	"aPlay", "aPush", "aRub", "aPick", "aEat", "aSign", "aClose", "aLook", "aTry"
+};
+
+const char *const WHO_WILL_ACTIONS[4] = {
+	"Open Grate", "Open Door", "Open Scroll", "Select Char"
+};
+
 const byte SYMBOLS[20][64] = {
 	{ // 0
 		0x00, 0x00, 0xA8, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0x00, 0xA8, 0x9E, 0x9C, 0x9C, 0x9E, 0x9E, 0x9E,
diff --git a/engines/xeen/resources.h b/engines/xeen/resources.h
index f6bcffa..28a3554 100644
--- a/engines/xeen/resources.h
+++ b/engines/xeen/resources.h
@@ -34,12 +34,18 @@ extern const char *const OPTIONS_TITLE;
 
 extern const char *const THE_PARTY_NEEDS_REST;
 
+extern const char *const WHO_WILL;
+
 extern const char *const TERRAIN_TYPES[6];
 
 extern const char *const SURFACE_TYPE_NAMES[15];
 
 extern const char *const SURFACE_NAMES[16];
 
+extern const char *const WHO_ACTIONS[32];
+
+extern const char *const WHO_WILL_ACTIONS[4];
+
 extern const byte SYMBOLS[20][64];
 
 extern const byte TEXT_COLORS[40][4];
diff --git a/engines/xeen/scripts.cpp b/engines/xeen/scripts.cpp
index 73c0445..4ccac8b 100644
--- a/engines/xeen/scripts.cpp
+++ b/engines/xeen/scripts.cpp
@@ -21,6 +21,7 @@
  */
 
 #include "xeen/scripts.h"
+#include "xeen/dialogs_whowill.h"
 #include "xeen/party.h"
 #include "xeen/xeen.h"
 
@@ -72,7 +73,8 @@ Scripts::Scripts(XeenEngine *vm) : _vm(vm) {
 	_treasureItems = 0;
 	_treasureGold = 0;
 	_treasureGems = 0;
-
+	_lineNum = 0;
+	_charIndex = 0;
 	_v2 = 0;
 	_nEdamageType = 0;
 	_animCounter = 0;
@@ -85,7 +87,7 @@ void Scripts::checkEvents() {
 	Map &map = *_vm->_map;
 	Party &party = *_vm->_party;
 
-	int var18 = 0;
+//	int var18 = 0;
 	_itemType = 0;
 	_var4F = 0;
 	bool var50 = false;
@@ -102,14 +104,14 @@ void Scripts::checkEvents() {
 
 	do {
 		_lineNum = 0;
-		int varA = 0;
+//		int varA = 0;
 		_animCounter = 0;
-		int var4E = 0;
+//		int var4E = 0;
 		const Common::Point pt = party._mazePosition;
-		int varC = 1;
+		_charIndex = 1;
 		_v2 = 1;
 		_nEdamageType = 0;
-		int var40 = -1;
+//		int var40 = -1;
 
 		while (_lineNum >= 0) {
 			// Break out of the events if there's an attacking monster
@@ -232,6 +234,9 @@ void Scripts::cmdDoorTextLrg(Common::Array<byte> &params) {
 	cmdNoAction(params);
 }
 
+/**
+ * Show a sign text on-screen
+ */
 void Scripts::cmdSignText(Common::Array<byte> &params) {
 	Interface &intf = *_vm->_interface;
 	intf._screenText = Common::String::format("\f08\x03""c\t120\v088%s\x03""l\fd",
@@ -247,6 +252,9 @@ void Scripts::cmdNPC(Common::Array<byte> &params) {
 	warning("TODO: cmdNPC");
 }
 
+/**
+ * Play a sound FX
+ */
 void Scripts::cmdPlayFX(Common::Array<byte> &params) {
 	_vm->_sound->playFX(params[0]);
 
@@ -255,74 +263,118 @@ void Scripts::cmdPlayFX(Common::Array<byte> &params) {
 }
 
 void Scripts::cmdTeleport(Common::Array<byte> &params) {
+	error("TODO");
 }
 
+/**
+ * Do a conditional check
+ */
 void Scripts::cmdIf(Common::Array<byte> &params) {
 	switch (params[0]) {
 	case 16:
 	case 34:
 	case 100:
+		// TODO
 		break;
 	case 25:
 	case 35:
 	case 101:
 	case 106:
+		// TODO
 		break;
 	default:
 		break;
 	}
 }
 
-void Scripts::cmdMoveObj(Common::Array<byte> &params) {}
-void Scripts::cmdTakeOrGive(Common::Array<byte> &params) {}
+void Scripts::cmdMoveObj(Common::Array<byte> &params) { error("TODO"); }
+void Scripts::cmdTakeOrGive(Common::Array<byte> &params) { error("TODO"); }
 
+/**
+ * Move to the next line of the script
+ */
 void Scripts::cmdNoAction(Common::Array<byte> &params) {
 	// Move to next line
 	_lineNum = _vm->_party->_partyDead ? -1 : _lineNum + 1;
 }
 
-void Scripts::cmdRemove(Common::Array<byte> &params) {}
-void Scripts::cmdSetChar(Common::Array<byte> &params) {}
-void Scripts::cmdSpawn(Common::Array<byte> &params) {}
-void Scripts::cmdDoTownEvent(Common::Array<byte> &params) {}
-void Scripts::cmdExit(Common::Array<byte> &params) {}
-void Scripts::cmdAfterMap(Common::Array<byte> &params) {}
-void Scripts::cmdGiveExtended(Common::Array<byte> &params) {}
-void Scripts::cmdConfirmWord(Common::Array<byte> &params) {}
-void Scripts::cmdDamage(Common::Array<byte> &params) {}
-void Scripts::cmdJumpRnd(Common::Array<byte> &params) {}
-void Scripts::cmdAfterEvent(Common::Array<byte> &params) {}
-void Scripts::cmdCallEvent(Common::Array<byte> &params) {}
-void Scripts::cmdReturn(Common::Array<byte> &params) {}
-void Scripts::cmdSetVar(Common::Array<byte> &params) {}
-void Scripts::cmdCutsceneEndClouds(Common::Array<byte> &params) {}
-void Scripts::cmdWhoWill(Common::Array<byte> &params) {}
-void Scripts::cmdRndDamage(Common::Array<byte> &params) {}
-void Scripts::cmdMoveWallObj(Common::Array<byte> &params) {}
-void Scripts::cmdAlterCellFlag(Common::Array<byte> &params) {}
-void Scripts::cmdAlterHed(Common::Array<byte> &params) {}
-void Scripts::cmdDisplayStat(Common::Array<byte> &params) {}
-void Scripts::cmdSeatTextSml(Common::Array<byte> &params) {}
-void Scripts::cmdPlayEventVoc(Common::Array<byte> &params) {}
-void Scripts::cmdDisplayBottom(Common::Array<byte> &params) {}
-void Scripts::cmdIfMapFlag(Common::Array<byte> &params) {}
-void Scripts::cmdSelRndChar(Common::Array<byte> &params) {}
-void Scripts::cmdGiveEnchanted(Common::Array<byte> &params) {}
-void Scripts::cmdItemType(Common::Array<byte> &params) {}
-void Scripts::cmdMakeNothingHere(Common::Array<byte> &params) {}
-void Scripts::cmdNoAction2(Common::Array<byte> &params) {}
-void Scripts::cmdChooseNumeric(Common::Array<byte> &params) {}
-void Scripts::cmdDisplayBottomTwoLines(Common::Array<byte> &params) {}
-void Scripts::cmdDisplayLarge(Common::Array<byte> &params) {}
-void Scripts::cmdExchObj(Common::Array<byte> &params) {}
-void Scripts::cmdFallToMap(Common::Array<byte> &params) {}
-void Scripts::cmdDisplayMain(Common::Array<byte> &params) {}
-void Scripts::cmdGoto(Common::Array<byte> &params) {}
-void Scripts::cmdConfirmWord2(Common::Array<byte> &params) {}
-void Scripts::cmdGotoRandom(Common::Array<byte> &params) {}
-void Scripts::cmdCutsceneEndDarkside(Common::Array<byte> &params) {}
-void Scripts::cmdCutsceneEdWorld(Common::Array<byte> &params) {}
-void Scripts::cmdFlipWorld(Common::Array<byte> &params) {}
-void Scripts::cmdPlayCD(Common::Array<byte> &params) {}
+void Scripts::cmdRemove(Common::Array<byte> &params) { error("TODO"); }
+
+/**
+ * Set the currently active character for other script operations
+ */
+void Scripts::cmdSetChar(Common::Array<byte> &params) { 
+	if (params[0] != 7) {
+		_charIndex = WhoWill::show(_vm, 22, 3, false);
+		if (_charIndex == 0) {
+			cmdExit(params);
+			return;
+		}
+	} else {
+		_charIndex = _vm->getRandomNumber(1, _vm->_party->_partyCount);
+	}
+
+	_v2 = 1;
+	cmdNoAction(params);
+}
+
+void Scripts::cmdSpawn(Common::Array<byte> &params) { error("TODO"); }
+void Scripts::cmdDoTownEvent(Common::Array<byte> &params) { error("TODO"); }
+
+/**
+ * Stop executing the script
+ */
+void Scripts::cmdExit(Common::Array<byte> &params) { 
+	_lineNum = -1;
+}
+
+void Scripts::cmdAfterMap(Common::Array<byte> &params) { error("TODO"); }
+void Scripts::cmdGiveExtended(Common::Array<byte> &params) { error("TODO"); }
+void Scripts::cmdConfirmWord(Common::Array<byte> &params) { error("TODO"); }
+void Scripts::cmdDamage(Common::Array<byte> &params) { error("TODO"); }
+void Scripts::cmdJumpRnd(Common::Array<byte> &params) { error("TODO"); }
+void Scripts::cmdAfterEvent(Common::Array<byte> &params) { error("TODO"); }
+void Scripts::cmdCallEvent(Common::Array<byte> &params) { error("TODO"); }
+void Scripts::cmdReturn(Common::Array<byte> &params) { error("TODO"); }
+void Scripts::cmdSetVar(Common::Array<byte> &params) { error("TODO"); }
+void Scripts::cmdCutsceneEndClouds(Common::Array<byte> &params) { error("TODO"); }
+
+void Scripts::cmdWhoWill(Common::Array<byte> &params) { 
+	_charIndex = WhoWill::show(_vm, params[0], params[1], true);
+
+	_var4F = true;
+	if (_charIndex == 0)
+		cmdExit(params);
+	else
+		cmdNoAction(params);
+}
+
+void Scripts::cmdRndDamage(Common::Array<byte> &params) { error("TODO"); }
+void Scripts::cmdMoveWallObj(Common::Array<byte> &params) { error("TODO"); }
+void Scripts::cmdAlterCellFlag(Common::Array<byte> &params) { error("TODO"); }
+void Scripts::cmdAlterHed(Common::Array<byte> &params) { error("TODO"); }
+void Scripts::cmdDisplayStat(Common::Array<byte> &params) { error("TODO"); }
+void Scripts::cmdSeatTextSml(Common::Array<byte> &params) { error("TODO"); }
+void Scripts::cmdPlayEventVoc(Common::Array<byte> &params) { error("TODO"); }
+void Scripts::cmdDisplayBottom(Common::Array<byte> &params) { error("TODO"); }
+void Scripts::cmdIfMapFlag(Common::Array<byte> &params) { error("TODO"); }
+void Scripts::cmdSelRndChar(Common::Array<byte> &params) { error("TODO"); }
+void Scripts::cmdGiveEnchanted(Common::Array<byte> &params) { error("TODO"); }
+void Scripts::cmdItemType(Common::Array<byte> &params) { error("TODO"); }
+void Scripts::cmdMakeNothingHere(Common::Array<byte> &params) { error("TODO"); }
+void Scripts::cmdNoAction2(Common::Array<byte> &params) { error("TODO"); }
+void Scripts::cmdChooseNumeric(Common::Array<byte> &params) { error("TODO"); }
+void Scripts::cmdDisplayBottomTwoLines(Common::Array<byte> &params) { error("TODO"); }
+void Scripts::cmdDisplayLarge(Common::Array<byte> &params) { error("TODO"); }
+void Scripts::cmdExchObj(Common::Array<byte> &params) { error("TODO"); }
+void Scripts::cmdFallToMap(Common::Array<byte> &params) { error("TODO"); }
+void Scripts::cmdDisplayMain(Common::Array<byte> &params) { error("TODO"); }
+void Scripts::cmdGoto(Common::Array<byte> &params) { error("TODO"); }
+void Scripts::cmdConfirmWord2(Common::Array<byte> &params) { error("TODO"); }
+void Scripts::cmdGotoRandom(Common::Array<byte> &params) { error("TODO"); }
+void Scripts::cmdCutsceneEndDarkside(Common::Array<byte> &params) { error("TODO"); }
+void Scripts::cmdCutsceneEdWorld(Common::Array<byte> &params) { error("TODO"); }
+void Scripts::cmdFlipWorld(Common::Array<byte> &params) { error("TODO"); }
+void Scripts::cmdPlayCD(Common::Array<byte> &params) { error("TODO"); }
 
 } // End of namespace Xeen
diff --git a/engines/xeen/scripts.h b/engines/xeen/scripts.h
index 808566a..2e4996e 100644
--- a/engines/xeen/scripts.h
+++ b/engines/xeen/scripts.h
@@ -121,12 +121,12 @@ class Scripts {
 private:
 	XeenEngine *_vm;
 	int _charFX[6];
-	int _whoWill;
 	int _itemType;
 	int _treasureItems;
 	int _treasureGold;
 	int _treasureGems;
 	int _lineNum;
+	int _charIndex;
 
 	int _v2;
 	int _var4F;
@@ -134,6 +134,8 @@ private:
 	Common::String _paramText;
 	MazeEvent *_event;
 
+	int whoWill(int v1, int v2, int v3);
+
 	void doOpcode(MazeEvent &event);
 	void cmdDisplay1(Common::Array<byte> &params);
 	void cmdDoorTextSml(Common::Array<byte> &params);
@@ -192,6 +194,7 @@ private:
 public:
 	int _animCounter;
 	bool _eventSkipped;
+	int _whoWill;
 public:
 	Scripts(XeenEngine *vm);
 
diff --git a/engines/xeen/xeen.cpp b/engines/xeen/xeen.cpp
index 38026d0..2d824e5 100644
--- a/engines/xeen/xeen.cpp
+++ b/engines/xeen/xeen.cpp
@@ -50,8 +50,6 @@ XeenEngine::XeenEngine(OSystem *syst, const XeenGameDescription *gameDesc)
 	_eventData = nullptr;
 	_loadDarkSide = 1;
 	_dangerSenseAllowed = false;
-	_face1State = 0;
-	_face2State = 0;
 	_noDirectionSense = false;
 	_moveMonsters = false;
 	_mode = MODE_0;
@@ -128,6 +126,10 @@ int XeenEngine::getRandomNumber(int maxNumber) {
 	return _randomSource.getRandomNumber(maxNumber);
 }
 
+int XeenEngine::getRandomNumber(int minNumber, int maxNumber) {
+	return getRandomNumber(maxNumber - minNumber) + minNumber;
+}
+
 Common::Error XeenEngine::saveGameState(int slot, const Common::String &desc) {
 	Common::OutSaveFile *out = g_system->getSavefileManager()->openForSaving(
 		generateSaveName(slot));
diff --git a/engines/xeen/xeen.h b/engines/xeen/xeen.h
index 3e86374..cf872b3 100644
--- a/engines/xeen/xeen.h
+++ b/engines/xeen/xeen.h
@@ -145,8 +145,6 @@ public:
 	Roster _roster;
 	int _loadDarkSide;
 	bool _dangerSenseAllowed;
-	int _face1State;
-	int _face2State;
 	bool _noDirectionSense;
 	bool _moveMonsters;
 	int _openDoor;
@@ -163,6 +161,8 @@ public:
 
 	int getRandomNumber(int maxNumber);
 
+	int getRandomNumber(int minNumber, int maxNumber);
+
 	/**
 	 * Load a savegame
 	 */


Commit: 749372e456ed8f1a4aee31ce23c4f4f7fd5644cc
    https://github.com/scummvm/scummvm/commit/749372e456ed8f1a4aee31ce23c4f4f7fd5644cc
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-01-23T20:44:02-05:00

Commit Message:
XEEN: More script code and string input dialog

Changed paths:
  A engines/xeen/dialogs_string_input.cpp
  A engines/xeen/dialogs_string_input.h
    engines/xeen/dialogs_whowill.cpp
    engines/xeen/dialogs_yesno.cpp
    engines/xeen/interface.cpp
    engines/xeen/interface.h
    engines/xeen/interface_map.h
    engines/xeen/items.cpp
    engines/xeen/items.h
    engines/xeen/map.cpp
    engines/xeen/map.h
    engines/xeen/module.mk
    engines/xeen/party.cpp
    engines/xeen/party.h
    engines/xeen/resources.cpp
    engines/xeen/resources.h
    engines/xeen/saves.cpp
    engines/xeen/saves.h
    engines/xeen/screen.cpp
    engines/xeen/screen.h
    engines/xeen/scripts.cpp
    engines/xeen/scripts.h
    engines/xeen/xeen.cpp
    engines/xeen/xeen.h



diff --git a/engines/xeen/dialogs_string_input.cpp b/engines/xeen/dialogs_string_input.cpp
new file mode 100644
index 0000000..03191f8
--- /dev/null
+++ b/engines/xeen/dialogs_string_input.cpp
@@ -0,0 +1,75 @@
+/* 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 "xeen/dialogs_string_input.h"
+#include "xeen/xeen.h"
+
+namespace Xeen {
+
+int StringInput::show(XeenEngine *vm, bool type, const Common::String &msg1,
+		const Common::String &msg2, int opcdoe) {
+	StringInput *dlg = new StringInput(vm);
+	int result = dlg->execute(type, msg1, msg2, opcdoe);
+	delete dlg;
+
+	return result;
+}
+
+int StringInput::execute(bool type, const Common::String &expected, 
+		const Common::String &title, int opcode) {
+	Interface &intf = *_vm->_interface;
+	Screen &screen = *_vm->_screen;
+	Window &w = screen._windows[6];
+	SoundManager &sound = *_vm->_sound;
+	int result = 0;
+
+	w.open();
+	w.writeString(Common::String::format("\r\x03""c%s\v024\t000", title.c_str()));
+	w.update();
+
+	Common::String line;
+	if (w.getString(line, 30, 200)) {
+		if (type) {
+			if (line == intf._interfaceText) {
+				result = true;
+			} else if (line == expected) {
+				result = (opcode == 55) ? -1 : 1;
+			}
+		} else {
+			// Load in the mirror list
+			File f(Common::String::format("%smirr.txt",
+				_vm->_files->_isDarkCc ? "dark" : "xeen"));
+			for (int idx = 0; f.pos() < f.size(); ++idx) {
+				if (line == f.readLine()) {
+					result = idx;
+					sound.playFX(_vm->_files->_isDarkCc ? 35 : 61);
+					break;
+				}
+			}
+		}
+	}
+
+	w.close();
+	return result;
+}
+
+} // End of namespace Xeen
diff --git a/engines/xeen/dialogs_string_input.h b/engines/xeen/dialogs_string_input.h
new file mode 100644
index 0000000..1e18726
--- /dev/null
+++ b/engines/xeen/dialogs_string_input.h
@@ -0,0 +1,45 @@
+/* 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_STRING_INPUT_H
+#define XEEN_DIALOGS_STRING_INPUT_H
+
+#include "xeen/dialogs.h"
+
+namespace Xeen {
+
+class StringInput : public ButtonContainer {
+private:
+	XeenEngine *_vm;
+
+	StringInput(XeenEngine *vm) : ButtonContainer(), _vm(vm) {}
+
+	int execute(bool type, const Common::String &expected, 
+		const Common::String &title, int opcode);
+public:
+	static int show(XeenEngine *vm, bool type, const Common::String &msg1, 
+		const Common::String &msg2, int opcdoe);
+};
+
+} // End of namespace Xeen
+
+#endif /* XEEN_DIALOGS_STRING_INPUT_H */
diff --git a/engines/xeen/dialogs_whowill.cpp b/engines/xeen/dialogs_whowill.cpp
index 402f5c6..042214a 100644
--- a/engines/xeen/dialogs_whowill.cpp
+++ b/engines/xeen/dialogs_whowill.cpp
@@ -76,6 +76,7 @@ int WhoWill::execute(int message, int action, bool type) {
 		}
 
 		events.wait(numFrames, true);
+		checkEvents(_vm);
 		if (!_buttonValue)
 			continue;
 
diff --git a/engines/xeen/dialogs_yesno.cpp b/engines/xeen/dialogs_yesno.cpp
index cefafa0..6f74d86 100644
--- a/engines/xeen/dialogs_yesno.cpp
+++ b/engines/xeen/dialogs_yesno.cpp
@@ -72,6 +72,7 @@ bool YesNo::execute(bool type, int v2) {
 		}
 
 		events.wait(3, true);
+		checkEvents(_vm);
 		if (!_buttonValue)
 			continue;
 
diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp
index 31fe00b..7487d63 100644
--- a/engines/xeen/interface.cpp
+++ b/engines/xeen/interface.cpp
@@ -485,7 +485,7 @@ void Interface::perform() {
 	if (_buttonValue == Common::KEYCODE_SPACE ||
 			(events._leftButton && waitBounds.contains(events._mousePos))) {
 		int lookupId = map.mazeLookup(party._mazePosition, 
-			WALL_NUMBERS[party._mazeDirection][2]);
+			WALL_SHIFTS[party._mazeDirection][2]);
 
 		bool eventsFlag = true;
 		switch (lookupId) {
diff --git a/engines/xeen/interface.h b/engines/xeen/interface.h
index 7879da5..3d8116d 100644
--- a/engines/xeen/interface.h
+++ b/engines/xeen/interface.h
@@ -52,7 +52,6 @@ private:
 	bool _buttonsLoaded;
 	int _hiliteChar;
 	int _steppingFX;
-	Common::String _interfaceText;
 
 	void initDrawStructs();
 
@@ -78,6 +77,7 @@ private:
 public:
 	SpriteResource _townSprites[8];
 	int _intrIndex1;
+	Common::String _interfaceText;
 public:
 	Interface(XeenEngine *vm);
 
diff --git a/engines/xeen/interface_map.h b/engines/xeen/interface_map.h
index 51b82a9..914120f 100644
--- a/engines/xeen/interface_map.h
+++ b/engines/xeen/interface_map.h
@@ -124,7 +124,6 @@ protected:
 	int _holyBonusUIFrame;
 	int _heroismUIFrame;
 	int _flipUIFrame;
-	byte _tillMove;
 	bool _flag1;
 	int _overallFrame;
 
@@ -147,6 +146,7 @@ public:
 	Common::String _screenText;
 	int _face1State;
 	int _face2State;
+	byte _tillMove;
 public:
 	InterfaceMap(XeenEngine *vm);
 
diff --git a/engines/xeen/items.cpp b/engines/xeen/items.cpp
index e22e865..e9425f7 100644
--- a/engines/xeen/items.cpp
+++ b/engines/xeen/items.cpp
@@ -36,4 +36,8 @@ void XeenItem::synchronize(Common::Serializer &s) {
 	s.syncAsByte(_equipped);
 }
 
+Treasure::Treasure() {
+	_hasItems = false;
+}
+
 } // End of namespace Xeen
diff --git a/engines/xeen/items.h b/engines/xeen/items.h
index eba2354..6fa57b9 100644
--- a/engines/xeen/items.h
+++ b/engines/xeen/items.h
@@ -28,6 +28,8 @@
 
 namespace Xeen {
 
+#define TOTAL_ITEMS 10
+
 class XeenItem {
 public:
 	int _material;
@@ -40,6 +42,17 @@ public:
 	void synchronize(Common::Serializer &s);
 };
 
+class Treasure {
+public:
+	XeenItem _misc[TOTAL_ITEMS];
+	XeenItem _accessories[TOTAL_ITEMS];
+	XeenItem _armor[TOTAL_ITEMS];
+	XeenItem _weapons[TOTAL_ITEMS];
+	bool _hasItems;
+public:
+	Treasure();
+};
+
 } // End of namespace Xeen
 
 #endif	/* XEEN_ITEMS_H */
diff --git a/engines/xeen/map.cpp b/engines/xeen/map.cpp
index 5c49e37..7801a05 100644
--- a/engines/xeen/map.cpp
+++ b/engines/xeen/map.cpp
@@ -1367,6 +1367,14 @@ void Map::setCellSurfaceFlags(const Common::Point &pt, int bits) {
 	_mazeData[0]._cells[pt.y][pt.x]._surfaceId |= bits;
 }
 
+void Map::setWall(const Common::Point &pt, Direction dir, int v) {
+	const int XOR_MASKS[4] = { 0xFFF, 0xF0FF, 0xFF0F, 0xFFF0 };
+	mazeLookup(pt, 0, 0);
+	
+	MazeWallLayers &wallLayer = _mazeData[0]._wallData[pt.y][pt.x];
+	wallLayer._data &= XOR_MASKS[dir];
+	wallLayer._data |= v << WALL_SHIFTS[dir][2];
+}
 
 int Map::getCell(int idx) {
 	int mapId = _vm->_party->_mazeId;
@@ -1489,7 +1497,7 @@ int Map::getCell(int idx) {
 			_currentSurfaceId = _mazeData[_mazeDataIndex]._cells[pt.y][pt.x]._surfaceId;
 
 		_currentWall = wallLayers;
-		return (_currentWall._data >> WALL_NUMBERS[dir][idx]) & 0xF;
+		return (_currentWall._data >> WALL_SHIFTS[dir][idx]) & 0xF;
 	}
 
 	return _currentWall._data;
diff --git a/engines/xeen/map.h b/engines/xeen/map.h
index 58e3aaa..51f426d 100644
--- a/engines/xeen/map.h
+++ b/engines/xeen/map.h
@@ -385,6 +385,8 @@ public:
 
 	void setCellSurfaceFlags(const Common::Point &pt, int bits);
 
+	void setWall(const Common::Point &pt, Direction dir, int v);
+
 	void saveMaze();
 
 	int getCell(int idx);
diff --git a/engines/xeen/module.mk b/engines/xeen/module.mk
index 05a9b23..ea6ea8c 100644
--- a/engines/xeen/module.mk
+++ b/engines/xeen/module.mk
@@ -10,6 +10,7 @@ MODULE_OBJS := \
 	dialogs.o \
 	dialogs_error.o \
 	dialogs_options.o \
+	dialogs_string_input.o \
 	dialogs_whowill.o \
 	dialogs_yesno.o \
 	events.o \
diff --git a/engines/xeen/party.cpp b/engines/xeen/party.cpp
index c1c4062..b33318f 100644
--- a/engines/xeen/party.cpp
+++ b/engines/xeen/party.cpp
@@ -51,7 +51,7 @@ PlayerStruct::PlayerStruct() {
 	_dbDay = 0;
 	_tempAge = 0;
 	Common::fill(&_skills[0], &_skills[18], 0);
-	Common::fill(&_awards[0], &_awards[512], false);
+	Common::fill(&_awards[0], &_awards[128], false);
 	Common::fill(&_spells[9], &_spells[312], false);
 	_lloydMap = 0;
 	_hasSpells = false;
@@ -95,9 +95,21 @@ void PlayerStruct::synchronize(Common::Serializer &s) {
 	s.syncAsByte(_dbDay);
 	s.syncAsByte(_tempAge);
 	
-	for (int i = 0; i < 18; ++i)
-		s.syncAsByte(_skills[i]);
-	SavesManager::syncBitFlags(s, &_awards[0], &_awards[512]);
+	// Synchronize the skill list
+	for (int idx = 0; idx < 18; ++idx)
+		s.syncAsByte(_skills[idx]);
+
+	// Synchronize character awards
+	for (int idx = 0; idx < 64; ++idx) {
+		byte b = (_awards[idx] ? 1 : 0) | (_awards[idx + 64] ? 0x10 : 0);
+		s.syncAsByte(b);
+		if (s.isLoading()) {
+			_awards[idx] = (b & 0xF) != 0;
+			_awards[idx + 64] = (b & 0xF0) != 0;
+		}
+	}
+
+	// Synchronize spell list
 	SavesManager::syncBitFlags(s, &_spells[0], &_spells[312]);
 	
 	s.syncAsByte(_lloydMap);
@@ -172,6 +184,26 @@ bool PlayerStruct::noActions() {
 	return false;
 }
 
+void PlayerStruct::setAward(int awardId, bool value) {
+	int v = awardId;
+	if (awardId == 73)
+		v = 126;
+	else if (awardId == 81)
+		v = 127;
+
+	_awards[v] = value;
+}
+
+bool PlayerStruct::hasAward(int awardId) {
+	int v = awardId;
+	if (awardId == 73)
+		v = 126;
+	else if (awardId == 81)
+		v = 127;
+
+	return _awards[v];
+}
+
 
 /*------------------------------------------------------------------------*/
 
diff --git a/engines/xeen/party.h b/engines/xeen/party.h
index 1937683..a00b189 100644
--- a/engines/xeen/party.h
+++ b/engines/xeen/party.h
@@ -99,7 +99,7 @@ public:
 	int _dbDay;
 	int _tempAge;
 	int _skills[18];
-	bool _awards[512];
+	bool _awards[128];
 	bool _spells[312];
 	int _lloydMap;
 	Common::Point _lloydPosition;
@@ -141,6 +141,10 @@ public:
 	bool charSavingThrow();
 
 	bool noActions();
+
+	bool hasAward(int awardId);
+
+	void setAward(int awardId, bool value);
 };
 
 class Roster: public Common::Array<PlayerStruct> {
diff --git a/engines/xeen/resources.cpp b/engines/xeen/resources.cpp
index 994762b..c167bdb 100644
--- a/engines/xeen/resources.cpp
+++ b/engines/xeen/resources.cpp
@@ -71,6 +71,8 @@ const char *const THE_PARTY_NEEDS_REST = "\x0B""012The Party needs rest!";
 const char *const WHO_WILL = "\X03""c\X0B""000\x09""000%s\x0A\x0A"
 	"Who will\x0A%s?\x0A\x0B""055F1 - F%d";
 
+const char *const WHATS_THE_PASSWORD = "What's the Password?";
+
 const char *const TERRAIN_TYPES[6] = {
 	"town", "cave", "towr", "cstl", "dung", "scfi"
 };
@@ -408,7 +410,7 @@ const int DIRECTION_ANIM_POSITIONS[4][4] = {
 	{ 0, 1, 2, 3 }, { 3, 0, 1, 2 }, { 2, 3, 0, 1 }, { 1, 2, 3, 0 }
 };
 
-const byte WALL_NUMBERS[4][48] = {
+const byte WALL_SHIFTS[4][48] = {
 	{
 		12, 0, 12, 8, 12, 12, 0, 12, 8, 12, 12, 0,
 		12, 0, 12, 8, 12, 8, 12, 12, 0, 12, 0, 12,
diff --git a/engines/xeen/resources.h b/engines/xeen/resources.h
index 28a3554..e62454e 100644
--- a/engines/xeen/resources.h
+++ b/engines/xeen/resources.h
@@ -36,6 +36,8 @@ extern const char *const THE_PARTY_NEEDS_REST;
 
 extern const char *const WHO_WILL;
 
+extern const char *const WHATS_THE_PASSWORD;
+
 extern const char *const TERRAIN_TYPES[6];
 
 extern const char *const SURFACE_TYPE_NAMES[15];
@@ -96,7 +98,7 @@ extern const int OUTDOOR_OBJECT_Y[2][12];
 
 extern const int DIRECTION_ANIM_POSITIONS[4][4];
 
-extern const byte WALL_NUMBERS[4][48];
+extern const byte WALL_SHIFTS[4][48];
 
 extern const int DRAW_NUMBERS[25];
 
diff --git a/engines/xeen/saves.cpp b/engines/xeen/saves.cpp
index c2b1510..da791cd 100644
--- a/engines/xeen/saves.cpp
+++ b/engines/xeen/saves.cpp
@@ -168,4 +168,8 @@ void SavesManager::writeCharFile() {
 	warning("TODO: writeCharFile");
 }
 
+void SavesManager::saveChars() {
+	warning("TODO: saveChars");
+}
+
 } // End of namespace Xeen
diff --git a/engines/xeen/saves.h b/engines/xeen/saves.h
index 6b73625..7dea941 100644
--- a/engines/xeen/saves.h
+++ b/engines/xeen/saves.h
@@ -77,6 +77,8 @@ public:
 
 	void writeCharFile();
 
+	void saveChars();
+
 	// Archive implementation
 	virtual Common::SeekableReadStream *createReadStreamForMember(const Common::String &name) const;
 };
diff --git a/engines/xeen/screen.cpp b/engines/xeen/screen.cpp
index de591d3..42182cc 100644
--- a/engines/xeen/screen.cpp
+++ b/engines/xeen/screen.cpp
@@ -182,6 +182,84 @@ void Window::drawList(DrawStruct *items, int count) {
 	}
 }
 
+/**
+ * Allows the user to enter a string
+ */
+int Window::getString(Common::String &line, int maxLen, int maxWidth) {
+	Interface &intf = *_vm->_interface;
+
+	_vm->_noDirectionSense = true;
+	Common::String msg = Common::String::format("\x03""l\t000\x04%03d\x03""c", maxWidth);
+	writeString(msg);
+	update();
+
+	while (!_vm->shouldQuit()) {
+		Common::KeyCode keyCode = doCursor(msg);
+		
+		if ((keyCode == Common::KEYCODE_BACKSPACE || keyCode == Common::KEYCODE_DELETE)
+				&& line.size() > 0)
+			line.deleteLastChar();
+		else if (keyCode >= Common::KEYCODE_SPACE && keyCode < Common::KEYCODE_DELETE
+				&& line.size() < maxLen && (line.size() > 0 || keyCode != Common::KEYCODE_SPACE)) {
+
+		} else if (keyCode == Common::KEYCODE_RETURN || keyCode == Common::KEYCODE_KP_ENTER) {
+			break;
+		} else if (keyCode == Common::KEYCODE_ESCAPE) {
+			line = "";
+			break;
+		}
+	}
+
+	_vm->_noDirectionSense = false;
+	return line.size();
+}
+
+/**
+ * Draws the cursor and waits until the user presses a key
+ */
+Common::KeyCode Window::doCursor(const Common::String &msg) {
+	EventsManager &events = *_vm->_events;
+	Interface &intf = *_vm->_interface;
+	Screen &screen = *_vm->_screen;
+	
+	bool oldUpDoorText = intf._upDoorText;
+	byte oldTillMove = intf._tillMove;
+	intf._upDoorText = false;
+	intf._tillMove = 0;
+
+	bool flag = !_vm->_startupWindowActive && !screen._windows[25]._enabled
+			&& _vm->_mode != MODE_FF && _vm->_mode != MODE_17;
+
+	Common::KeyCode ch = Common::KEYCODE_INVALID;
+	while (!_vm->shouldQuit()) {
+		events.updateGameCounter();
+
+		if (flag)
+			intf.draw3d(false);
+		writeString(msg);
+		update();
+
+		if (flag)
+			screen._windows[3].update();
+
+		events.wait(1, true);
+		if (events.isKeyPending()) {
+			Common::KeyState keyState;
+			events.getKey(keyState);
+			ch = keyState.keycode;
+			break;
+		}
+	}
+
+	writeString("");
+	update();
+
+	intf._tillMove = oldTillMove;
+	intf._upDoorText = oldUpDoorText;
+
+	return ch;
+}
+
 /*------------------------------------------------------------------------*/
 
 /**
diff --git a/engines/xeen/screen.h b/engines/xeen/screen.h
index adf956e..5e4e46c 100644
--- a/engines/xeen/screen.h
+++ b/engines/xeen/screen.h
@@ -26,6 +26,7 @@
 #include "common/scummsys.h"
 #include "common/system.h"
 #include "common/array.h"
+#include "common/keyboard.h"
 #include "common/rect.h"
 #include "xeen/font.h"
 #include "xeen/sprites.h"
@@ -66,6 +67,8 @@ private:
 	int _ycL, _ycH;
 
 	void open2();
+
+	Common::KeyCode doCursor(const Common::String &msg);
 public:
 	bool _enabled;
 public:
@@ -91,6 +94,8 @@ public:
 	void writeString(const Common::String &s);
 
 	void drawList(DrawStruct *items, int count);
+
+	int getString(Common::String &line, int maxLen, int maxWidth);
 };
 
 class Screen: public FontSurface {
diff --git a/engines/xeen/scripts.cpp b/engines/xeen/scripts.cpp
index 4ccac8b..afc86ab 100644
--- a/engines/xeen/scripts.cpp
+++ b/engines/xeen/scripts.cpp
@@ -21,8 +21,10 @@
  */
 
 #include "xeen/scripts.h"
+#include "xeen/dialogs_string_input.h"
 #include "xeen/dialogs_whowill.h"
 #include "xeen/party.h"
+#include "xeen/resources.h"
 #include "xeen/xeen.h"
 
 namespace Xeen {
@@ -167,7 +169,7 @@ void Scripts::doOpcode(MazeEvent &event) {
 		&Scripts::cmdIf, &Scripts::cmdIf, &Scripts::cmdIf,
 		&Scripts::cmdMoveObj, &Scripts::cmdTakeOrGive, &Scripts::cmdNoAction,
 		&Scripts::cmdRemove, &Scripts::cmdSetChar, &Scripts::cmdSpawn,
-		&Scripts::cmdDoTownEvent, &Scripts::cmdExit, &Scripts::cmdAfterMap,
+		&Scripts::cmdDoTownEvent, &Scripts::cmdExit, &Scripts::cmdAlterMap,
 		&Scripts::cmdGiveExtended, &Scripts::cmdConfirmWord, &Scripts::cmdDamage,
 		&Scripts::cmdJumpRnd, &Scripts::cmdAfterEvent, &Scripts::cmdCallEvent,
 		&Scripts::cmdReturn, &Scripts::cmdSetVar, &Scripts::cmdTakeOrGive,
@@ -180,7 +182,7 @@ void Scripts::doOpcode(MazeEvent &event) {
 		&Scripts::cmdItemType, &Scripts::cmdMakeNothingHere, &Scripts::cmdNoAction2,
 		&Scripts::cmdChooseNumeric, &Scripts::cmdDisplayBottomTwoLines,
 		&Scripts::cmdDisplayLarge, &Scripts::cmdExchObj, &Scripts::cmdFallToMap,
-		&Scripts::cmdDisplayMain, &Scripts::cmdGoto, &Scripts::cmdConfirmWord2,
+		&Scripts::cmdDisplayMain, &Scripts::cmdGoto, &Scripts::cmdConfirmWord,
 		&Scripts::cmdGotoRandom, &Scripts::cmdCutsceneEndDarkside,
 		&Scripts::cmdCutsceneEdWorld, &Scripts::cmdFlipWorld, &Scripts::cmdPlayCD
 	};
@@ -287,7 +289,21 @@ void Scripts::cmdIf(Common::Array<byte> &params) {
 	}
 }
 
-void Scripts::cmdMoveObj(Common::Array<byte> &params) { error("TODO"); }
+/**
+ * Moves the position of an object
+ */
+void Scripts::cmdMoveObj(Common::Array<byte> &params) { 
+	MazeObject &mazeObj = _vm->_map->_mobData._objects[params[0]];
+
+	if (mazeObj._position.x == params[1] && mazeObj._position.y == params[2]) {
+		// Already in position, so simply flip it
+		mazeObj._flipped = !mazeObj._flipped;
+	} else {
+		mazeObj._position.x = params[1];
+		mazeObj._position.y = params[2];
+	}
+}
+
 void Scripts::cmdTakeOrGive(Common::Array<byte> &params) { error("TODO"); }
 
 /**
@@ -318,7 +334,23 @@ void Scripts::cmdSetChar(Common::Array<byte> &params) {
 	cmdNoAction(params);
 }
 
-void Scripts::cmdSpawn(Common::Array<byte> &params) { error("TODO"); }
+/**
+ * Spawn a monster
+ */
+void Scripts::cmdSpawn(Common::Array<byte> &params) {
+	MazeMonster &monster = _vm->_map->_mobData._monsters[params[0]];
+	MonsterStruct &monsterData = _vm->_map->_monsterData[monster._spriteId];
+	monster._position.x = params[1];
+	monster._position.y = params[2];
+	monster._frame = _vm->getRandomNumber(7);
+	monster._field7 = 0;
+	monster._isAttacking = params[1] != 0;
+	monster._hp = monsterData._hp;
+
+	_var4F = 1;
+	cmdNoAction(params);
+}
+
 void Scripts::cmdDoTownEvent(Common::Array<byte> &params) { error("TODO"); }
 
 /**
@@ -328,9 +360,97 @@ void Scripts::cmdExit(Common::Array<byte> &params) {
 	_lineNum = -1;
 }
 
-void Scripts::cmdAfterMap(Common::Array<byte> &params) { error("TODO"); }
-void Scripts::cmdGiveExtended(Common::Array<byte> &params) { error("TODO"); }
-void Scripts::cmdConfirmWord(Common::Array<byte> &params) { error("TODO"); }
+/**
+ * Changes the value for the wall on a given cell
+ */
+void Scripts::cmdAlterMap(Common::Array<byte> &params) { 
+	Map &map = *_vm->_map;
+
+	if (params[2] == DIR_ALL) {
+		for (int dir = DIR_NORTH; dir <= DIR_WEST; ++dir)
+			map.setWall(Common::Point(params[0], params[1]), (Direction)dir, params[3]);
+	} else {
+		map.setWall(Common::Point(params[0], params[1]), (Direction)params[2], params[3]);
+	}
+
+	_var4F = true;
+	cmdNoAction(params);
+}
+
+void Scripts::cmdGiveExtended(Common::Array<byte> &params) { 
+	switch (params[0]) {
+	case 16:
+	case 34:
+	case 100:
+		// TODO
+		break;
+	case 25:
+	case 35:
+	case 101:
+	case 106:
+		// TODO
+		break;
+	default:
+		break;
+	}
+}
+
+void Scripts::cmdConfirmWord(Common::Array<byte> &params) { 
+	Map &map = *_vm->_map;
+	Common::String msg1 = params[2] ? map._events._text[params[2]] :
+		_vm->_interface->_interfaceText;
+	Common::String msg2;
+
+	if (_event->_opcode == OP_ConfirmWord_2) {
+		msg2 = map._events._text[params[3]];
+	} else if (params[3]) {
+		msg2 = "";
+	} else {
+		msg2 = WHATS_THE_PASSWORD;
+	}
+
+	int result = StringInput::show(_vm, params[0], msg1, msg2,_event->_opcode);
+	if (result) {
+		if (result == 33 && _vm->_files->_isDarkCc) {
+			doEndGame2();
+		} else if (result == 34 && _vm->_files->_isDarkCc) {
+			doWorldEnd();
+		} else if (result == 35 && _vm->_files->_isDarkCc &&
+				_vm->getGameID() == GType_WorldOfXeen) {
+			doEndGame();
+		} else if (result == 40 && !_vm->_files->_isDarkCc) {
+			doEndGame();
+		} else if (result == 60 && !_vm->_files->_isDarkCc) {
+			doEndGame2();
+		}
+		else if (result == 61 && !_vm->_files->_isDarkCc) {
+			doWorldEnd();
+		} else {		
+			if (result == 59 && !_vm->_files->_isDarkCc) {
+				for (int idx = 0; idx < TOTAL_ITEMS; ++idx) {
+					XeenItem &item = _vm->_treasure._weapons[idx];
+					if (!item._name) {
+						item._name = 34;
+						item._material = 0;
+						item._bonusFlags = 0;
+						_vm->_treasure._hasItems = true;
+						
+						cmdExit(params);
+						return;
+					}
+				}
+			}
+
+			_lineNum = result == -1 ? params[3] : params[1];
+			
+			return;
+		}
+	}
+
+	_var4F = true;
+	cmdNoAction(params);
+}
+
 void Scripts::cmdDamage(Common::Array<byte> &params) { error("TODO"); }
 void Scripts::cmdJumpRnd(Common::Array<byte> &params) { error("TODO"); }
 void Scripts::cmdAfterEvent(Common::Array<byte> &params) { error("TODO"); }
@@ -370,11 +490,45 @@ void Scripts::cmdExchObj(Common::Array<byte> &params) { error("TODO"); }
 void Scripts::cmdFallToMap(Common::Array<byte> &params) { error("TODO"); }
 void Scripts::cmdDisplayMain(Common::Array<byte> &params) { error("TODO"); }
 void Scripts::cmdGoto(Common::Array<byte> &params) { error("TODO"); }
-void Scripts::cmdConfirmWord2(Common::Array<byte> &params) { error("TODO"); }
+
 void Scripts::cmdGotoRandom(Common::Array<byte> &params) { error("TODO"); }
 void Scripts::cmdCutsceneEndDarkside(Common::Array<byte> &params) { error("TODO"); }
 void Scripts::cmdCutsceneEdWorld(Common::Array<byte> &params) { error("TODO"); }
 void Scripts::cmdFlipWorld(Common::Array<byte> &params) { error("TODO"); }
 void Scripts::cmdPlayCD(Common::Array<byte> &params) { error("TODO"); }
 
+void Scripts::doEndGame() {
+	doEnding("ENDGAME", 0);
+}
+
+void Scripts::doEndGame2() {
+	Party &party = *_vm->_party;
+	int v2 = 0;
+
+	for (int idx = 0; idx < party._partyCount; ++idx) {
+		PlayerStruct &player = party._activeParty[idx];
+		if (player.hasAward(77)) {
+			v2 = 2;
+			break;
+		}
+		else if (player.hasAward(76)) {
+			v2 = 1;
+			break;
+		}
+	}
+
+	doEnding("ENDGAME2", v2);
+}
+
+void Scripts::doWorldEnd() {
+
+}
+
+void Scripts::doEnding(const Common::String &endStr, int v2) {
+	_vm->_saves->saveChars();
+	
+	warning("TODO: doEnding");
+}
+
+
 } // End of namespace Xeen
diff --git a/engines/xeen/scripts.h b/engines/xeen/scripts.h
index 2e4996e..5f931c1 100644
--- a/engines/xeen/scripts.h
+++ b/engines/xeen/scripts.h
@@ -134,8 +134,6 @@ private:
 	Common::String _paramText;
 	MazeEvent *_event;
 
-	int whoWill(int v1, int v2, int v3);
-
 	void doOpcode(MazeEvent &event);
 	void cmdDisplay1(Common::Array<byte> &params);
 	void cmdDoorTextSml(Common::Array<byte> &params);
@@ -153,7 +151,7 @@ private:
 	void cmdSpawn(Common::Array<byte> &params);
 	void cmdDoTownEvent(Common::Array<byte> &params);
 	void cmdExit(Common::Array<byte> &params);
-	void cmdAfterMap(Common::Array<byte> &params);
+	void cmdAlterMap(Common::Array<byte> &params);
 	void cmdGiveExtended(Common::Array<byte> &params);
 	void cmdConfirmWord(Common::Array<byte> &params);
 	void cmdDamage(Common::Array<byte> &params);
@@ -185,12 +183,21 @@ private:
 	void cmdFallToMap(Common::Array<byte> &params);
 	void cmdDisplayMain(Common::Array<byte> &params);
 	void cmdGoto(Common::Array<byte> &params);
-	void cmdConfirmWord2(Common::Array<byte> &params);
 	void cmdGotoRandom(Common::Array<byte> &params);
 	void cmdCutsceneEndDarkside(Common::Array<byte> &params);
 	void cmdCutsceneEdWorld(Common::Array<byte> &params);
 	void cmdFlipWorld(Common::Array<byte> &params);
 	void cmdPlayCD(Common::Array<byte> &params);
+
+	int whoWill(int v1, int v2, int v3);
+
+	void doEndGame();
+
+	void doEndGame2();
+
+	void doWorldEnd();
+
+	void doEnding(const Common::String &endStr, int v2);
 public:
 	int _animCounter;
 	bool _eventSkipped;
diff --git a/engines/xeen/xeen.cpp b/engines/xeen/xeen.cpp
index 2d824e5..99adbb3 100644
--- a/engines/xeen/xeen.cpp
+++ b/engines/xeen/xeen.cpp
@@ -54,6 +54,7 @@ XeenEngine::XeenEngine(OSystem *syst, const XeenGameDescription *gameDesc)
 	_moveMonsters = false;
 	_mode = MODE_0;
 	_openDoor = 0;
+	_startupWindowActive = false;
 }
 
 XeenEngine::~XeenEngine() {
diff --git a/engines/xeen/xeen.h b/engines/xeen/xeen.h
index cf872b3..1065adf 100644
--- a/engines/xeen/xeen.h
+++ b/engines/xeen/xeen.h
@@ -72,6 +72,7 @@ enum XeenDebugChannels {
 };
 
 enum Mode {
+	MODE_FF = -1,
 	MODE_0 = 0,
 	MODE_1 = 1,
 	MODE_2 = 2,
@@ -139,6 +140,7 @@ public:
 	Screen *_screen;
 	Scripts *_scripts;
 	SoundManager *_sound;
+	Treasure _treasure;
 	Mode _mode;
 	GameEvent _gameEvent;
 	Common::SeekableReadStream *_eventData;
@@ -148,6 +150,7 @@ public:
 	bool _noDirectionSense;
 	bool _moveMonsters;
 	int _openDoor;
+	bool _startupWindowActive;
 public:
 	XeenEngine(OSystem *syst, const XeenGameDescription *gameDesc);
 	virtual ~XeenEngine();


Commit: c08e54fde105637082ee7eb79eeacd1cb4137d57
    https://github.com/scummvm/scummvm/commit/c08e54fde105637082ee7eb79eeacd1cb4137d57
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-01-23T21:12:35-05:00

Commit Message:
XEEN: Implement further script opcodes

Changed paths:
    engines/xeen/interface.cpp
    engines/xeen/map.cpp
    engines/xeen/map.h
    engines/xeen/party.cpp
    engines/xeen/party.h
    engines/xeen/saves.cpp
    engines/xeen/saves.h
    engines/xeen/scripts.cpp
    engines/xeen/xeen.cpp
    engines/xeen/xeen.h



diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp
index 7487d63..307027b 100644
--- a/engines/xeen/interface.cpp
+++ b/engines/xeen/interface.cpp
@@ -79,8 +79,9 @@ void Interface::setup() {
 }
 
 void Interface::manageCharacters(bool soundPlayed) {
-	Screen &screen = *_vm->_screen;
 	EventsManager &events = *_vm->_events;
+	Map &map = *_vm->_map;
+	Screen &screen = *_vm->_screen;
 	bool flag = false;
 
 start:
@@ -106,7 +107,7 @@ start:
 		// Build up a list of characters on the same Xeen side being loaded
 		for (int i = 0; i < XEEN_TOTAL_CHARACTERS; ++i) {
 			PlayerStruct &player = _vm->_roster[i];
-			if (player._name.empty() || player._xeenSide != _vm->_loadDarkSide)
+			if (player._name.empty() || player._xeenSide != (map._loadDarkSide ? 1 : 0))
 				continue;
 
 			xeenSideChars.push_back(i);
diff --git a/engines/xeen/map.cpp b/engines/xeen/map.cpp
index 7801a05..ca22b38 100644
--- a/engines/xeen/map.cpp
+++ b/engines/xeen/map.cpp
@@ -857,7 +857,8 @@ void AnimationInfo::load(const Common::String &name) {
 /*------------------------------------------------------------------------*/
 
 Map::Map(XeenEngine *vm) : _vm(vm), _mobData(vm) {
-	_townPortalSide = 0;
+	_townPortalSide = false;
+	_loadDarkSide = false;
 	_sideObjects = 0;
 	_sideMonsters = 0;
 	_sidePictures = 0;
@@ -896,13 +897,13 @@ void Map::load(int mapId) {
 	_sideMonsters = 1;
 	_sidePictures = 1;
 	if (mapId >= 113 && mapId <= 127) {
-		_townPortalSide = 0;
+		_townPortalSide = false;
 	} else {
-		_townPortalSide = _vm->_loadDarkSide;
+		_townPortalSide = _loadDarkSide;
 	}
 
 	if (_vm->getGameID() == GType_WorldOfXeen) {
-		if (_vm->_loadDarkSide) {
+		if (_loadDarkSide) {
 			_animationInfo.load("clouds.dat");
 			_monsterData.load("xeen.mon");
 			_wallPicSprites.load("xeenpic.dat");
diff --git a/engines/xeen/map.h b/engines/xeen/map.h
index 51f426d..273a4b4 100644
--- a/engines/xeen/map.h
+++ b/engines/xeen/map.h
@@ -345,7 +345,7 @@ private:
 	MazeData _mazeData[9];
 	Common::String _mazeName;
 	SpriteResource _wallPicSprites;
-	int _townPortalSide;
+	bool _townPortalSide;
 	int _sidePictures;
 	int _sideObjects;
 	int _sideMonsters;
@@ -374,6 +374,7 @@ public:
 	int _currentTile;
 	int _currentSurfaceId;
 	bool _currentSteppedOn;
+	bool _loadDarkSide;
 public:
 	Map(XeenEngine *vm);
 
diff --git a/engines/xeen/party.cpp b/engines/xeen/party.cpp
index b33318f..8d59e68 100644
--- a/engines/xeen/party.cpp
+++ b/engines/xeen/party.cpp
@@ -272,6 +272,8 @@ Party::Party(XeenEngine *vm): _vm(vm) {
 	_stepped = false;
 	_damageType = DT_PHYSICAL;
 	_falling = false;
+	_fallMaze = 0;
+	_fallDamage = 0;
 }
 
 void Party::synchronize(Common::Serializer &s) {
diff --git a/engines/xeen/party.h b/engines/xeen/party.h
index a00b189..3962ba4 100644
--- a/engines/xeen/party.h
+++ b/engines/xeen/party.h
@@ -221,6 +221,9 @@ public:
 	bool _isNight;
 	bool _stepped;
 	int _falling;
+	Common::Point _fallPosition;
+	int _fallMaze;
+	int _fallDamage;
 	DamageType _damageType;
 public:
 	Party(XeenEngine *vm);
diff --git a/engines/xeen/saves.cpp b/engines/xeen/saves.cpp
index da791cd..85ab60b 100644
--- a/engines/xeen/saves.cpp
+++ b/engines/xeen/saves.cpp
@@ -49,6 +49,8 @@ SavesManager::SavesManager(XeenEngine *vm, Party &party, Roster &roster) :
 		BaseCCArchive(), _vm(vm), _party(party), _roster(roster) {
 	SearchMan.add("saves", this, 0, false);
 	_data = nullptr;
+	_wonWorld = false;
+	_wonDarkSide = false;
 }
 
 SavesManager::~SavesManager() {
diff --git a/engines/xeen/saves.h b/engines/xeen/saves.h
index 7dea941..5d35518 100644
--- a/engines/xeen/saves.h
+++ b/engines/xeen/saves.h
@@ -67,6 +67,9 @@ private:
 public:
 	static void syncBitFlags(Common::Serializer &s, bool *startP, bool *endP);
 public:
+	bool _wonWorld;
+	bool _wonDarkSide;
+public:
 	SavesManager(XeenEngine *vm, Party &party, Roster &roster);
 
 	~SavesManager();
diff --git a/engines/xeen/scripts.cpp b/engines/xeen/scripts.cpp
index afc86ab..bbba4b9 100644
--- a/engines/xeen/scripts.cpp
+++ b/engines/xeen/scripts.cpp
@@ -486,15 +486,82 @@ void Scripts::cmdNoAction2(Common::Array<byte> &params) { error("TODO"); }
 void Scripts::cmdChooseNumeric(Common::Array<byte> &params) { error("TODO"); }
 void Scripts::cmdDisplayBottomTwoLines(Common::Array<byte> &params) { error("TODO"); }
 void Scripts::cmdDisplayLarge(Common::Array<byte> &params) { error("TODO"); }
-void Scripts::cmdExchObj(Common::Array<byte> &params) { error("TODO"); }
-void Scripts::cmdFallToMap(Common::Array<byte> &params) { error("TODO"); }
-void Scripts::cmdDisplayMain(Common::Array<byte> &params) { error("TODO"); }
-void Scripts::cmdGoto(Common::Array<byte> &params) { error("TODO"); }
-
-void Scripts::cmdGotoRandom(Common::Array<byte> &params) { error("TODO"); }
-void Scripts::cmdCutsceneEndDarkside(Common::Array<byte> &params) { error("TODO"); }
-void Scripts::cmdCutsceneEdWorld(Common::Array<byte> &params) { error("TODO"); }
-void Scripts::cmdFlipWorld(Common::Array<byte> &params) { error("TODO"); }
+
+/**
+ * Exchange the positions of two objects in the maze
+ */
+void Scripts::cmdExchObj(Common::Array<byte> &params) {
+	MazeObject &obj1 = _vm->_map->_mobData._objects[params[0]];
+	MazeObject &obj2 = _vm->_map->_mobData._objects[params[1]];
+
+	Common::Point pt = obj1._position;
+	obj1._position = obj2._position;
+	obj2._position = pt;
+
+	_var4F = true;
+	cmdNoAction(params);
+}
+
+void Scripts::cmdFallToMap(Common::Array<byte> &params) {
+	Party &party = *_vm->_party;
+	party._fallMaze = params[0];
+	party._fallPosition = Common::Point(params[1], params[2]);
+	party._fallDamage = params[3];
+
+	_var4F = true;
+	_lineNum = -1;
+}
+
+void Scripts::cmdDisplayMain(Common::Array<byte> &params) { 
+	error("TODO"); 
+}
+
+/**
+ * Jumps to a given line number if the surface at relative cell position 1 matches
+ * a specified surface.
+ * @remarks		This opcode is apparently never actually used
+ */
+void Scripts::cmdGoto(Common::Array<byte> &params) { 
+	Map &map = *_vm->_map;
+	map.getCell(1);
+	if (params[0] == map._currentSurfaceId)
+		_lineNum = params[1] - 1;
+
+	_var4F = true;
+	cmdNoAction(params);
+}
+
+/**
+ * Pick a random value from the parameter list and jump to that line number
+ */
+void Scripts::cmdGotoRandom(Common::Array<byte> &params) { 
+	_lineNum = params[_vm->getRandomNumber(1, params[0])] - 1;
+	_var4F = true;
+	cmdNoAction(params);
+}
+
+void Scripts::cmdCutsceneEndDarkside(Common::Array<byte> &params) { 
+	Party &party = *_vm->_party;
+	_vm->_saves->_wonDarkSide = true;
+	party._questItems[53] = 1;
+	party._darkSideEnd = true;
+	party._mazeId = 29;
+	party._mazeDirection = DIR_NORTH;
+	party._mazePosition = Common::Point(25, 21);
+
+	doEndGame2();
+}
+
+void Scripts::cmdCutsceneEdWorld(Common::Array<byte> &params) { 
+	_vm->_saves->_wonWorld = true;
+	_vm->_party->_worldEnd = true;
+	doWorldEnd();
+}
+
+void Scripts::cmdFlipWorld(Common::Array<byte> &params) { 
+	_vm->_map->_loadDarkSide = params[0] != 0;
+}
+
 void Scripts::cmdPlayCD(Common::Array<byte> &params) { error("TODO"); }
 
 void Scripts::doEndGame() {
diff --git a/engines/xeen/xeen.cpp b/engines/xeen/xeen.cpp
index 99adbb3..8489f86 100644
--- a/engines/xeen/xeen.cpp
+++ b/engines/xeen/xeen.cpp
@@ -48,7 +48,6 @@ XeenEngine::XeenEngine(OSystem *syst, const XeenGameDescription *gameDesc)
 	_scripts = nullptr;
 	_sound = nullptr;
 	_eventData = nullptr;
-	_loadDarkSide = 1;
 	_dangerSenseAllowed = false;
 	_noDirectionSense = false;
 	_moveMonsters = false;
@@ -287,8 +286,8 @@ void XeenEngine::play() {
 	_screen->loadPalette("mm4.pal");
 	_interface->loadPartyIcons();
 
-	if (getGameID() != GType_WorldOfXeen && !_loadDarkSide) {
-		_loadDarkSide = true;
+	if (getGameID() != GType_WorldOfXeen && !_map->_loadDarkSide) {
+		_map->_loadDarkSide = true;
 		_party->_mazeId = 29;
 		_party->_mazeDirection = DIR_NORTH;
 		_party->_mazePosition.x = 25;
diff --git a/engines/xeen/xeen.h b/engines/xeen/xeen.h
index 1065adf..b60908d 100644
--- a/engines/xeen/xeen.h
+++ b/engines/xeen/xeen.h
@@ -145,7 +145,6 @@ public:
 	GameEvent _gameEvent;
 	Common::SeekableReadStream *_eventData;
 	Roster _roster;
-	int _loadDarkSide;
 	bool _dangerSenseAllowed;
 	bool _noDirectionSense;
 	bool _moveMonsters;


Commit: fac1d0642fe21600c775be6379c5fd4098ab9d4e
    https://github.com/scummvm/scummvm/commit/fac1d0642fe21600c775be6379c5fd4098ab9d4e
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-01-23T21:25:58-05:00

Commit Message:
XEEN: Implement script opcodes for cmdCallEvent and cmdReturn

Changed paths:
    engines/xeen/scripts.cpp
    engines/xeen/scripts.h



diff --git a/engines/xeen/scripts.cpp b/engines/xeen/scripts.cpp
index bbba4b9..247165f 100644
--- a/engines/xeen/scripts.cpp
+++ b/engines/xeen/scripts.cpp
@@ -109,7 +109,7 @@ void Scripts::checkEvents() {
 //		int varA = 0;
 		_animCounter = 0;
 //		int var4E = 0;
-		const Common::Point pt = party._mazePosition;
+		_currentPos = party._mazePosition;
 		_charIndex = 1;
 		_v2 = 1;
 		_nEdamageType = 0;
@@ -127,8 +127,8 @@ void Scripts::checkEvents() {
 			for (eventIndex = 0; eventIndex < map._events.size(); ++eventIndex) {
 				MazeEvent &event = map._events[eventIndex];
 
-				if (event._position == pt && party._mazeDirection != (pt.x | pt.y)
-						&& event._line == _lineNum) {
+				if (event._position == _currentPos && party._mazeDirection != 
+						(_currentPos.x | _currentPos.y) && event._line == _lineNum) {
 					if (event._direction == party._mazeDirection || event._direction == DIR_ALL) {
 						_vm->_mode = MODE_9;
 						_paramText = event._parameters.size() == 0 ? "" :
@@ -454,8 +454,33 @@ void Scripts::cmdConfirmWord(Common::Array<byte> &params) {
 void Scripts::cmdDamage(Common::Array<byte> &params) { error("TODO"); }
 void Scripts::cmdJumpRnd(Common::Array<byte> &params) { error("TODO"); }
 void Scripts::cmdAfterEvent(Common::Array<byte> &params) { error("TODO"); }
-void Scripts::cmdCallEvent(Common::Array<byte> &params) { error("TODO"); }
-void Scripts::cmdReturn(Common::Array<byte> &params) { error("TODO"); }
+
+/**
+ * Stores the current location and line for later resuming, and set up to execute
+ * a script at a given location
+ */
+void Scripts::cmdCallEvent(Common::Array<byte> &params) { 
+	_stack.push(StackEntry(_currentPos, _lineNum));
+	_currentPos = Common::Point(params[0], params[1]);
+	_lineNum = params[2] - 1;
+
+	_var4F = true;
+	cmdNoAction(params);
+}
+
+/**
+ * Return from executing a script to the script location that previously 
+ * called the script
+ */
+void Scripts::cmdReturn(Common::Array<byte> &params) {
+	StackEntry &se = _stack.top();
+	_currentPos = se;
+	_lineNum = se.line;
+
+	_var4F = true;
+	cmdNoAction(params);
+}
+
 void Scripts::cmdSetVar(Common::Array<byte> &params) { error("TODO"); }
 void Scripts::cmdCutsceneEndClouds(Common::Array<byte> &params) { error("TODO"); }
 
diff --git a/engines/xeen/scripts.h b/engines/xeen/scripts.h
index 5f931c1..2924d43 100644
--- a/engines/xeen/scripts.h
+++ b/engines/xeen/scripts.h
@@ -26,6 +26,7 @@
 #include "common/scummsys.h"
 #include "common/system.h"
 #include "common/serializer.h"
+#include "common/stack.h"
 #include "common/str-array.h"
 #include "xeen/files.h"
 
@@ -117,6 +118,12 @@ public:
 	void synchronize(XeenSerializer &s);
 };
 
+struct StackEntry : public Common::Point {
+	int line;
+
+	StackEntry(const Common::Point &pt, int l) : Common::Point(pt), line(l) {}
+};
+
 class Scripts {
 private:
 	XeenEngine *_vm;
@@ -133,6 +140,8 @@ private:
 	int _nEdamageType;
 	Common::String _paramText;
 	MazeEvent *_event;
+	Common::Point _currentPos;
+	Common::Stack<StackEntry> _stack;
 
 	void doOpcode(MazeEvent &event);
 	void cmdDisplay1(Common::Array<byte> &params);


Commit: 7bfc0344210cf1ea85ccbe784ea54d172ebadc40
    https://github.com/scummvm/scummvm/commit/7bfc0344210cf1ea85ccbe784ea54d172ebadc40
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-01-23T21:33:18-05:00

Commit Message:
XEEN: Implement cmdJumpRnd script opcode

Changed paths:
    engines/xeen/scripts.cpp
    engines/xeen/scripts.h



diff --git a/engines/xeen/scripts.cpp b/engines/xeen/scripts.cpp
index 247165f..6a08286 100644
--- a/engines/xeen/scripts.cpp
+++ b/engines/xeen/scripts.cpp
@@ -452,8 +452,20 @@ void Scripts::cmdConfirmWord(Common::Array<byte> &params) {
 }
 
 void Scripts::cmdDamage(Common::Array<byte> &params) { error("TODO"); }
-void Scripts::cmdJumpRnd(Common::Array<byte> &params) { error("TODO"); }
-void Scripts::cmdAfterEvent(Common::Array<byte> &params) { error("TODO"); }
+
+/**
+ * Jump if a random number matches a given value
+ */
+void Scripts::cmdJumpRnd(Common::Array<byte> &params) {
+	int v = _vm->getRandomNumber(1, params[0]);
+	if (v == params[1])
+		_lineNum = params[2] - 1;
+
+	_var4F = true;
+	cmdNoAction(params);
+}
+
+void Scripts::cmdAlterEvent(Common::Array<byte> &params) { error("TODO"); }
 
 /**
  * Stores the current location and line for later resuming, and set up to execute
diff --git a/engines/xeen/scripts.h b/engines/xeen/scripts.h
index 2924d43..862c54d 100644
--- a/engines/xeen/scripts.h
+++ b/engines/xeen/scripts.h
@@ -165,7 +165,7 @@ private:
 	void cmdConfirmWord(Common::Array<byte> &params);
 	void cmdDamage(Common::Array<byte> &params);
 	void cmdJumpRnd(Common::Array<byte> &params);
-	void cmdAfterEvent(Common::Array<byte> &params);
+	void cmdAlterEvent(Common::Array<byte> &params);
 	void cmdCallEvent(Common::Array<byte> &params);
 	void cmdReturn(Common::Array<byte> &params);
 	void cmdSetVar(Common::Array<byte> &params);


Commit: 06b7eb220e6f7a98007f6eb011a23b04812506b1
    https://github.com/scummvm/scummvm/commit/06b7eb220e6f7a98007f6eb011a23b04812506b1
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-01-23T23:47:05-05:00

Commit Message:
XEEN: Implemented If script opcode

Changed paths:
    engines/xeen/interface.cpp
    engines/xeen/party.cpp
    engines/xeen/party.h
    engines/xeen/resources.cpp
    engines/xeen/resources.h
    engines/xeen/scripts.cpp
    engines/xeen/scripts.h



diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp
index 307027b..a23cee6 100644
--- a/engines/xeen/interface.cpp
+++ b/engines/xeen/interface.cpp
@@ -355,7 +355,7 @@ void Interface::charIconsPrint(bool updateFlag) {
 			PlayerStruct &ps = _vm->_party->_activeParty[charIndex];
 
 			// Draw the Hp bar
-			int maxHp = ps.getMaxHp();
+			int maxHp = ps.getMaxHP();
 			int frame;
 			if (ps._currentHp < 1)
 				frame = 4;
diff --git a/engines/xeen/party.cpp b/engines/xeen/party.cpp
index 8d59e68..43c2eca 100644
--- a/engines/xeen/party.cpp
+++ b/engines/xeen/party.cpp
@@ -158,17 +158,22 @@ Condition PlayerStruct::worstCondition() const {
 	return NO_CONDITION;
 }
 
-int PlayerStruct::getAge(int partyYear, bool ignoreTemp) {
-	int year = MIN(partyYear - _ybDay, 254);
+int PlayerStruct::getAge(bool ignoreTemp) const {
+	int year = MIN(Party::_vm->_party->_year - _ybDay, 254);
 
 	return ignoreTemp ? year : year + _tempAge;
 }
 
-int PlayerStruct::getMaxHp() {
+int PlayerStruct::getMaxHP() const {
 	warning("TODO: getMaxHp");
 	return 20;
 }
 
+int PlayerStruct::getMaxSP() const {
+	warning("TODO: getMaxSP");
+	return 20;
+}
+
 int PlayerStruct::getStat(int statNum, int v2) {
 	// TODO
 	return 10;
@@ -194,7 +199,7 @@ void PlayerStruct::setAward(int awardId, bool value) {
 	_awards[v] = value;
 }
 
-bool PlayerStruct::hasAward(int awardId) {
+bool PlayerStruct::hasAward(int awardId) const {
 	int v = awardId;
 	if (awardId == 73)
 		v = 126;
@@ -204,6 +209,15 @@ bool PlayerStruct::hasAward(int awardId) {
 	return _awards[v];
 }
 
+int PlayerStruct::getArmorClass(bool baseOnly) const {
+	// TODO
+	return 1;
+}
+
+int PlayerStruct::getThievery() const {
+	// TODO
+	return 1;
+}
 
 /*------------------------------------------------------------------------*/
 
@@ -217,7 +231,10 @@ void Roster::synchronize(Common::Serializer &s) {
 
 /*------------------------------------------------------------------------*/
 
-Party::Party(XeenEngine *vm): _vm(vm) {
+XeenEngine *Party::_vm;
+
+Party::Party(XeenEngine *vm) {
+	_vm = vm;
 	_partyCount = 0;
 	_realPartyCount = 0;
 	Common::fill(&_partyMembers[0], &_partyMembers[8], 0);
@@ -258,7 +275,7 @@ Party::Party(XeenEngine *vm): _vm(vm) {
 	_rested = false;
 
 	Common::fill(&_gameFlags[0], &_gameFlags[512], false);
-	Common::fill(&_autoNotes[0], &_autoNotes[128], false);
+	Common::fill(&_worldFlags[0], &_worldFlags[128], false);
 	Common::fill(&_quests[0], &_quests[64], false);
 	Common::fill(&_questItems[0], &_questItems[85], 0);
 
@@ -337,7 +354,7 @@ void Party::synchronize(Common::Serializer &s) {
 	s.syncAsUint32LE(_totalTime);
 	s.syncAsByte(_rested);
 	SavesManager::syncBitFlags(s, &_gameFlags[0], &_gameFlags[512]);
-	SavesManager::syncBitFlags(s, &_autoNotes[0], &_autoNotes[128]);
+	SavesManager::syncBitFlags(s, &_worldFlags[0], &_worldFlags[128]);
 	SavesManager::syncBitFlags(s, &_quests[0], &_quests[64]);
 
 	for (int i = 0; i < 85; ++i)
diff --git a/engines/xeen/party.h b/engines/xeen/party.h
index 3962ba4..2677813 100644
--- a/engines/xeen/party.h
+++ b/engines/xeen/party.h
@@ -132,9 +132,11 @@ public:
 
 	Condition worstCondition() const;
 
-	int getAge(int partyYear, bool ignoreTemp);
+	int getAge(bool ignoreTemp) const;
 
-	int getMaxHp();
+	int getMaxHP() const;
+
+	int getMaxSP() const;
 
 	int getStat(int statNum, int v2);
 
@@ -142,9 +144,13 @@ public:
 
 	bool noActions();
 
-	bool hasAward(int awardId);
-
 	void setAward(int awardId, bool value);
+
+	bool hasAward(int awardId) const;
+
+	int getArmorClass(bool baseOnly) const;
+
+	int getThievery() const;
 };
 
 class Roster: public Common::Array<PlayerStruct> {
@@ -155,8 +161,9 @@ public:
 };
 
 class Party {
+	friend class PlayerStruct;
 private:
-	XeenEngine *_vm;
+	static XeenEngine *_vm;
 public:
 	// Dynamic data that's saved
 	int _partyCount;
@@ -204,7 +211,7 @@ public:
 	int _totalTime;
 	bool _rested;
 	bool _gameFlags[512];
-	bool _autoNotes[128];
+	bool _worldFlags[128];
 	bool _quests[64];
 	int _questItems[85];
 	XeenItem _blacksmithWeapons2[ITEMS_COUNT];
diff --git a/engines/xeen/resources.cpp b/engines/xeen/resources.cpp
index c167bdb..837ff15 100644
--- a/engines/xeen/resources.cpp
+++ b/engines/xeen/resources.cpp
@@ -471,4 +471,23 @@ const int MONSTER_EFFECT_FLAGS[15][8] = {
 	{ 0x108, 0x108, 0x108, 0x108, 0x108, 0x108, 0x108, 0x108 }
 };
 
+const int SPELLS_ALLOWED[3][40] = {
+	{
+		0, 1, 2, 3, 5, 6, 7, 8, 9, 10,
+		12, 14, 16, 23, 26, 27, 28, 30, 31, 32,
+		33, 42, 46, 48, 49, 50, 52, 55, 56, 58,
+		59, 62, 64, 65, 67, 68, 71, 73, 74, 76
+	}, {
+		1, 4, 11, 13, 15, 17, 18, 19, 20, 21,
+		22, 24, 25, 29, 34, 35, 36, 37, 38, 39,
+		40, 41, 42, 43, 44, 45, 47, 51, 53, 54,
+		57, 60, 61, 63, 66, 69, 70, 72, 75, 76
+	}, {
+		0, 1, 2, 3, 4, 5, 7, 9, 10, 20,
+		25, 26, 27, 28, 30, 31, 34, 38, 40, 41,
+		42, 43, 44, 45, 49, 50, 52, 53, 55, 59,
+		60, 61, 62, 67, 68, 72, 73, 74, 75, 76
+	}
+};
+
 } // End of namespace Xeen
diff --git a/engines/xeen/resources.h b/engines/xeen/resources.h
index e62454e..36ac6b2 100644
--- a/engines/xeen/resources.h
+++ b/engines/xeen/resources.h
@@ -110,6 +110,8 @@ extern const int COMBAT_FLOAT_Y[8];
 
 extern const int MONSTER_EFFECT_FLAGS[15][8];
 
+extern const int SPELLS_ALLOWED[3][40];
+
 } // End of namespace Xeen
 
 #endif	/* XEEN_RESOURCES_H */
diff --git a/engines/xeen/scripts.cpp b/engines/xeen/scripts.cpp
index 6a08286..d59346e 100644
--- a/engines/xeen/scripts.cpp
+++ b/engines/xeen/scripts.cpp
@@ -23,6 +23,7 @@
 #include "xeen/scripts.h"
 #include "xeen/dialogs_string_input.h"
 #include "xeen/dialogs_whowill.h"
+#include "xeen/dialogs_yesno.h"
 #include "xeen/party.h"
 #include "xeen/resources.h"
 #include "xeen/xeen.h"
@@ -171,7 +172,7 @@ void Scripts::doOpcode(MazeEvent &event) {
 		&Scripts::cmdRemove, &Scripts::cmdSetChar, &Scripts::cmdSpawn,
 		&Scripts::cmdDoTownEvent, &Scripts::cmdExit, &Scripts::cmdAlterMap,
 		&Scripts::cmdGiveExtended, &Scripts::cmdConfirmWord, &Scripts::cmdDamage,
-		&Scripts::cmdJumpRnd, &Scripts::cmdAfterEvent, &Scripts::cmdCallEvent,
+		&Scripts::cmdJumpRnd, &Scripts::cmdAlterEvent, &Scripts::cmdCallEvent,
 		&Scripts::cmdReturn, &Scripts::cmdSetVar, &Scripts::cmdTakeOrGive,
 		&Scripts::cmdTakeOrGive, &Scripts::cmdCutsceneEndClouds,
 		&Scripts::cmdTeleport, &Scripts::cmdWhoWill,
@@ -378,21 +379,47 @@ void Scripts::cmdAlterMap(Common::Array<byte> &params) {
 }
 
 void Scripts::cmdGiveExtended(Common::Array<byte> &params) { 
+	Party &party = *_vm->_party;
+	uint32 mask;
+	int newLineNum;
+	bool result;
+
 	switch (params[0]) {
 	case 16:
 	case 34:
 	case 100:
-		// TODO
+		mask = (params[4] << 24) | params[3] | (params[2] << 8) | (params[1] << 16);
+		newLineNum = params[5];
 		break;
 	case 25:
 	case 35:
 	case 101:
 	case 106:
-		// TODO
+		mask = (params[2] << 8) | params[1];
+		newLineNum = params[3];
 		break;
 	default:
+		mask = params[1];
+		newLineNum = params[2];
 		break;
 	}
+
+	if ((_charIndex != 0 & _charIndex != 8) || params[0] == 44) {
+		result = ifProc(params[0], mask, _event->_opcode - OP_If1, _charIndex - 1);
+	} else {
+		result = false;
+		for (int idx = 0; idx < party._partyCount && !result; ++idx) {
+			if (_charIndex == 0 || (_charIndex == 8 && _v2 != idx)) {
+				result = ifProc(params[0], mask, _event->_opcode - OP_If1, idx);
+			}
+		}
+	}
+
+	if (result)
+		_lineNum = newLineNum - 1;
+
+	_var4F = true;
+	cmdNoAction(params);
 }
 
 void Scripts::cmdConfirmWord(Common::Array<byte> &params) { 
@@ -634,5 +661,386 @@ void Scripts::doEnding(const Common::String &endStr, int v2) {
 	warning("TODO: doEnding");
 }
 
+/**
+ * This monstrosity handles doing the various types of If checks on various data
+ */
+bool Scripts::ifProc(int action, uint32 mask, int mode, int charIndex) {
+	Party &party = *_vm->_party;
+	PlayerStruct &ps = party._activeParty[charIndex];
+	uint v = 0;
+
+	switch (action) {
+	case 3:
+		// Player sex
+		v = (uint)ps._sex;
+		break;
+	case 4:
+		// Player race
+		v = (uint)ps._race;
+		break;
+	case 5:
+		// Player class
+		v = (uint)ps._class;
+		break;
+	case 8:
+		// Current health points
+		v = (uint)ps._currentHp;
+		break;
+	case 9:
+		// Current spell points
+		v = (uint)ps._currentSp;
+		break;
+	case 10:
+		// Get armor class
+		v = (uint)ps.getArmorClass(false);
+		break;
+	case 11:
+		// Level bonus (extra beyond base)
+		v = ps._level._temporary;
+		break;
+	case 12:
+		// Current age, including unnatural aging
+		v = ps.getAge(false);
+		break;
+	case 13:
+		assert(mask < 18);
+		if (ps._skills[mask])
+			v = mask;
+		break;
+	case 15:
+		// Award
+		assert(mask < 128);
+		if (ps.hasAward(mask))
+			v = mask;
+		break;
+	case 16:
+		// Experience
+		v = ps._experience;
+		break;
+	case 17:
+		// Party poison resistence
+		v = party._poisonResistence;
+		break;
+	case 18:
+		// Condition
+		assert(mask < 16);
+		if (!ps._conditions[mask] && !(mask & 0x10))
+			v = mask;
+		break;
+	case 19: {
+		// Can player cast a given spell
+
+		// Get the type of character
+		int category;
+		switch (ps._class) {
+		case CLASS_KNIGHT:
+		case CLASS_ARCHER:
+			category = 0;
+			break;
+		case CLASS_PALADIN:
+		case CLASS_CLERIC:
+			category = 1;
+			break;
+		case CLASS_BARBARIAN:
+		case CLASS_DRUID:
+			category = 2;
+			break;
+		default:
+			category = 0;
+			break;
+		}
+
+		// Check if the character class can cast the particular spell
+		for (int idx = 0; idx < 39; ++idx) {
+			if (SPELLS_ALLOWED[mode][idx] == mask) {
+				// Can cast it. Check if the player has it in their spellbook
+				if (ps._spells[idx])
+					v = mask;
+				break;
+			}
+		}
+		break;
+	}
+	case 20:
+		if (_vm->_files->_isDarkCc)
+			mask += 0x100;
+		assert(mask < 0x200);
+		if (party._gameFlags[mask])
+			v = mask;
+		break;
+	case 21:
+		// Scans inventories for given item number
+		v = 0xFFFFFFFF;
+		if (mask < 82) {
+			for (int idx = 0; idx < 9; ++idx) {
+				if (mask == 35) {
+					if (ps._weapons[idx]._name == mask) {
+						v = mask;
+						break;
+					}
+				} else if (mask < 49) {
+					if (ps._armor[idx]._name == (mask - 35)) {
+						v = mask;
+						break;
+					}
+				} else if (mask < 60) {
+					if (ps._accessories[idx]._name == (mask - 49)) {
+						v = mask;
+						break;
+					}
+				} else {
+					if (ps._misc[idx]._name == (mask - 60)) {
+						v = mask;
+						break;
+					}
+				}
+			}
+		} else {
+			int baseFlag = 8 * (6 + mask);
+			for (int idx = 0; idx < 8; ++idx) {
+				if (party._gameFlags[baseFlag + idx]) {
+					v = mask;
+					break;
+				}
+			}
+		}
+		break;
+	case 25:
+		// Returns number of minutes elapsed in the day (0-1440)
+		v = party._minutes;
+		break;
+	case 34:
+		// Current party gold
+		v = party._gold;
+		break;
+	case 35:
+		// Current party gems
+		v = party._gems;
+		break;
+	case 37:
+		// Might bonus (extra beond base)
+		v = ps._might._temporary;
+		break;
+	case 38:
+		// Intellect bonus (extra beyond base)
+		v = ps._intellect._temporary;
+		break;
+	case 39:
+		// Personality bonus (extra beyond base)
+		v = ps._personality._temporary;
+		break;
+	case 40:
+		// Endurance bonus (extra beyond base)
+		v = ps._endurance._temporary;
+		break;
+	case 41:
+		// Speed bonus (extra beyond base)
+		v = ps._speed._temporary;
+		break;
+	case 42:
+		// Accuracy bonus (extra beyond base)
+		v = ps._accuracy._temporary;
+		break;
+	case 43:
+		// Luck bonus (extra beyond base)
+		v = ps._luck._temporary;
+		break;
+	case 44:
+		v = YesNo::show(_vm, mask, 0);
+		if (!mask && v)
+			v = 0;
+		break;
+	case 45:
+		// Might base (before bonus)
+		v = ps._might._permanent;
+		break;
+	case 46:
+		// Intellect base (before bonus)
+		v = ps._intellect._permanent;
+		break;
+	case 47:
+		// Personality base (before bonus)
+		v = ps._personality._permanent;
+		break;
+	case 48:
+		// Endurance base (before bonus)
+		v = ps._endurance._permanent;
+		break;
+	case 49:
+		// Speed base (before bonus)
+		v = ps._speed._permanent;
+		break;
+	case 50:
+		// Accuracy base (before bonus)
+		v = ps._accuracy._permanent;
+		break;
+	case 51:
+		// Luck base (before bonus)
+		v = ps._luck._permanent;
+		break;
+	case 52:
+		// Fire resistence (before bonus)
+		v = ps._fireResistence._permanent;
+		break;
+	case 53:
+		// Elecricity resistence (before bonus)
+		v = ps._electricityResistence._permanent;
+		break;
+	case 54:
+		// Cold resistence (before bonus)
+		v = ps._coldResistence._permanent;
+		break;
+	case 55:
+		// Poison resistence (before bonus)
+		v = ps._poisonResistence._permanent;
+		break;
+	case 56:
+		// Energy reistence (before bonus)
+		v = ps._energyResistence._permanent;
+		break;
+	case 57:
+		// Energy resistence (before bonus)
+		v = ps._magicResistence._permanent;
+		break;
+	case 58:
+		// Fire resistence (extra beyond base)
+		v = ps._fireResistence._temporary;
+		break;
+	case 59:
+		// Electricity resistence (extra beyond base)
+		v = ps._electricityResistence._temporary;
+		break;
+	case 60:
+		// Cold resistence (extra beyond base)
+		v = ps._coldResistence._temporary;
+		break;
+	case 61:
+		// Poison resistence (extra beyod base)
+		v = ps._poisonResistence._temporary;
+		break;
+	case 62:
+		// Energy resistence (extra beyond base)
+		v = ps._energyResistence._temporary;
+		break;
+	case 63:
+		// Magic resistence (extra beyond base)
+		v = ps._magicResistence._temporary;
+		break;
+	case 64:
+		// Level (before bonus)
+		v = ps._level._permanent;
+		break;
+	case 65:
+		// Total party food
+		v = party._food;
+		break;
+	case 69:
+		// Test for Levitate being active
+		v = party._levitateActive ? 1 : 0;
+		break;
+	case 70:
+		// Amount of light
+		v = party._lightCount;
+		break;
+	case 71:
+		// Party magical fire resistence
+		v = party._fireResistence;
+		break;
+	case 72:
+		// Party magical electricity resistence
+		v = party._electricityResistence;
+		break;
+	case 73:
+		// Party magical cold resistence
+		v = party._coldResistence;
+		break;
+	case 76:
+		// Day of the year (100 per year)
+		v = party._day;
+		break;
+	case 77:
+		// Armor class (extra beyond base)
+		v = ps._ACTemp;
+		break;
+	case 78:
+		// Test whether current Hp is equal to or exceeds the max HP
+		v = ps._currentHp >= ps.getMaxHP() ? 1 : 0;
+		break;
+	case 79:
+		// Test for Wizard Eye being active
+		v = party._wizardEyeActive ? 1 : 0;
+		break;
+	case 81:
+		// Test whether current Sp is equal to or exceeds the max SP
+		v = ps._currentSp >= ps.getMaxSP() ? 1 : 0;
+		break;
+	case 84:
+		// Current facing direction
+		v = (uint)party._mazeDirection;
+		break;
+	case 85:
+		// Current game year since start
+		v = party._year;
+		break;
+	case 86:
+	case 87:
+	case 88:
+	case 89:
+	case 90:
+	case 91:
+	case 92:
+		// Get a player stat
+		v = ps.getStat(action - 86, 0);
+		break;
+	case 93:
+		// Current day of the week (10 days per week)
+		v = party._day / 10;
+		break;
+	case 94:
+		// Test whether Walk on Water is currently active
+		v = party._walkOnWaterActive ? 1 : 0;
+		break;
+	case 99:
+		// Party skills check
+		if (party.checkSkill((Skill)mask))
+			v = mask;
+		break;
+	case 102:
+		// Thievery skill
+		v = ps.getThievery();
+		break;
+	case 103:
+		// Get value of world flag
+		if (party._worldFlags[mask])
+			v = mask;
+		break;
+	case 104:
+		// Get value of quest flag
+		if (party._quests[mask + (_vm->_files->_isDarkCc ? 30 : 0)])
+			v = mask;
+		break;
+	case 105:
+		// Test number of Megacredits in party. Only used by King's Engineer in Castle Burlock
+		v = party._questItems[26];
+		break;
+	case 107:
+		// Get value of character flag
+		error("Unused");
+		break;
+	default:
+		break;
+	}
+
+	switch (mode) {
+	case 0:
+		return mask >= v;
+	case 1:
+		return mask == v;
+	case 2:
+		return mask <= v;
+	default:
+		return false;
+	}
+}
 
 } // End of namespace Xeen
diff --git a/engines/xeen/scripts.h b/engines/xeen/scripts.h
index 862c54d..fb415ca 100644
--- a/engines/xeen/scripts.h
+++ b/engines/xeen/scripts.h
@@ -41,8 +41,8 @@ enum Opcode {
 	OP_NPC			= 0x05,
 	OP_PlayFX		= 0x06,
 	OP_TeleportAndExit = 0x07,
-	OP_If_1			= 0x08,
-	OP_If_2			= 0x09,
+	OP_If1			= 0x08,
+	OP_If2			= 0x09,
 	OP_If3			= 0x0A,
 	OP_MoveObj		= 0x0B,
 	OP_TakeOrGive	= 0x0C,
@@ -207,6 +207,8 @@ private:
 	void doWorldEnd();
 
 	void doEnding(const Common::String &endStr, int v2);
+
+	bool ifProc(int action, uint32 mask, int mode, int charIndex);
 public:
 	int _animCounter;
 	bool _eventSkipped;


Commit: 3ec43ce1cc118f1d0168f25d3d9d0c252758b629
    https://github.com/scummvm/scummvm/commit/3ec43ce1cc118f1d0168f25d3d9d0c252758b629
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-01-24T00:00:20-05:00

Commit Message:
XEEN: Implement the cmdRemove and cmdMakeNothingHere script opcodes

Changed paths:
    engines/xeen/interface_map.h
    engines/xeen/scripts.cpp



diff --git a/engines/xeen/interface_map.h b/engines/xeen/interface_map.h
index 914120f..3ae73b7 100644
--- a/engines/xeen/interface_map.h
+++ b/engines/xeen/interface_map.h
@@ -111,7 +111,6 @@ protected:
 	bool _flipDefaultGround;
 	bool _isShooting;
 	bool _charsShooting;
-	int _objNumber;
 	bool _thinWall;
 	bool _isAnimReset;
 	int _batUIFrame;
@@ -147,6 +146,7 @@ public:
 	int _face1State;
 	int _face2State;
 	byte _tillMove;
+	int _objNumber;
 public:
 	InterfaceMap(XeenEngine *vm);
 
diff --git a/engines/xeen/scripts.cpp b/engines/xeen/scripts.cpp
index d59346e..ffe5441 100644
--- a/engines/xeen/scripts.cpp
+++ b/engines/xeen/scripts.cpp
@@ -315,7 +315,18 @@ void Scripts::cmdNoAction(Common::Array<byte> &params) {
 	_lineNum = _vm->_party->_partyDead ? -1 : _lineNum + 1;
 }
 
-void Scripts::cmdRemove(Common::Array<byte> &params) { error("TODO"); }
+void Scripts::cmdRemove(Common::Array<byte> &params) { 
+	Interface &intf = *_vm->_interface;
+	Map &map = *_vm->_map;
+
+	if (intf._objNumber) {
+		// Give the active object a completely way out of bounds position
+		MazeObject &obj = map._mobData._objects[intf._objNumber - 1];
+		obj._position = Common::Point(128, 128);
+	}
+
+	cmdMakeNothingHere(params);
+}
 
 /**
  * Set the currently active character for other script operations
@@ -545,7 +556,26 @@ void Scripts::cmdIfMapFlag(Common::Array<byte> &params) { error("TODO"); }
 void Scripts::cmdSelRndChar(Common::Array<byte> &params) { error("TODO"); }
 void Scripts::cmdGiveEnchanted(Common::Array<byte> &params) { error("TODO"); }
 void Scripts::cmdItemType(Common::Array<byte> &params) { error("TODO"); }
-void Scripts::cmdMakeNothingHere(Common::Array<byte> &params) { error("TODO"); }
+
+/**
+ * Disable all the scripts at the party's current position
+ */
+void Scripts::cmdMakeNothingHere(Common::Array<byte> &params) {
+	Map &map = *_vm->_map;
+	Party &party = *_vm->_party;
+
+	// Scan through the event list and mark the opcodes for all the lines of any scripts
+	// on the party's current cell as having no operation, effectively disabling them
+	for (int idx = 0; idx < map._events.size(); ++idx) {
+		MazeEvent &evt = map._events[idx];
+		if (evt._position == party._mazePosition)
+			evt._opcode = OP_None;
+	}
+
+	_var4F = true;
+	cmdExit(params);
+}
+
 void Scripts::cmdNoAction2(Common::Array<byte> &params) { error("TODO"); }
 void Scripts::cmdChooseNumeric(Common::Array<byte> &params) { error("TODO"); }
 void Scripts::cmdDisplayBottomTwoLines(Common::Array<byte> &params) { error("TODO"); }


Commit: b533822c0666ade51d2da2047e87351d3047fb58
    https://github.com/scummvm/scummvm/commit/b533822c0666ade51d2da2047e87351d3047fb58
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-01-24T09:27:48-05:00

Commit Message:
XEEN: Implement lots of stubbed PlayerStruct methods

Changed paths:
    engines/xeen/combat.h
    engines/xeen/items.cpp
    engines/xeen/items.h
    engines/xeen/map.cpp
    engines/xeen/party.cpp
    engines/xeen/party.h
    engines/xeen/resources.cpp
    engines/xeen/resources.h
    engines/xeen/scripts.cpp



diff --git a/engines/xeen/combat.h b/engines/xeen/combat.h
index 882f90e..550b39f 100644
--- a/engines/xeen/combat.h
+++ b/engines/xeen/combat.h
@@ -28,7 +28,7 @@
 namespace Xeen {
 
 enum DamageType {
-	DT_PHYSICAL = 0, DT_1 = 1, DT_FIRE = 2, DT_ELECTRICAL = 3,
+	DT_PHYSICAL = 0, DT_MAGICAL = 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,
diff --git a/engines/xeen/items.cpp b/engines/xeen/items.cpp
index e9425f7..f7dfecc 100644
--- a/engines/xeen/items.cpp
+++ b/engines/xeen/items.cpp
@@ -21,6 +21,7 @@
  */
 
 #include "xeen/items.h"
+#include "xeen/resources.h"
 
 namespace Xeen {
 
@@ -36,6 +37,23 @@ void XeenItem::synchronize(Common::Serializer &s) {
 	s.syncAsByte(_equipped);
 }
 
+int XeenItem::getElementalCategory() const {
+	int idx;
+	for (idx = 0; ELEMENTAL_CATEGORIES[idx] < _material; ++idx)
+		;
+
+	return idx;
+}
+
+int XeenItem::getAttributeCategory() const {
+	int m = _material - 59;
+	int idx;
+	for (idx = 0; ATTRIBUTE_CATEGORIES[idx] < m; ++idx)
+		;
+
+	return idx;
+}
+
 Treasure::Treasure() {
 	_hasItems = false;
 }
diff --git a/engines/xeen/items.h b/engines/xeen/items.h
index 6fa57b9..9141def 100644
--- a/engines/xeen/items.h
+++ b/engines/xeen/items.h
@@ -40,6 +40,10 @@ public:
 	XeenItem();
 
 	void synchronize(Common::Serializer &s);
+
+	int getElementalCategory() const;
+
+	int getAttributeCategory() const;
 };
 
 class Treasure {
diff --git a/engines/xeen/map.cpp b/engines/xeen/map.cpp
index ca22b38..750e634 100644
--- a/engines/xeen/map.cpp
+++ b/engines/xeen/map.cpp
@@ -170,7 +170,7 @@ MonsterData::MonsterData() {
 				   10, 100, 10, 10, 10, 10, 0, 0, 0, 10, 0, false, 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,
+				   500, 1, DT_MAGICAL, SA_NONE, 1, 1, MONSTER_HUMANOID, 20, 50,
 				   20, 20, 20, 30, 0, 0, 0, 25, 4, false, 8, 0, 0, 117,
 				   "cleric"));
 	push_back(MonsterStruct("Mantis Ant", 40000, 300, 30, 40, 2, CLASS_16, 2, 100,
@@ -226,7 +226,7 @@ MonsterData::MonsterData() {
 				   DT_PHYSICAL, SA_NONE, 1, 0, MONSTER_0, 0, 0, 0, 0, 0,
 				   0, 0, 0, 0, 0, 0, false, 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,
+				   250, DT_MAGICAL, SA_DRAINSP, 1, 0, MONSTER_GOLEM, 100, 100,
 				   100, 100, 100, 100, 50, 0, 0, 100, 0, true, 24, 0, 10,
 				   100, "golem"));
 	push_back(MonsterStruct("Gremlin", 2000, 20, 7, 35, 2, CLASS_16, 2, 10,
@@ -260,7 +260,7 @@ MonsterData::MonsterData() {
 				   DT_FIRE, SA_NONE, 1, 0, MONSTER_INSECT, 100, 100, 0,
 				   100, 0, 0, 0, 0, 0, 0, 0, false, 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,
+				   DT_MAGICAL, SA_UNCONSCIOUS, 1, 1, MONSTER_UNDEAD, 0, 0, 0, 0,
 				   0, 80, 70, 0, 0, 0, 0, true, 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,
@@ -317,7 +317,7 @@ MonsterData::MonsterData() {
 				   10, 100, 10, 10, 10, 20, 0, 0, 0, 20, 0, false, 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,
+				   DT_MAGICAL, SA_NONE, 1, 1, MONSTER_HUMANOID, 10, 20, 10, 10,
 				   10, 80, 0, 0, 0, 50, 5, false, 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,
@@ -367,7 +367,7 @@ MonsterData::MonsterData() {
 				   50, 50, 50, 50, 50, 0, 0, 0, 50, 0, false, 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,
+				   25, DT_MAGICAL, SA_NONE, 1, 1, MONSTER_HUMANOID, 50, 30, 30,
 				   30, 30, 30, 0, 0, 0, 20, 0, false, 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,
@@ -391,7 +391,7 @@ MonsterData::MonsterData() {
 				   MONSTER_HUMANOID, 80, 80, 80, 80, 80, 20, 0, 0, 200,
 				   0, 7, false, 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,
+				   DT_MAGICAL, SA_DEATH, 1, 1, MONSTER_UNDEAD, 0, 0, 0, 0, 0,
 				   90, 80, 0, 0, 100, 7, true, 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,
@@ -439,7 +439,7 @@ MonsterData::MonsterData() {
 				   0, MONSTER_UNDEAD, 80, 80, 80, 80, 80, 80, 90, 0, 0, 0,
 				   0, false, 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,
+				   DT_MAGICAL, SA_NONE, 1, 0, MONSTER_HUMANOID, 50, 30, 30, 30,
 				   40, 30, 0, 0, 0, 0, 0, false, 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,
diff --git a/engines/xeen/party.cpp b/engines/xeen/party.cpp
index 43c2eca..b19e39a 100644
--- a/engines/xeen/party.cpp
+++ b/engines/xeen/party.cpp
@@ -165,28 +165,194 @@ int PlayerStruct::getAge(bool ignoreTemp) const {
 }
 
 int PlayerStruct::getMaxHP() const {
-	warning("TODO: getMaxHp");
-	return 20;
+	int hp = BASE_HP_BY_CLASS[_class];
+	hp += statBonus(getStat(ENDURANCE, false));
+	hp += RACE_HP_BONUSES[_race];
+	if (_skills[BODYBUILDER])
+		++hp;
+	if (hp < 1)
+		hp = 1;
+
+	hp *= getCurrentLevel();
+	hp += itemScan(7);
+
+	if (hp < 0)
+		hp = 0;
+
+	return hp;
 }
 
 int PlayerStruct::getMaxSP() const {
-	warning("TODO: getMaxSP");
-	return 20;
+	int result = 0;
+	bool flag = false;
+	int amount;
+	Attribute attrib;
+	Skill skill;
+
+	if (_hasSpells)
+		return 0;
+
+	if (_class == CLASS_SORCERER || _class == CLASS_ARCHER) {
+		attrib = INTELLECT;
+		skill = PRESTIDIGITATION;
+	} else {
+		attrib = PERSONALITY;
+		skill = PRAYER_MASTER;
+	}
+	if (_class == CLASS_DRUID || _class == CLASS_RANGER)
+		skill = ASTROLOGER;
+
+	for (;;) {
+		// Get the base number of spell points
+		result = statBonus(getStat(attrib, false));
+		result += RACE_SP_BONUSES[_race][attrib - 1];
+
+		if (_skills[skill])
+			result += 2;
+		if (result < 1)
+			result = 1;
+
+		// Multiply it by the character's level
+		result *= getCurrentLevel();
+
+		// Classes other than sorcerer, clerics, and druids only get half the SP
+		if (_class != CLASS_SORCERER && _class != CLASS_CLERIC && _class != CLASS_DRUID)
+			result /= 2;
+
+		if (flag || (_class != CLASS_DRUID && _class != CLASS_RANGER))
+			break;
+
+		// Druids and rangers get bonuses averaged on both personality and intellect
+		attrib = INTELLECT;
+		flag = true;
+		amount = result;
+	}
+	if (flag)
+		result = (amount + result) / 2;
+
+	result += itemScan(8);
+	if (result < 0)
+		result = 0;
+
+	return result;
+}
+
+/**
+ * Get the effective value of a given stat for the character
+ */
+int PlayerStruct::getStat(Attribute attrib, bool applyMod) const {
+	AttributePair attr;
+	int mode = 0;
+
+	switch (attrib) {
+	case MIGHT:
+		attr = _might;
+		break;
+	case INTELLECT:
+		attr = _intellect;
+		mode = 1;
+		break;
+	case PERSONALITY:
+		attr = _personality;
+		mode = 1;
+		break;
+	case ENDURANCE:
+		attr = _endurance;
+		break;
+	case SPEED:
+		attr = _speed;
+		break;
+	case ACCURACY:
+		attr = _accuracy;
+		break;
+	case LUCK:
+		attr = _luck;
+		mode = 2;
+		break;
+	default:
+		return 0;
+	}
+
+	// All the attributes except luck are affected by the character's age
+	if (mode < 2) {
+		int age = getAge(false);
+		int ageIndex = 0;
+		while (AGE_RANGES[ageIndex] < age)
+			++ageIndex;
+
+		attr._permanent += AGE_RANGES_ADJUST[mode][ageIndex];
+	}
+
+	if (applyMod) {
+		attr._permanent += conditionMod(attrib);
+		attr._permanent += attr._temporary;
+	}
+
+	return (attr._permanent >= 1) ? attr._permanent : 0;
 }
 
-int PlayerStruct::getStat(int statNum, int v2) {
-	// TODO
-	return 10;
+int PlayerStruct::statBonus(int statValue) const {
+	for (int idx = 0; STAT_VALUES[idx] <= statValue; ++idx)
+		return STAT_BONUSES[idx];
+
+	return 0;
 }
 
-bool PlayerStruct::charSavingThrow() {
-	// TODO
-	return false;
+bool PlayerStruct::charSavingThrow(DamageType attackType) const {
+	int v, vMax;
+
+	if (attackType == DT_PHYSICAL) {
+		v = statBonus(getStat(LUCK, false)) + getCurrentLevel();
+		vMax = v + 20;
+	} else {
+		switch (attackType) {
+		case DT_MAGICAL:
+			v = _magicResistence._permanent + _magicResistence._temporary + itemScan(16);
+			break;
+		case DT_FIRE:
+			v = _fireResistence._permanent + _fireResistence._temporary + itemScan(11);
+			break;
+		case DT_ELECTRICAL:
+			v = _electricityResistence._permanent + _electricityResistence._temporary + itemScan(12);
+			break;
+		case DT_COLD:
+			v = _coldResistence._permanent + _coldResistence._temporary + itemScan(13);
+			break;
+		case DT_POISON:
+			v = _poisonResistence._permanent + _poisonResistence._temporary + itemScan(14);
+			break;
+		case DT_ENERGY:
+			v = _energyResistence._permanent + _energyResistence._temporary + itemScan(15);
+			break;
+		default:
+			v = 0;
+			break;
+		}
+
+		vMax = v + 40;
+	}
+
+	return Party::_vm->getRandomNumber(1, vMax) <= v;
 }
 
 bool PlayerStruct::noActions() {
-	// TODO
-	return false;
+	Condition condition = worstCondition();
+
+	switch (condition) {
+	case CURSED:
+	case POISONED:
+	case DISEASED:
+	case INSANE:
+	case IN_LOVE:
+	case DRUNK: {
+		Common::String msg = Common::String::format(IN_NO_CONDITION, _name.c_str());
+		ErrorScroll::show(Party::_vm, msg, 
+			Party::_vm->_mode == 17 ? WT_2 : WT_NONFREEZED_WAIT);
+		return true;
+	}
+	default:
+		return false;
+	}
 }
 
 void PlayerStruct::setAward(int awardId, bool value) {
@@ -210,13 +376,177 @@ bool PlayerStruct::hasAward(int awardId) const {
 }
 
 int PlayerStruct::getArmorClass(bool baseOnly) const {
-	// TODO
-	return 1;
+	Party &party = *Party::_vm->_party;
+
+	int result = statBonus(getStat(SPEED, false)) + itemScan(9);
+	if (!baseOnly)
+		result += (party._blessedActive ? 1 : 0) + _ACTemp;
+
+	return MAX(result, 0);
 }
 
+/**
+ * Returns the thievery skill level, adjusted by class and race
+ */
 int PlayerStruct::getThievery() const {
-	// TODO
-	return 1;
+	int result = getCurrentLevel() * 2;
+
+	if (_class == CLASS_NINJA)
+		result += 15;
+	else if (_class == CLASS_ROBBER)
+		result += 30;
+
+	switch (_race) {
+	case ELF:
+	case GNOME:
+		result += 10;
+		break;
+	case DWARF:
+		result += 5;
+		break;
+	case HALF_ORC:
+		result -= 10;
+		break;
+	default:
+		break;
+	}
+
+	result += itemScan(10);
+
+	// If the character doesn't have a thievery skill, then do'nt allow any result
+	if (!_skills[THIEVERY])
+		result = 0;
+
+	return MAX(result, 0);
+}
+
+int PlayerStruct::getCurrentLevel() const {
+	return MAX(_level._permanent + _level._temporary, 0);
+}
+
+int PlayerStruct::itemScan(int itemId) const {
+	int result = 0;
+
+	for (int accessIdx = 0; accessIdx < 3; ++accessIdx) {
+		switch (accessIdx) {
+		case 0:
+			for (int idx = 0; idx < INV_ITEMS_TOTAL; ++idx) {
+				const XeenItem &item = _weapons[idx];
+
+				if (item._equipped && !(item._bonusFlags & 0xC0) && itemId < 11
+						&& itemId != 3 && item._material >= 59 && item._material <= 130) {
+					int mIndex = item.getAttributeCategory();
+					if (mIndex > 2)
+						++mIndex;
+
+					if (mIndex == itemId)
+						result += ATTRIBUTE_BONUSES[item._material - 59];
+				}
+			}
+			break;
+
+		case 1:
+			for (int idx = 0; idx < INV_ITEMS_TOTAL; ++idx) {
+				const XeenItem &item = _armor[idx];
+
+				if (item._equipped && !(item._bonusFlags & 0xC0)) {
+					if (itemId < 11 && itemId != 3 && item._material >= 59 && item._material <= 130) {
+						int mIndex = item.getAttributeCategory();
+						if (mIndex > 2)
+							++mIndex;
+
+						if (mIndex == itemId)
+							result += ATTRIBUTE_BONUSES[item._material - 59];
+					}
+
+					if (itemId > 10 && item._material < 37) {
+						int mIndex = item.getElementalCategory() + 11;
+
+						if (mIndex == itemId) {
+							result += ELEMENTAL_RESISTENCES[item._material];
+						}
+					}
+
+					if (itemId == 9) {
+						result += ARMOR_STRENGTHS[item._name];
+
+						if (item._material >= 37 && item._material <= 58)
+							result += METAL_LAC[item._material - 37];
+					}
+				}
+			}
+			break;
+
+		case 2:
+			for (int idx = 0; idx < INV_ITEMS_TOTAL; ++idx) {
+				const XeenItem &item = _accessories[idx];
+
+				if (item._equipped && !(item._bonusFlags & 0xC0) && itemId < 11 && itemId != 3) {
+					if (item._material >= 59 && item._material <= 130) {
+						int mIndex = item.getAttributeCategory();
+						if (mIndex > 2)
+							++mIndex;
+
+						if (mIndex == itemId) {
+							result += ATTRIBUTE_BONUSES[item._material - 59];
+						}
+					}
+
+					if (itemId > 10 && item._material < 37) {
+						int mIndex = item.getElementalCategory() + 11;
+						
+						if (mIndex == itemId)
+							result += ELEMENTAL_RESISTENCES[item._material];
+					}
+				}
+			}
+			break;
+		}
+	};
+
+	return result;
+}
+
+/**
+ * Modifies a passed attribute value based on player's condition
+ */
+int PlayerStruct::conditionMod(Attribute attrib) const {
+	if (_conditions[DEAD] || _conditions[STONED] || _conditions[ERADICATED])
+		return 0;
+
+	int v[7];
+	Common::fill(&v[0], &v[7], 0);
+	if (_conditions[CURSED])
+		v[6] -= _conditions[CURSED];
+
+	if (_conditions[INSANE]) {
+		v[2] -= _conditions[INSANE];
+		v[1] -= _conditions[INSANE];
+		v[5] -= _conditions[INSANE];
+		v[0] -= _conditions[INSANE];
+		v[4] -= _conditions[INSANE];
+	}
+
+	if (_conditions[POISONED]) {
+		v[0] -= _conditions[POISONED];
+		v[4] -= _conditions[POISONED];
+		v[5] -= _conditions[POISONED];
+	}
+
+	if (_conditions[DISEASED]) {
+		v[3] -= _conditions[DISEASED];
+		v[2] -= _conditions[DISEASED];
+		v[1] -= _conditions[DISEASED];
+	}
+
+	for (int idx = 0; idx < 7; ++idx) {
+		v[idx] -= _conditions[HEART_BROKEN];
+		v[idx] -= _conditions[IN_LOVE];
+		v[idx] -= _conditions[WEAK];
+		v[idx] -= _conditions[DRUNK];
+	}
+
+	return v[attrib];
 }
 
 /*------------------------------------------------------------------------*/
@@ -432,7 +762,7 @@ void Party::changeTime(int numMinutes) {
 			if (!player._conditions[DEAD] && !player._conditions[STONED] &&
 					!player._conditions[ERADICATED]) {
 				for (int statNum = 0; statNum < TOTAL_STATS; ++statNum) {
-					int statVal = player.getStat(statNum, 0);
+					int statVal = player.getStat((Attribute)statNum, false);
 					if (statVal < 1)
 						player._conditions[DEAD] = 1;
 				}
@@ -448,16 +778,16 @@ void Party::changeTime(int numMinutes) {
 
 			// Handle poisoning
 			if (!player._conditions[POISONED]) {
-				if (_vm->getRandomNumber(9) != 1 || !player.charSavingThrow())
+				if (_vm->getRandomNumber(1, 10) != 1 || !player.charSavingThrow(DT_ELECTRICAL))
 					player._conditions[POISONED] *= 2;
 				else
 					// Poison wears off
 					player._conditions[POISONED] = 0;
 			}
 
-			// Handle poisoning
+			// Handle disease
 			if (!player._conditions[DISEASED]) {
-				if (_vm->getRandomNumber(9) != 1 || !player.charSavingThrow())
+				if (_vm->getRandomNumber(9) != 1 || !player.charSavingThrow(DT_COLD))
 					player._conditions[DISEASED] *= 2;
 				else
 					// Disease wears off
@@ -506,7 +836,7 @@ void Party::changeTime(int numMinutes) {
 		PlayerStruct &player = _activeParty[idx];
 
 		if (player._conditions[CONFUSED] && _vm->getRandomNumber(2) == 1) {
-			if (player.charSavingThrow()) {
+			if (player.charSavingThrow(DT_PHYSICAL)) {
 				player._conditions[CONFUSED] = 0;
 			} else {
 				player._conditions[CONFUSED]--;
diff --git a/engines/xeen/party.h b/engines/xeen/party.h
index 2677813..5d35b0f 100644
--- a/engines/xeen/party.h
+++ b/engines/xeen/party.h
@@ -49,6 +49,11 @@ enum CharacterClass {
 	CLASS_12 = 12, CLASS_15 = 15, CLASS_16 = 16
 };
 
+enum Attribute{
+	MIGHT = 0, INTELLECT = 1, PERSONALITY = 2, ENDURANCE = 3, SPEED = 4,
+	ACCURACY = 5, LUCK = 6
+};
+
 enum Skill { THIEVERY = 0, ARMS_MASTER = 1, ASTROLOGER = 2, BODYBUILDER = 3,
 	CARTOGRAPHER = 4, CRUSADER = 5, DIRECTION_SENSE = 6, LINGUIST = 7, 
 	MERCHANT = 8, MOUNTAINEER = 9, NAVIGATOR = 10, PATHFINDER = 11,
@@ -68,6 +73,7 @@ enum Condition { CURSED = 0, HEART_BROKEN = 1, WEAK = 2, POISONED = 3,
 #define XEEN_TOTAL_CHARACTERS 24
 #define MAX_ACTIVE_PARTY 6
 #define TOTAL_STATS 7
+#define INV_ITEMS_TOTAL 9
 
 class XeenEngine;
 
@@ -81,6 +87,8 @@ public:
 };
 
 class PlayerStruct {
+private:
+	int conditionMod(Attribute attrib) const;
 public:
 	Common::String _name;
 	Sex _sex;
@@ -106,10 +114,10 @@ public:
 	bool _hasSpells;
 	int _currentSpell;
 	int _quickOption;
-	XeenItem _weapons[9];
-	XeenItem _armor[9];
-	XeenItem _accessories[9];
-	XeenItem _misc[9];
+	XeenItem _weapons[INV_ITEMS_TOTAL];
+	XeenItem _armor[INV_ITEMS_TOTAL];
+	XeenItem _accessories[INV_ITEMS_TOTAL];
+	XeenItem _misc[INV_ITEMS_TOTAL];
 	int _lloydSide;
 	AttributePair _fireResistence;
 	AttributePair _coldResistence;
@@ -138,9 +146,11 @@ public:
 
 	int getMaxSP() const;
 
-	int getStat(int statNum, int v2);
+	int getStat(Attribute attrib, bool applyMod) const;
 
-	bool charSavingThrow();
+	int statBonus(int statValue) const;
+
+	bool charSavingThrow(DamageType attackType) const;
 
 	bool noActions();
 
@@ -151,6 +161,10 @@ public:
 	int getArmorClass(bool baseOnly) const;
 
 	int getThievery() const;
+
+	int getCurrentLevel() const;
+
+	int itemScan(int itemId) const;
 };
 
 class Roster: public Common::Array<PlayerStruct> {
diff --git a/engines/xeen/resources.cpp b/engines/xeen/resources.cpp
index 837ff15..993bf2f 100644
--- a/engines/xeen/resources.cpp
+++ b/engines/xeen/resources.cpp
@@ -73,6 +73,8 @@ const char *const WHO_WILL = "\X03""c\X0B""000\x09""000%s\x0A\x0A"
 
 const char *const WHATS_THE_PASSWORD = "What's the Password?";
 
+const char *const IN_NO_CONDITION = "\x0B""007%s is not in any condition to perform actions!";
+
 const char *const TERRAIN_TYPES[6] = {
 	"town", "cave", "towr", "cstl", "dung", "scfi"
 };
@@ -271,6 +273,12 @@ const char *const DIRECTION_TEXT[4] = { "NORTH", "EAST", "SOUTH", "WEST" };
 
 const char *const RACE_NAMES[5] = { "Human", "Elf", "Dwarf", "Gnome", "H-Orc" };
 
+const int RACE_HP_BONUSES[5] = { 0, -2, 1, -1, 2 };
+
+const int RACE_SP_BONUSES[5][2] = {
+	{ 0, 0 }, { 2, 0 }, { -1, -1 }, { 1, 1 }, { -2, -2 }
+};
+
 const char *const ALIGNMENT_NAMES[3] = { "Good", "Neutral", "Evil" };
 
 const char *const SEX_NAMES[2] = { "Male", "Female" };
@@ -471,7 +479,7 @@ const int MONSTER_EFFECT_FLAGS[15][8] = {
 	{ 0x108, 0x108, 0x108, 0x108, 0x108, 0x108, 0x108, 0x108 }
 };
 
-const int SPELLS_ALLOWED[3][40] = {
+const uint SPELLS_ALLOWED[3][40] = {
 	{
 		0, 1, 2, 3, 5, 6, 7, 8, 9, 10,
 		12, 14, 16, 23, 26, 27, 28, 30, 31, 32,
@@ -490,4 +498,56 @@ const int SPELLS_ALLOWED[3][40] = {
 	}
 };
 
+const int BASE_HP_BY_CLASS[10] = { 10, 8, 7, 5, 4, 8, 7, 12, 6, 9 };
+
+const int AGE_RANGES[10] = { 1, 6, 11, 18, 36, 51, 76, 101, 201, 0xffff };
+
+const int AGE_RANGES_ADJUST[2][10] = {
+	{ -250, -50, -20, -10, 0, -2, -5, -10, -20, -50 },
+	{ -250, -50, -20, -10, 0, 2, 5, 10, 20, 50 }
+};
+
+const int STAT_VALUES[24] = {
+	11, 13, 15, 17, 19, 21, 25, 30, 35, 40, 50, 75,
+	100, 125, 150, 175, 200, 225, 250, 65535
+};
+
+const int STAT_BONUSES[24] = {
+	251, 252, 253, 254, 255, 0, 1, 2, 3, 4, 5, 6,
+	7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 20
+};
+
+const int ELEMENTAL_CATEGORIES[6] = { 8, 15, 20, 25, 33, 36 };
+
+const int ATTRIBUTE_CATEGORIES[10] = {
+	9, 17, 25, 33, 39, 45, 50, 56, 61, 72 };
+
+const int ATTRIBUTE_BONUSES[72] = {
+	2, 3, 5, 8, 12, 17, 23, 30, 38, 47,	// Might bonus
+	2, 3, 5, 8, 12, 17, 23, 30,			// INT bonus
+	2, 3, 5, 8, 12, 17, 23, 30,			// PER bonus
+	2, 3, 5, 8, 12, 17, 23, 30,			// SPD bonus
+	3, 5, 10, 15, 20, 30,				// ACC bonus
+	5, 10, 15, 20, 25, 30,				// LUC bonus
+	4, 6, 10, 20, 50,					// HP bonus
+	4, 8, 12, 16, 20, 25,				// SP bonus
+	2, 4, 6, 10, 16,					// AC bonus
+	4, 6, 8, 10, 12, 14, 16, 18, 20, 25	// Thievery bonus
+};
+
+const int ELEMENTAL_RESISTENCES[37] = {
+	0, 5, 7, 9, 12, 15, 20, 25, 30, 5, 7, 9, 12, 15, 20, 25,
+	5, 10, 15, 20, 25, 10, 15, 20, 25, 40, 5, 7, 9, 11, 13, 15, 20, 25,
+	5, 10, 20
+};
+
+const int ELEMENTAL_DAMAGE[37] = {
+	0, 2, 3, 4, 5, 10, 15, 20, 30, 2, 3, 4, 5, 10, 15, 20, 2, 4, 5, 10, 20,
+	2, 4, 8, 16, 32, 2, 3, 4, 5, 10, 15, 20, 30, 5, 10, 25
+};
+
+const int METAL_LAC[9] = { -3, 0, -2, -1, 1, 2, 4, 6, 8 };
+
+const int ARMOR_STRENGTHS[14] = { 0, 2, 4, 5, 6, 7, 8, 10, 4, 2, 1, 1, 1, 1 };
+
 } // End of namespace Xeen
diff --git a/engines/xeen/resources.h b/engines/xeen/resources.h
index 36ac6b2..b1c9720 100644
--- a/engines/xeen/resources.h
+++ b/engines/xeen/resources.h
@@ -38,6 +38,8 @@ extern const char *const WHO_WILL;
 
 extern const char *const WHATS_THE_PASSWORD;
 
+extern const char *const IN_NO_CONDITION;
+
 extern const char *const TERRAIN_TYPES[6];
 
 extern const char *const SURFACE_TYPE_NAMES[15];
@@ -56,6 +58,10 @@ extern const char *const DIRECTION_TEXT[4];
 
 extern const char *const RACE_NAMES[5];
 
+extern const int RACE_HP_BONUSES[5];
+
+extern const int RACE_SP_BONUSES[5][2];
+
 extern const char *const CLASS_NAMES[11];
 
 extern const char *const ALIGNMENT_NAMES[3];
@@ -110,7 +116,31 @@ extern const int COMBAT_FLOAT_Y[8];
 
 extern const int MONSTER_EFFECT_FLAGS[15][8];
 
-extern const int SPELLS_ALLOWED[3][40];
+extern const uint SPELLS_ALLOWED[3][40];
+
+extern const int BASE_HP_BY_CLASS[10];
+
+extern const int AGE_RANGES[10];
+
+extern const int AGE_RANGES_ADJUST[2][10];
+
+extern const int STAT_VALUES[24];
+
+extern const int STAT_BONUSES[24];
+
+extern const int ELEMENTAL_CATEGORIES[6];
+
+extern const int ATTRIBUTE_CATEGORIES[10];
+
+extern const int ATTRIBUTE_BONUSES[72];
+
+extern const int ELEMENTAL_RESISTENCES[37];
+
+extern const int ELEMENTAL_DAMAGE[37];
+
+extern const int METAL_LAC[9];
+
+extern const int ARMOR_STRENGTHS[14];
 
 } // End of namespace Xeen
 
diff --git a/engines/xeen/scripts.cpp b/engines/xeen/scripts.cpp
index ffe5441..6f14be2 100644
--- a/engines/xeen/scripts.cpp
+++ b/engines/xeen/scripts.cpp
@@ -86,7 +86,7 @@ Scripts::Scripts(XeenEngine *vm) : _vm(vm) {
 
 void Scripts::checkEvents() {
 	Combat &combat = *_vm->_combat;
-	Interface &intf = *_vm->_interface;
+//	Interface &intf = *_vm->_interface;
 	Map &map = *_vm->_map;
 	Party &party = *_vm->_party;
 
@@ -415,7 +415,7 @@ void Scripts::cmdGiveExtended(Common::Array<byte> &params) {
 		break;
 	}
 
-	if ((_charIndex != 0 & _charIndex != 8) || params[0] == 44) {
+	if ((_charIndex != 0 && _charIndex != 8) || params[0] == 44) {
 		result = ifProc(params[0], mask, _event->_opcode - OP_If1, _charIndex - 1);
 	} else {
 		result = false;
@@ -566,7 +566,7 @@ void Scripts::cmdMakeNothingHere(Common::Array<byte> &params) {
 
 	// Scan through the event list and mark the opcodes for all the lines of any scripts
 	// on the party's current cell as having no operation, effectively disabling them
-	for (int idx = 0; idx < map._events.size(); ++idx) {
+	for (uint idx = 0; idx < map._events.size(); ++idx) {
 		MazeEvent &evt = map._events[idx];
 		if (evt._position == party._mazePosition)
 			evt._opcode = OP_None;
@@ -804,22 +804,22 @@ bool Scripts::ifProc(int action, uint32 mask, int mode, int charIndex) {
 		if (mask < 82) {
 			for (int idx = 0; idx < 9; ++idx) {
 				if (mask == 35) {
-					if (ps._weapons[idx]._name == mask) {
+					if ((int)ps._weapons[idx]._name == mask) {
 						v = mask;
 						break;
 					}
 				} else if (mask < 49) {
-					if (ps._armor[idx]._name == (mask - 35)) {
+					if ((int)ps._armor[idx]._name == (mask - 35)) {
 						v = mask;
 						break;
 					}
 				} else if (mask < 60) {
-					if (ps._accessories[idx]._name == (mask - 49)) {
+					if ((int)ps._accessories[idx]._name == (mask - 49)) {
 						v = mask;
 						break;
 					}
 				} else {
-					if (ps._misc[idx]._name == (mask - 60)) {
+					if ((int)ps._misc[idx]._name == (mask - 60)) {
 						v = mask;
 						break;
 					}
@@ -1020,7 +1020,7 @@ bool Scripts::ifProc(int action, uint32 mask, int mode, int charIndex) {
 	case 91:
 	case 92:
 		// Get a player stat
-		v = ps.getStat(action - 86, 0);
+		v = ps.getStat((Attribute)(action - 86), 0);
 		break;
 	case 93:
 		// Current day of the week (10 days per week)


Commit: 1f8a5ea24a8c031979289953fdb674029338d9bc
    https://github.com/scummvm/scummvm/commit/1f8a5ea24a8c031979289953fdb674029338d9bc
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-01-24T09:29:17-05:00

Commit Message:
XEEN: Changed PlayerStruct to Character

Changed paths:
    engines/xeen/interface.cpp
    engines/xeen/party.cpp
    engines/xeen/party.h
    engines/xeen/scripts.cpp



diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp
index a23cee6..44e2326 100644
--- a/engines/xeen/interface.cpp
+++ b/engines/xeen/interface.cpp
@@ -106,7 +106,7 @@ start:
 
 		// Build up a list of characters on the same Xeen side being loaded
 		for (int i = 0; i < XEEN_TOTAL_CHARACTERS; ++i) {
-			PlayerStruct &player = _vm->_roster[i];
+			Character &player = _vm->_roster[i];
 			if (player._name.empty() || player._xeenSide != (map._loadDarkSide ? 1 : 0))
 				continue;
 
@@ -300,7 +300,7 @@ void Interface::setupFaces(int charIndex, Common::Array<int> xeenSideChars, bool
 
 		Common::Rect &b = _buttons[7 + posIndex]._bounds;
 		b.moveTo((posIndex & 1) ? 117 : 16, b.top);
-		PlayerStruct &ps = _vm->_roster[xeenSideChars[charIndex + posIndex]];
+		Character &ps = _vm->_roster[xeenSideChars[charIndex + posIndex]];
 		playerNames[posIndex] = isInParty ? IN_PARTY : ps._name;
 		playerRaces[posIndex] = RACE_NAMES[ps._race];
 		playerSex[posIndex] = SEX_NAMES[ps._sex];
@@ -336,7 +336,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];
+		Character &ps = _vm->_party->_activeParty[charIndex];
 		Condition charCondition = ps.worstCondition();
 		int charFrame = FACE_CONDITION_FRAMES[charCondition];
 		
@@ -352,7 +352,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];
+			Character &ps = _vm->_party->_activeParty[charIndex];
 
 			// Draw the Hp bar
 			int maxHp = ps.getMaxHP();
diff --git a/engines/xeen/party.cpp b/engines/xeen/party.cpp
index b19e39a..791a19f 100644
--- a/engines/xeen/party.cpp
+++ b/engines/xeen/party.cpp
@@ -42,7 +42,7 @@ void AttributePair::synchronize(Common::Serializer &s) {
 
 /*------------------------------------------------------------------------*/
 
-PlayerStruct::PlayerStruct() {
+Character::Character() {
 	_sex = MALE;
 	_race = HUMAN;
 	_xeenSide = 0;
@@ -69,7 +69,7 @@ PlayerStruct::PlayerStruct() {
 	_currentCombatSpell = 0;
 }
 
-void PlayerStruct::synchronize(Common::Serializer &s) {
+void Character::synchronize(Common::Serializer &s) {
 	char name[16];
 	Common::fill(&name[0], &name[16], '\0');
 	strncpy(name, _name.c_str(), 16);
@@ -149,7 +149,7 @@ void PlayerStruct::synchronize(Common::Serializer &s) {
 	s.syncAsByte(_currentCombatSpell);
 }
 
-Condition PlayerStruct::worstCondition() const {
+Condition Character::worstCondition() const {
 	for (int cond = ERADICATED; cond >= CURSED; --cond) {
 		if (_conditions[cond])
 			return (Condition)cond;
@@ -158,13 +158,13 @@ Condition PlayerStruct::worstCondition() const {
 	return NO_CONDITION;
 }
 
-int PlayerStruct::getAge(bool ignoreTemp) const {
+int Character::getAge(bool ignoreTemp) const {
 	int year = MIN(Party::_vm->_party->_year - _ybDay, 254);
 
 	return ignoreTemp ? year : year + _tempAge;
 }
 
-int PlayerStruct::getMaxHP() const {
+int Character::getMaxHP() const {
 	int hp = BASE_HP_BY_CLASS[_class];
 	hp += statBonus(getStat(ENDURANCE, false));
 	hp += RACE_HP_BONUSES[_race];
@@ -182,7 +182,7 @@ int PlayerStruct::getMaxHP() const {
 	return hp;
 }
 
-int PlayerStruct::getMaxSP() const {
+int Character::getMaxSP() const {
 	int result = 0;
 	bool flag = false;
 	int amount;
@@ -240,7 +240,7 @@ int PlayerStruct::getMaxSP() const {
 /**
  * Get the effective value of a given stat for the character
  */
-int PlayerStruct::getStat(Attribute attrib, bool applyMod) const {
+int Character::getStat(Attribute attrib, bool applyMod) const {
 	AttributePair attr;
 	int mode = 0;
 
@@ -291,14 +291,14 @@ int PlayerStruct::getStat(Attribute attrib, bool applyMod) const {
 	return (attr._permanent >= 1) ? attr._permanent : 0;
 }
 
-int PlayerStruct::statBonus(int statValue) const {
+int Character::statBonus(int statValue) const {
 	for (int idx = 0; STAT_VALUES[idx] <= statValue; ++idx)
 		return STAT_BONUSES[idx];
 
 	return 0;
 }
 
-bool PlayerStruct::charSavingThrow(DamageType attackType) const {
+bool Character::charSavingThrow(DamageType attackType) const {
 	int v, vMax;
 
 	if (attackType == DT_PHYSICAL) {
@@ -335,7 +335,7 @@ bool PlayerStruct::charSavingThrow(DamageType attackType) const {
 	return Party::_vm->getRandomNumber(1, vMax) <= v;
 }
 
-bool PlayerStruct::noActions() {
+bool Character::noActions() {
 	Condition condition = worstCondition();
 
 	switch (condition) {
@@ -355,7 +355,7 @@ bool PlayerStruct::noActions() {
 	}
 }
 
-void PlayerStruct::setAward(int awardId, bool value) {
+void Character::setAward(int awardId, bool value) {
 	int v = awardId;
 	if (awardId == 73)
 		v = 126;
@@ -365,7 +365,7 @@ void PlayerStruct::setAward(int awardId, bool value) {
 	_awards[v] = value;
 }
 
-bool PlayerStruct::hasAward(int awardId) const {
+bool Character::hasAward(int awardId) const {
 	int v = awardId;
 	if (awardId == 73)
 		v = 126;
@@ -375,7 +375,7 @@ bool PlayerStruct::hasAward(int awardId) const {
 	return _awards[v];
 }
 
-int PlayerStruct::getArmorClass(bool baseOnly) const {
+int Character::getArmorClass(bool baseOnly) const {
 	Party &party = *Party::_vm->_party;
 
 	int result = statBonus(getStat(SPEED, false)) + itemScan(9);
@@ -388,7 +388,7 @@ int PlayerStruct::getArmorClass(bool baseOnly) const {
 /**
  * Returns the thievery skill level, adjusted by class and race
  */
-int PlayerStruct::getThievery() const {
+int Character::getThievery() const {
 	int result = getCurrentLevel() * 2;
 
 	if (_class == CLASS_NINJA)
@@ -420,11 +420,11 @@ int PlayerStruct::getThievery() const {
 	return MAX(result, 0);
 }
 
-int PlayerStruct::getCurrentLevel() const {
+int Character::getCurrentLevel() const {
 	return MAX(_level._permanent + _level._temporary, 0);
 }
 
-int PlayerStruct::itemScan(int itemId) const {
+int Character::itemScan(int itemId) const {
 	int result = 0;
 
 	for (int accessIdx = 0; accessIdx < 3; ++accessIdx) {
@@ -510,7 +510,7 @@ int PlayerStruct::itemScan(int itemId) const {
 /**
  * Modifies a passed attribute value based on player's condition
  */
-int PlayerStruct::conditionMod(Attribute attrib) const {
+int Character::conditionMod(Attribute attrib) const {
 	if (_conditions[DEAD] || _conditions[STONED] || _conditions[ERADICATED])
 		return 0;
 
@@ -757,7 +757,7 @@ void Party::changeTime(int numMinutes) {
 
 	if (((_minutes + numMinutes) / 480) != (_minutes / 480)) {
 		for (int idx = 0; idx < _partyCount; ++idx) {
-			PlayerStruct &player = _activeParty[idx];
+			Character &player = _activeParty[idx];
 
 			if (!player._conditions[DEAD] && !player._conditions[STONED] &&
 					!player._conditions[ERADICATED]) {
@@ -833,7 +833,7 @@ void Party::changeTime(int numMinutes) {
 	addTime(numMinutes);
 
 	for (int idx = 0; idx < _partyCount; ++idx) {
-		PlayerStruct &player = _activeParty[idx];
+		Character &player = _activeParty[idx];
 
 		if (player._conditions[CONFUSED] && _vm->getRandomNumber(2) == 1) {
 			if (player.charSavingThrow(DT_PHYSICAL)) {
@@ -899,7 +899,7 @@ void Party::addTime(int numMinutes) {
 
 void Party::resetTemps() {
 	for (int idx = 0; idx < _partyCount; ++idx) {
-		PlayerStruct &player = _activeParty[idx];
+		Character &player = _activeParty[idx];
 
 		player._magicResistence._temporary = 0;
 		player._energyResistence._temporary = 0;
diff --git a/engines/xeen/party.h b/engines/xeen/party.h
index 5d35b0f..f561909 100644
--- a/engines/xeen/party.h
+++ b/engines/xeen/party.h
@@ -86,7 +86,7 @@ public:
 	void synchronize(Common::Serializer &s);
 };
 
-class PlayerStruct {
+class Character {
 private:
 	int conditionMod(Attribute attrib) const;
 public:
@@ -135,7 +135,7 @@ public:
 	int _currentAdventuringSpell;
 	int _currentCombatSpell;
 public:
-	PlayerStruct();
+	Character();
 	void synchronize(Common::Serializer &s);
 
 	Condition worstCondition() const;
@@ -167,7 +167,7 @@ public:
 	int itemScan(int itemId) const;
 };
 
-class Roster: public Common::Array<PlayerStruct> {
+class Roster: public Common::Array<Character> {
 public:
 	Roster() {}
 
@@ -175,7 +175,7 @@ public:
 };
 
 class Party {
-	friend class PlayerStruct;
+	friend class Character;
 private:
 	static XeenEngine *_vm;
 public:
@@ -235,7 +235,7 @@ public:
 	bool _characterFlags[30][24];
 public:
 	// Other party related runtime data
-	Common::Array<PlayerStruct> _activeParty;
+	Common::Array<Character> _activeParty;
 	int _combatPartyCount;
 	bool _partyDead;
 	bool _newDay;
diff --git a/engines/xeen/scripts.cpp b/engines/xeen/scripts.cpp
index 6f14be2..10ba972 100644
--- a/engines/xeen/scripts.cpp
+++ b/engines/xeen/scripts.cpp
@@ -667,7 +667,7 @@ void Scripts::doEndGame2() {
 	int v2 = 0;
 
 	for (int idx = 0; idx < party._partyCount; ++idx) {
-		PlayerStruct &player = party._activeParty[idx];
+		Character &player = party._activeParty[idx];
 		if (player.hasAward(77)) {
 			v2 = 2;
 			break;
@@ -696,7 +696,7 @@ void Scripts::doEnding(const Common::String &endStr, int v2) {
  */
 bool Scripts::ifProc(int action, uint32 mask, int mode, int charIndex) {
 	Party &party = *_vm->_party;
-	PlayerStruct &ps = party._activeParty[charIndex];
+	Character &ps = party._activeParty[charIndex];
 	uint v = 0;
 
 	switch (action) {


Commit: 2b5167cafcebe78e797318690080e2ed3706da28
    https://github.com/scummvm/scummvm/commit/2b5167cafcebe78e797318690080e2ed3706da28
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-01-24T09:35:56-05:00

Commit Message:
XEEN: Fix side loading bug in Map::load

Changed paths:
    engines/xeen/map.cpp
    engines/xeen/map.h



diff --git a/engines/xeen/map.cpp b/engines/xeen/map.cpp
index 750e634..4adf356 100644
--- a/engines/xeen/map.cpp
+++ b/engines/xeen/map.cpp
@@ -857,8 +857,8 @@ void AnimationInfo::load(const Common::String &name) {
 /*------------------------------------------------------------------------*/
 
 Map::Map(XeenEngine *vm) : _vm(vm), _mobData(vm) {
-	_townPortalSide = false;
 	_loadDarkSide = false;
+	_sideTownPortal = 0;
 	_sideObjects = 0;
 	_sideMonsters = 0;
 	_sidePictures = 0;
@@ -897,13 +897,13 @@ void Map::load(int mapId) {
 	_sideMonsters = 1;
 	_sidePictures = 1;
 	if (mapId >= 113 && mapId <= 127) {
-		_townPortalSide = false;
+		_sideTownPortal = 0;
 	} else {
-		_townPortalSide = _loadDarkSide;
+		_sideTownPortal = _loadDarkSide ? 1 : 0;
 	}
 
 	if (_vm->getGameID() == GType_WorldOfXeen) {
-		if (_loadDarkSide) {
+		if (!_loadDarkSide) {
 			_animationInfo.load("clouds.dat");
 			_monsterData.load("xeen.mon");
 			_wallPicSprites.load("xeenpic.dat");
@@ -1050,7 +1050,7 @@ void Map::load(int mapId) {
 			filename = "085.obj";
 			_mobData._objectSprites[0]._spriteId = 85;
 		} else {
-			filename = Common::String::format("xeen|%03d.%cbj", 
+			filename = Common::String::format("%03d.%cbj", 
 				_mobData._objectSprites[i]._spriteId,
 				_mobData._objectSprites[i]._spriteId >= 100 ? '0' : 'o');
 		}
diff --git a/engines/xeen/map.h b/engines/xeen/map.h
index 273a4b4..499b451 100644
--- a/engines/xeen/map.h
+++ b/engines/xeen/map.h
@@ -345,7 +345,7 @@ private:
 	MazeData _mazeData[9];
 	Common::String _mazeName;
 	SpriteResource _wallPicSprites;
-	bool _townPortalSide;
+	int _sideTownPortal;
 	int _sidePictures;
 	int _sideObjects;
 	int _sideMonsters;


Commit: de1341ddb54befd64776370f988774970e5a9494
    https://github.com/scummvm/scummvm/commit/de1341ddb54befd64776370f988774970e5a9494
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-01-24T09:39:33-05:00

Commit Message:
XEEN: Add special case block to Map::load

Changed paths:
    engines/xeen/map.cpp



diff --git a/engines/xeen/map.cpp b/engines/xeen/map.cpp
index 4adf356..043f8c0 100644
--- a/engines/xeen/map.cpp
+++ b/engines/xeen/map.cpp
@@ -1044,7 +1044,9 @@ void Map::load(int mapId) {
 	for (uint i = 0; i < _mobData._objectSprites.size(); ++i) {
 		if (_vm->_party->_cloudsEnd && _mobData._objectSprites[i]._spriteId == 85 &&
 				mapId == 27 && isDarkCc) {
-			// TODO: Flags set that don't seem to be used
+			_mobData._objects[29]._spriteId = 0;
+			_mobData._objects[29]._id = 8;
+			_mobData._objectSprites[i]._sprites.clear();
 		} else if (mapId == 12 && _vm->_party->_gameFlags[43] &&
 			_mobData._objectSprites[i]._spriteId == 118 && !isDarkCc) {
 			filename = "085.obj";


Commit: f69fd28fe0dd4aceeb21f186101a2236f7d89740
    https://github.com/scummvm/scummvm/commit/f69fd28fe0dd4aceeb21f186101a2236f7d89740
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-01-24T10:13:32-05:00

Commit Message:
XEEN: Fixes for hit points calculations

Changed paths:
    engines/xeen/party.cpp
    engines/xeen/party.h
    engines/xeen/resources.cpp



diff --git a/engines/xeen/party.cpp b/engines/xeen/party.cpp
index 791a19f..2822e41 100644
--- a/engines/xeen/party.cpp
+++ b/engines/xeen/party.cpp
@@ -166,7 +166,7 @@ int Character::getAge(bool ignoreTemp) const {
 
 int Character::getMaxHP() const {
 	int hp = BASE_HP_BY_CLASS[_class];
-	hp += statBonus(getStat(ENDURANCE, false));
+	hp += statBonus(getStat(ENDURANCE));
 	hp += RACE_HP_BONUSES[_race];
 	if (_skills[BODYBUILDER])
 		++hp;
@@ -176,10 +176,7 @@ int Character::getMaxHP() const {
 	hp *= getCurrentLevel();
 	hp += itemScan(7);
 
-	if (hp < 0)
-		hp = 0;
-
-	return hp;
+	return MAX(hp, 0);
 }
 
 int Character::getMaxSP() const {
@@ -204,7 +201,7 @@ int Character::getMaxSP() const {
 
 	for (;;) {
 		// Get the base number of spell points
-		result = statBonus(getStat(attrib, false));
+		result = statBonus(getStat(attrib));
 		result += RACE_SP_BONUSES[_race][attrib - 1];
 
 		if (_skills[skill])
@@ -240,7 +237,7 @@ int Character::getMaxSP() const {
 /**
  * Get the effective value of a given stat for the character
  */
-int Character::getStat(Attribute attrib, bool applyMod) const {
+int Character::getStat(Attribute attrib, bool baseOnly) const {
 	AttributePair attr;
 	int mode = 0;
 
@@ -277,32 +274,36 @@ int Character::getStat(Attribute attrib, bool applyMod) const {
 	if (mode < 2) {
 		int age = getAge(false);
 		int ageIndex = 0;
-		while (AGE_RANGES[ageIndex] < age)
+		while (AGE_RANGES[ageIndex] <= age)
 			++ageIndex;
 
 		attr._permanent += AGE_RANGES_ADJUST[mode][ageIndex];
 	}
 
-	if (applyMod) {
+
+	attr._permanent += itemScan((int)attrib);
+
+	if (!baseOnly) {
 		attr._permanent += conditionMod(attrib);
 		attr._permanent += attr._temporary;
 	}
 
-	return (attr._permanent >= 1) ? attr._permanent : 0;
+	return MAX(attr._permanent, 0);
 }
 
 int Character::statBonus(int statValue) const {
-	for (int idx = 0; STAT_VALUES[idx] <= statValue; ++idx)
-		return STAT_BONUSES[idx];
+	int idx;
+	for (idx = 0; STAT_VALUES[idx] <= statValue; ++idx)
+		;
 
-	return 0;
+	return STAT_BONUSES[idx];
 }
 
 bool Character::charSavingThrow(DamageType attackType) const {
 	int v, vMax;
 
 	if (attackType == DT_PHYSICAL) {
-		v = statBonus(getStat(LUCK, false)) + getCurrentLevel();
+		v = statBonus(getStat(LUCK)) + getCurrentLevel();
 		vMax = v + 20;
 	} else {
 		switch (attackType) {
@@ -378,7 +379,7 @@ bool Character::hasAward(int awardId) const {
 int Character::getArmorClass(bool baseOnly) const {
 	Party &party = *Party::_vm->_party;
 
-	int result = statBonus(getStat(SPEED, false)) + itemScan(9);
+	int result = statBonus(getStat(SPEED)) + itemScan(9);
 	if (!baseOnly)
 		result += (party._blessedActive ? 1 : 0) + _ACTemp;
 
@@ -762,7 +763,7 @@ void Party::changeTime(int numMinutes) {
 			if (!player._conditions[DEAD] && !player._conditions[STONED] &&
 					!player._conditions[ERADICATED]) {
 				for (int statNum = 0; statNum < TOTAL_STATS; ++statNum) {
-					int statVal = player.getStat((Attribute)statNum, false);
+					int statVal = player.getStat((Attribute)statNum);
 					if (statVal < 1)
 						player._conditions[DEAD] = 1;
 				}
diff --git a/engines/xeen/party.h b/engines/xeen/party.h
index f561909..dc87e88 100644
--- a/engines/xeen/party.h
+++ b/engines/xeen/party.h
@@ -146,7 +146,7 @@ public:
 
 	int getMaxSP() const;
 
-	int getStat(Attribute attrib, bool applyMod) const;
+	int getStat(Attribute attrib, bool baseOnly = false) const;
 
 	int statBonus(int statValue) const;
 
diff --git a/engines/xeen/resources.cpp b/engines/xeen/resources.cpp
index 993bf2f..556544d 100644
--- a/engines/xeen/resources.cpp
+++ b/engines/xeen/resources.cpp
@@ -508,12 +508,12 @@ const int AGE_RANGES_ADJUST[2][10] = {
 };
 
 const int STAT_VALUES[24] = {
-	11, 13, 15, 17, 19, 21, 25, 30, 35, 40, 50, 75,
-	100, 125, 150, 175, 200, 225, 250, 65535
+	3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 25, 30, 35, 40, 
+	50, 75, 100, 125, 150, 175, 200, 225, 250, 65535
 };
 
 const int STAT_BONUSES[24] = {
-	251, 252, 253, 254, 255, 0, 1, 2, 3, 4, 5, 6,
+	-5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6,
 	7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 20
 };
 


Commit: 82010fb5ef27ea622103d91c0b6bcad67366ee32
    https://github.com/scummvm/scummvm/commit/82010fb5ef27ea622103d91c0b6bcad67366ee32
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-01-24T10:24:45-05:00

Commit Message:
XEEN: Formatting fixes

Changed paths:
    engines/xeen/interface_map.cpp



diff --git a/engines/xeen/interface_map.cpp b/engines/xeen/interface_map.cpp
index 2d2fddf..95263c9 100644
--- a/engines/xeen/interface_map.cpp
+++ b/engines/xeen/interface_map.cpp
@@ -438,8 +438,7 @@ void InterfaceMap::draw3d(bool updateFlag) {
 
 		if (_isAnimReset) {
 			mazeObject._frame = animEntry._frame1._frames[directionIndex];
-		}
-		else {
+		} else {
 			++mazeObject._frame;
 			if ((int)idx == objNum && scripts._animCounter > 0 && (
 				objObject._spriteId == (_vm->_files->_isDarkCc ? 15 : 16) ||
@@ -457,8 +456,7 @@ void InterfaceMap::draw3d(bool updateFlag) {
 
 	if (map._isOutdoors) {
 		error("TODO: draw3d outdoors handling");
-	}
-	else {
+	} else {
 		// Default all the parts of draw struct not to be drawn by default
 		for (int idx = 3; idx < _indoorList.size(); ++idx)
 			_indoorList[idx]._frame = -1;
@@ -478,8 +476,7 @@ void InterfaceMap::draw3d(bool updateFlag) {
 					_indoorList[162 + idx]._frame = 0;
 				}
 			}
-		}
-		else if (_charsShooting) {
+		} else if (_charsShooting) {
 			for (int idx = 0; idx < 96; ++idx) {
 				if (_indoorList[162 + idx]._sprites != nullptr) {
 					_indoorList[162 + idx]._frame = 0;
@@ -522,8 +519,7 @@ void InterfaceMap::draw3d(bool updateFlag) {
 					if (ds1._scale == 0x8000) {
 						ds1._x /= 3;
 						ds1._y = 60;
-					}
-					else {
+					} else {
 						ds1._y = 73;
 					}
 
@@ -561,8 +557,7 @@ void InterfaceMap::draw3d(bool updateFlag) {
 			_indoorList[156]._sprites = nullptr;
 			_indoorList[157]._sprites = nullptr;
 			monsterIndex = 1;
-		}
-		else if (combat._attackMonsters[1] != -1 && map._mobData._monsters[combat._attackMonsters[1]]._frame >= 0) {
+		} else if (combat._attackMonsters[1] != -1 && map._mobData._monsters[combat._attackMonsters[1]]._frame >= 0) {
 			_indoorList[159] = _indoorList[150];
 			_indoorList[160] = _indoorList[151];
 			_indoorList[161] = _indoorList[152];
@@ -570,8 +565,7 @@ void InterfaceMap::draw3d(bool updateFlag) {
 			_indoorList[151]._sprites = nullptr;
 			_indoorList[150]._sprites = nullptr;
 			monsterIndex = 2;
-		}
-		else if (combat._attackMonsters[2] != -1 && map._mobData._monsters[combat._attackMonsters[2]]._frame >= 0) {
+		} else if (combat._attackMonsters[2] != -1 && map._mobData._monsters[combat._attackMonsters[2]]._frame >= 0) {
 			_indoorList[159] = _indoorList[153];
 			_indoorList[160] = _indoorList[154];
 			_indoorList[161] = _indoorList[155];
@@ -2250,6 +2244,9 @@ void InterfaceMap::setMazeBits() {
 	}
 }
 
+/**
+ * Set up draw structures for displaying on-screen monsters
+ */
 void InterfaceMap::setIndoorsMonsters() {
 	Combat &combat = *_vm->_combat;
 	Map &map = *_vm->_map;
@@ -2498,6 +2495,10 @@ void InterfaceMap::setIndoorsMonsters() {
 	}
 }
 
+/**
+ * Helper method for setIndoorsMonsters to set a draw structure
+ * with the deatils for a given monster
+ */
 void InterfaceMap::setMonsterSprite(DrawStruct &drawStruct, MazeMonster &monster, SpriteResource *sprites, 
 		int frame, int defaultY) {
 	MonsterStruct &monsterData = _vm->_map->_monsterData[monster._spriteId];
@@ -2519,6 +2520,9 @@ void InterfaceMap::setMonsterSprite(DrawStruct &drawStruct, MazeMonster &monster
 		drawStruct._flags = MONSTER_EFFECT_FLAGS[monster._effect2][monster._effect3];
 }
 
+/**
+ * Set up draw structures for displaying on-screen objects
+ */
 void InterfaceMap::setIndoorsObjects() {
 	Common::Point mazePos = _vm->_party->_mazePosition;
 	Direction dir = _vm->_party->_mazeDirection;
@@ -2744,6 +2748,9 @@ void InterfaceMap::setIndoorsObjects() {
 	}
 }
 
+/**
+ * Set up draw structures for displaying on-screen wall items
+ */
 void InterfaceMap::setIndoorsWallPics() {
 	Map &map = *_vm->_map;
 	const Common::Point &mazePos = _vm->_party->_mazePosition;
@@ -2978,6 +2985,9 @@ void InterfaceMap::setOutdoorsObjects() {
 
 }
 
+/**
+ * Draw the contents of the current 3d view of an indoor map
+ */
 void InterfaceMap::drawIndoors() {
 	Map &map = *_vm->_map;
 	int surfaceId;


Commit: c17c2aead5990d0ad5e69c0ea7c083a49b35ae96
    https://github.com/scummvm/scummvm/commit/c17c2aead5990d0ad5e69c0ea7c083a49b35ae96
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-01-24T12:09:16-05:00

Commit Message:
XEEN: Implemented outdoors drawing code in draw3d

Changed paths:
    engines/xeen/interface_map.cpp
    engines/xeen/interface_map.h
    engines/xeen/resources.cpp
    engines/xeen/resources.h



diff --git a/engines/xeen/interface_map.cpp b/engines/xeen/interface_map.cpp
index 95263c9..42bc079 100644
--- a/engines/xeen/interface_map.cpp
+++ b/engines/xeen/interface_map.cpp
@@ -413,6 +413,11 @@ void InterfaceMap::draw3d(bool updateFlag) {
 	Screen &screen = *_vm->_screen;
 	Scripts &scripts = *_vm->_scripts;
 
+	const int COMBAT_POS_X[3][2] = { { 102, 134 }, { 36, 67 }, { 161, 161 } };
+	const int INDOOR_INDEXES[3] = { 157, 151, 154 };
+	const int OUTDOOR_INDEXES[3] = { 119, 113, 116 };
+	const int COMBAT_OFFSET_X[4] = { 8, 6, 4, 2 };
+
 	if (screen._windows[11]._enabled)
 		return;
 
@@ -455,8 +460,133 @@ void InterfaceMap::draw3d(bool updateFlag) {
 	}
 
 	if (map._isOutdoors) {
-		error("TODO: draw3d outdoors handling");
+		// Outdoors drawing
+		for (int idx = 0; idx < 44; ++idx)
+			_outdoorList[OUTDOOR_DRAWSTRCT_INDEXES[idx]]._frame = -1;
+
+		if (_flag1) {
+			for (int idx = 0; idx < 8; ++idx) {
+				if (_outdoorList._combatImgs4[idx]._sprites)
+					_outdoorList._combatImgs4[idx]._frame = 0;
+				else if (_outdoorList._combatImgs3[idx]._sprites)
+					_outdoorList._combatImgs3[idx]._frame = 1;
+				else if (_outdoorList._combatImgs2[idx]._sprites)
+					_outdoorList._combatImgs2[idx]._frame = 2;
+				else if (_outdoorList._combatImgs1[idx]._sprites)
+					_outdoorList._combatImgs1[idx]._frame = 0;
+			}
+		} else if (_charsShooting) {
+			for (int idx = 0; idx < 8; ++idx) {
+				if (_outdoorList._combatImgs1[idx]._sprites)
+					_outdoorList._combatImgs1[idx]._frame = 0;
+				else if (_outdoorList._combatImgs2[idx]._sprites)
+					_outdoorList._combatImgs2[idx]._frame = 1;
+				else if (_outdoorList._combatImgs3[idx]._sprites)
+					_outdoorList._combatImgs3[idx]._frame = 2;
+				else if (_outdoorList._combatImgs4[idx]._sprites)
+					_outdoorList._combatImgs1[idx]._frame = 0;
+			}
+		}
+
+		_isAnimReset = false;
+		int attackMon2 = combat._attackMonsters[2];
+
+		for (int idx = 0; idx < 3; ++idx) {
+			DrawStruct &ds1 = _outdoorList[OUTDOOR_INDEXES[idx] + 1];
+			DrawStruct &ds2 = _outdoorList[OUTDOOR_INDEXES[idx]];
+			ds1._sprites = nullptr;
+			ds2._sprites = nullptr;
+
+			if (combat._charsArray1[idx]) {
+				int vIndex = combat._attackMonsters[1] && !attackMon2 ? 1 : 0;
+				combat._charsArray1[idx]--;
+
+				if (combat._monPow[idx]) {
+					ds2._x = COMBAT_POS_X[idx][vIndex];
+					ds2._frame = 0;
+					ds2._scale = combat._monsterScale[idx];
+
+					if (ds2._scale == 0x8000) {
+						ds2._x /= 3;
+						ds2._y = 60;
+					} else {
+						ds2._y = 73;
+					}
+
+					ds2._flags = SPRFLAG_4000 | SPRFLAG_2000;
+					ds2._sprites = &_charPowSprites;
+				}
+
+				if (combat._elemPow[idx]) {
+					ds1._x = COMBAT_POS_X[idx][vIndex] + COMBAT_OFFSET_X[idx];
+					ds1._frame = combat._elemPow[idx];
+					ds1._scale = combat._elemScale[idx];
+
+					if (ds1._scale == 0x8000)
+						ds1._x /= 3;
+					ds1._flags = SPRFLAG_4000 | SPRFLAG_2000;
+					ds1._sprites = &_charPowSprites;
+				}
+			}
+		}
+
+		setOutdoorsMonsters();
+		setOutdoorsObjects();
+
+		_outdoorList[123]._sprites = nullptr;
+		_outdoorList[122]._sprites = nullptr;
+		_outdoorList[121]._sprites = nullptr;
+
+		int monsterIndex;
+		if (combat._attackMonsters[0] != -1 && map._mobData._monsters[combat._attackMonsters[0]]._frame >= 8) {
+			_outdoorList[121] = _outdoorList[118];
+			_outdoorList[122] = _outdoorList[119];
+			_outdoorList[123] = _outdoorList[120];
+			_outdoorList[118]._sprites = nullptr;
+			_outdoorList[119]._sprites = nullptr;
+			_outdoorList[120]._sprites = nullptr;
+			monsterIndex = 1;
+		} else if (combat._attackMonsters[1] != -1 && map._mobData._monsters[combat._attackMonsters[1]]._frame >= 8) {
+			_outdoorList[121] = _outdoorList[112];
+			_outdoorList[122] = _outdoorList[113];
+			_outdoorList[123] = _outdoorList[114];
+			_outdoorList[112]._sprites = nullptr;
+			_outdoorList[113]._sprites = nullptr;
+			_outdoorList[124]._sprites = nullptr;
+			monsterIndex = 2;
+		} else if (combat._attackMonsters[2] != -1 && map._mobData._monsters[combat._attackMonsters[2]]._frame >= 8) {
+			_outdoorList[121] = _outdoorList[115];
+			_outdoorList[122] = _outdoorList[116];
+			_outdoorList[123] = _outdoorList[117];
+			_outdoorList[115]._sprites = nullptr;
+			_outdoorList[116]._sprites = nullptr;
+			_outdoorList[117]._sprites = nullptr;
+			monsterIndex = 3;
+		}
+
+		drawOutdoors();
+
+		switch (monsterIndex) {
+		case 1:
+			_outdoorList[118] = _outdoorList[121];
+			_outdoorList[119] = _outdoorList[122];
+			_outdoorList[120] = _outdoorList[123];
+			break;
+		case 2:
+			_outdoorList[112] = _outdoorList[121];
+			_outdoorList[113] = _outdoorList[122];
+			_outdoorList[114] = _outdoorList[123];
+			break;
+		case 3:
+			_outdoorList[115] = _outdoorList[121];
+			_outdoorList[116] = _outdoorList[122];
+			_outdoorList[117] = _outdoorList[123];
+			break;
+		default:
+			break;
+		}
 	} else {
+		// Indoor drawing
 		// Default all the parts of draw struct not to be drawn by default
 		for (int idx = 3; idx < _indoorList.size(); ++idx)
 			_indoorList[idx]._frame = -1;
@@ -495,11 +625,8 @@ void InterfaceMap::draw3d(bool updateFlag) {
 
 		setMazeBits();
 		_isAnimReset = false;
-		const int INDOOR_INDEXES[3] = { 157, 151, 154 };
-		const int INDOOR_COMBAT_POS[3][2] = { { 102, 134 }, { 36, 67 }, { 161, 161 } };
-		const int INDOOR_COMBAT_POS2[4] = { 8, 6, 4, 2 };
 
-		// Double check this, since it's not being used?
+		// Code in the original that's not being used
 		//MazeObject &objObject = map._mobData._objects[_objNumber - 1];
 
 		for (int idx = 0; idx < 3; ++idx) {
@@ -513,7 +640,7 @@ void InterfaceMap::draw3d(bool updateFlag) {
 				--combat._charsArray1[idx];
 
 				if (combat._monPow[idx]) {
-					ds1._x = INDOOR_COMBAT_POS[idx][0];
+					ds1._x = COMBAT_POS_X[idx][posIndex];
 					ds1._frame = 0;
 					ds1._scale = combat._monsterScale[idx];
 					if (ds1._scale == 0x8000) {
@@ -528,7 +655,7 @@ void InterfaceMap::draw3d(bool updateFlag) {
 				}
 
 				if (combat._elemPow[idx]) {
-					ds2._x = INDOOR_COMBAT_POS[idx][posIndex] + INDOOR_COMBAT_POS2[idx];
+					ds2._x = COMBAT_POS_X[idx][posIndex] + COMBAT_OFFSET_X[idx];
 					ds2._frame = combat._elemPow[idx];
 					ds2._scale = combat._elemScale[idx];
 					if (ds2._scale == 0x8000)
@@ -549,7 +676,7 @@ void InterfaceMap::draw3d(bool updateFlag) {
 
 		// Handle attacking monsters
 		int monsterIndex = 0;
-		if (combat._attackMonsters[0] != -1 && map._mobData._monsters[combat._attackMonsters[0]]._frame >= 0) {
+		if (combat._attackMonsters[0] != -1 && map._mobData._monsters[combat._attackMonsters[0]]._frame >= 8) {
 			_indoorList[159] = _indoorList[156];
 			_indoorList[160] = _indoorList[157];
 			_indoorList[161] = _indoorList[158];
@@ -557,7 +684,7 @@ void InterfaceMap::draw3d(bool updateFlag) {
 			_indoorList[156]._sprites = nullptr;
 			_indoorList[157]._sprites = nullptr;
 			monsterIndex = 1;
-		} else if (combat._attackMonsters[1] != -1 && map._mobData._monsters[combat._attackMonsters[1]]._frame >= 0) {
+		} else if (combat._attackMonsters[1] != -1 && map._mobData._monsters[combat._attackMonsters[1]]._frame >= 8) {
 			_indoorList[159] = _indoorList[150];
 			_indoorList[160] = _indoorList[151];
 			_indoorList[161] = _indoorList[152];
@@ -565,7 +692,7 @@ void InterfaceMap::draw3d(bool updateFlag) {
 			_indoorList[151]._sprites = nullptr;
 			_indoorList[150]._sprites = nullptr;
 			monsterIndex = 2;
-		} else if (combat._attackMonsters[2] != -1 && map._mobData._monsters[combat._attackMonsters[2]]._frame >= 0) {
+		} else if (combat._attackMonsters[2] != -1 && map._mobData._monsters[combat._attackMonsters[2]]._frame >= 8) {
 			_indoorList[159] = _indoorList[153];
 			_indoorList[160] = _indoorList[154];
 			_indoorList[161] = _indoorList[155];
@@ -2978,11 +3105,11 @@ void InterfaceMap::setIndoorsWallPics() {
 }
 
 void InterfaceMap::setOutdoorsMonsters() {
-
+	// TODO
 }
 
 void InterfaceMap::setOutdoorsObjects() {
-
+	// TODO
 }
 
 /**
@@ -3834,6 +3961,14 @@ void InterfaceMap::drawIndoors() {
 	_charsShooting = _isShooting;
 }
 
+/**
+ * Draw the contents of the current 3d view of an outdoor map
+ */
+void InterfaceMap::drawOutdoors() {
+	// TODO
+}
+
+
 void InterfaceMap::moveMonsters() {
 	// TODO
 }
diff --git a/engines/xeen/interface_map.h b/engines/xeen/interface_map.h
index 3ae73b7..4a4ff13 100644
--- a/engines/xeen/interface_map.h
+++ b/engines/xeen/interface_map.h
@@ -166,6 +166,8 @@ public:
 
 	void setOutdoorsObjects();
 
+	void drawOutdoors();
+
 	void drawTownAnim(int v);
 };
 
diff --git a/engines/xeen/resources.cpp b/engines/xeen/resources.cpp
index 556544d..b54779d 100644
--- a/engines/xeen/resources.cpp
+++ b/engines/xeen/resources.cpp
@@ -550,4 +550,11 @@ const int METAL_LAC[9] = { -3, 0, -2, -1, 1, 2, 4, 6, 8 };
 
 const int ARMOR_STRENGTHS[14] = { 0, 2, 4, 5, 6, 7, 8, 10, 4, 2, 1, 1, 1, 1 };
 
+const int OUTDOOR_DRAWSTRCT_INDEXES[44] = {
+	37, 38, 39, 40, 41, 44, 42, 43, 47, 45, 46,
+	48, 49, 52, 50, 51, 66, 67, 68, 69, 70, 71,
+	72, 75, 73, 74, 87, 88, 89, 90, 91, 94, 92,
+	93, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120
+};
+
 } // End of namespace Xeen
diff --git a/engines/xeen/resources.h b/engines/xeen/resources.h
index b1c9720..58ac405 100644
--- a/engines/xeen/resources.h
+++ b/engines/xeen/resources.h
@@ -142,6 +142,8 @@ extern const int METAL_LAC[9];
 
 extern const int ARMOR_STRENGTHS[14];
 
+extern const int OUTDOOR_DRAWSTRCT_INDEXES[44];
+
 } // End of namespace Xeen
 
 #endif	/* XEEN_RESOURCES_H */


Commit: a04daf38207bf6b7624bea04a662c38968f4e7d9
    https://github.com/scummvm/scummvm/commit/a04daf38207bf6b7624bea04a662c38968f4e7d9
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-01-24T13:49:41-05:00

Commit Message:
XEEN: Implemented drawOutdoorsMonsters

Changed paths:
    engines/xeen/interface_map.cpp
    engines/xeen/resources.cpp
    engines/xeen/resources.h



diff --git a/engines/xeen/interface_map.cpp b/engines/xeen/interface_map.cpp
index 42bc079..9c3d7b7 100644
--- a/engines/xeen/interface_map.cpp
+++ b/engines/xeen/interface_map.cpp
@@ -2379,7 +2379,6 @@ void InterfaceMap::setIndoorsMonsters() {
 	Map &map = *_vm->_map;
 	Common::Point mazePos = _vm->_party->_mazePosition;
 	Direction dir = _vm->_party->_mazeDirection;
-	const int INDOOR_MONSTERS_Y[4] = { 2, 34, 53, 59 };
 
 	combat.clear();
 	for (uint monsterIdx = 0; monsterIdx < map._mobData._monsters.size(); ++monsterIdx) {
@@ -3105,6 +3104,255 @@ void InterfaceMap::setIndoorsWallPics() {
 }
 
 void InterfaceMap::setOutdoorsMonsters() {
+	Combat &combat = *_vm->_combat;
+	Map &map = *_vm->_map;
+	Party &party = *_vm->_party;
+	Direction dir = party._mazeDirection;
+	Common::Point pt = party._mazePosition;
+
+	for (uint idx = 0; idx < map._mobData._monsters.size(); ++idx) {
+		MazeMonster &monster = map._mobData._monsters[idx];
+
+		if (monster._position.x == (pt.x + SCREEN_POSITIONING_X[dir][2]) &&
+				monster._position.y == (pt.y + SCREEN_POSITIONING_Y[dir][2])) {
+			monster._isAttacking = true;
+			if (combat._attackMonsters[0] == -1) {
+				_outdoorList[118]._frame = idx;
+				combat._attackMonsters[0] = idx;
+			} else if (combat._attackMonsters[1] == -1) {
+				_outdoorList[112]._frame = idx;
+				combat._attackMonsters[1] = idx;
+			} else if (combat._attackMonsters[2] == -1) {
+				_outdoorList[115]._frame = idx;
+				combat._attackMonsters[2] = idx;
+			}
+		}
+
+		if (monster._position.x == (pt.x + SCREEN_POSITIONING_X[dir][7]) &&
+				monster._position.y == (pt.y + SCREEN_POSITIONING_Y[dir][7])) {
+			monster._isAttacking = true;
+			if (combat._attackMonsters[3] == -1) {
+				_outdoorList[94]._frame = idx;
+				combat._attackMonsters[3] = idx;
+			} else if (combat._attackMonsters[4] == -1) {
+				_outdoorList[92]._frame = idx;
+				combat._attackMonsters[4] = idx;
+			} else if (combat._attackMonsters[5] == -1) {
+				_outdoorList[93]._frame = idx;
+				combat._attackMonsters[5] = idx;
+			}
+		}
+
+		if (monster._position.x == (pt.x + SCREEN_POSITIONING_X[dir][5]) &&
+				monster._position.y == (pt.y + SCREEN_POSITIONING_Y[dir][5])) {
+			monster._isAttacking = true;
+			if (combat._attackMonsters[12] == -1) {
+				_outdoorList[90]._frame = idx;
+				combat._attackMonsters[12] = idx;
+			}
+		}
+
+		if (monster._position.x == (pt.x + SCREEN_POSITIONING_X[dir][9]) &&
+				monster._position.y == (pt.y + SCREEN_POSITIONING_Y[dir][9])) {
+			monster._isAttacking = true;
+			if (combat._attackMonsters[13] == -1) {
+				_outdoorList[91]._frame = idx;
+				combat._attackMonsters[13] = idx;
+			}
+		}
+
+		if (monster._position.x == (pt.x + SCREEN_POSITIONING_X[dir][14]) &&
+				monster._position.y == (pt.y + SCREEN_POSITIONING_Y[dir][14])) {
+			monster._isAttacking = true;
+			if (combat._attackMonsters[6] == -1) {
+				_outdoorList[75]._frame = idx;
+				combat._attackMonsters[6] = idx;
+			} else if (combat._attackMonsters[7] == -1) {
+				_outdoorList[73]._frame = idx;
+				combat._attackMonsters[7] = idx;
+			} else if (combat._attackMonsters[8] == -1) {
+				_outdoorList[74]._frame = idx;
+				combat._attackMonsters[8] = idx;
+			}
+		}
+
+		if (monster._position.x == (pt.x + SCREEN_POSITIONING_X[dir][12]) &&
+				monster._position.y == (pt.y + SCREEN_POSITIONING_Y[dir][12])) {
+			monster._isAttacking = true;
+			if (combat._attackMonsters[14] == -1) {
+				_outdoorList[69]._frame = idx;
+				combat._attackMonsters[14] = idx;
+			} else if (combat._attackMonsters[20] == -1) {
+				_outdoorList[70]._frame = idx;
+				combat._attackMonsters[20] = idx;
+			}
+		}
+
+		if (monster._position.x == (pt.x + SCREEN_POSITIONING_X[dir][16]) &&
+				monster._position.y == (pt.y + SCREEN_POSITIONING_Y[dir][16])) {
+			monster._isAttacking = true;
+			if (combat._attackMonsters[15] == -1) {
+				_outdoorList[71]._frame = idx;
+				combat._attackMonsters[15] = idx;
+			} else if (combat._attackMonsters[21] == -1) {
+				_outdoorList[72]._frame = idx;
+				combat._attackMonsters[21] = idx;
+			}
+		}
+
+		if (monster._position.x == (pt.x + SCREEN_POSITIONING_X[dir][27]) &&
+				monster._position.y == (pt.y + SCREEN_POSITIONING_Y[dir][27])) {
+			monster._isAttacking = true;
+			if (combat._attackMonsters[9] == -1) {
+				_outdoorList[52]._frame = idx;
+				combat._attackMonsters[9] = idx;
+			} else if (combat._attackMonsters[10] == -1) {
+				_outdoorList[50]._frame = idx;
+				combat._attackMonsters[10] = idx;
+			} else if (combat._attackMonsters[11] == -1) {
+				_outdoorList[51]._frame = idx;
+				combat._attackMonsters[11] = idx;
+			}
+		}
+
+		if (monster._position.x == (pt.x + SCREEN_POSITIONING_X[dir][25]) &&
+				monster._position.y == (pt.y + SCREEN_POSITIONING_Y[dir][25])) {
+			monster._isAttacking = true;
+			if (combat._attackMonsters[16] == -1) {
+				_outdoorList[44]._frame = idx;
+				combat._attackMonsters[16] = idx;
+			} else if (combat._attackMonsters[22] == -1) {
+				_outdoorList[42]._frame = idx;
+				combat._attackMonsters[22] = idx;
+			} else if (combat._attackMonsters[24] == -1) {
+				_outdoorList[43]._frame = idx;
+				combat._attackMonsters[24] = idx;
+			}
+		}
+
+		if (monster._position.x == (pt.x + SCREEN_POSITIONING_X[dir][23]) &&
+				monster._position.y == (pt.y + SCREEN_POSITIONING_Y[dir][23])) {
+			monster._isAttacking = true;
+			if (combat._attackMonsters[18] == -1) {
+				_outdoorList[48]._frame = idx;
+				combat._attackMonsters[18] = idx;
+			}
+		}
+
+		if (monster._position.x == (pt.x + SCREEN_POSITIONING_X[dir][29]) &&
+				monster._position.y == (pt.y + SCREEN_POSITIONING_Y[dir][29])) {
+			monster._isAttacking = true;
+			if (combat._attackMonsters[17] == -1) {
+				_outdoorList[47]._frame = idx;
+				combat._attackMonsters[17] = idx;
+			} else if (combat._attackMonsters[23] == -1) {
+				_outdoorList[45]._frame = idx;
+				combat._attackMonsters[23] = idx;
+			} else if (combat._attackMonsters[25] == -1) {
+				_outdoorList[46]._frame = idx;
+				combat._attackMonsters[25] = idx;
+			}
+		}
+
+		if (monster._position.x == (pt.x + SCREEN_POSITIONING_X[dir][31]) &&
+				monster._position.y == (pt.y + SCREEN_POSITIONING_Y[dir][31])) {
+			monster._isAttacking = true;
+			if (combat._attackMonsters[19] == -1) {
+				_outdoorList[49]._frame = idx;
+				combat._attackMonsters[19] = idx;
+			}
+		}
+	}
+
+	_outdoorList[115]._x = 58;
+	_outdoorList[93]._x = 25;
+	_outdoorList[74]._x = 9;
+	_outdoorList[51]._x = -1;
+	_outdoorList[43]._x = -26;
+	_outdoorList[46]._x = 23;
+	_outdoorList[48]._x = -58;
+	_outdoorList[49]._x = 40;
+	_outdoorList[69]._x = -65;
+	_outdoorList[70]._x = -85;
+	_outdoorList[71]._x = 49;
+	_outdoorList[72]._x = 65;
+	_outdoorList[90]._x = -112;
+	_outdoorList[91]._x = 98;
+
+	if (combat._attackMonsters[1] != -1 && combat._attackMonsters[2] == -1) {
+		_outdoorList[118]._x = 31;
+		_outdoorList[112]._x = -36;
+	} else {
+		_outdoorList[118]._x = -5;
+		_outdoorList[112]._x = -67;
+	}
+	if (combat._attackMonsters[4] != -1 && combat._attackMonsters[5] == -1) {
+		_outdoorList[94]._x = 8;
+		_outdoorList[92]._x = -23;
+	} else {
+		_outdoorList[94]._x = -7;
+		_outdoorList[92]._x = -38;
+	}
+	if (combat._attackMonsters[7] != -1 && combat._attackMonsters[8] == -1) {
+		_outdoorList[75]._x = 0;
+		_outdoorList[73]._x = -16;
+	} else {
+		_outdoorList[75]._x = -8;
+		_outdoorList[73]._x = -24;
+	}
+	if (combat._attackMonsters[10] != -1 && combat._attackMonsters[11] == -1) {
+		_outdoorList[52]._x = -5;
+		_outdoorList[50]._x = -13;
+	} else {
+		_outdoorList[52]._x = -9;
+		_outdoorList[50]._x = -17;
+	}
+	if (combat._attackMonsters[22] != -1 && combat._attackMonsters[24] == -1) {
+		_outdoorList[44]._x = -27;
+		_outdoorList[42]._x = -37;
+	} else {
+		_outdoorList[44]._x = -34;
+		_outdoorList[42]._x = -41;
+	}
+	if (combat._attackMonsters[23] != -1 && combat._attackMonsters[25] == -1) {
+		_outdoorList[47]._x = 20;
+		_outdoorList[45]._x = -12;
+	} else {
+		_outdoorList[47]._x = 16;
+		_outdoorList[45]._x = -16;
+	}
+
+	for (int idx = 0; idx < 26; ++idx) {
+		DrawStruct &ds = _outdoorList[OUTDOOR_MONSTER_INDEXES[idx]];
+
+		if (ds._frame != -1) {
+			ds._flags &= ~0xfff;
+
+			// TODO: Double-check.. this section looks *weird*
+			MazeMonster &monster = map._mobData._monsters[ds._frame];
+			MonsterStruct &monsterData = map._monsterData[monster._spriteId];
+
+			ds._frame = monster._frame;
+
+			if (monster._effect2) {
+				ds._flags = MONSTER_EFFECT_FLAGS[monster._effect2 - 1][monster._effect3];
+			}
+
+			if (monster._frame > 7) {
+				monster._frame -= 8;
+				ds._sprites = monster._attackSprites;
+			} else {
+				ds._sprites = monster._sprites;
+			}
+
+			ds._y = OUTDOOR_MONSTERS_Y[idx];
+
+			if (monsterData._flying) {
+				ds._x += COMBAT_FLOAT_X[_combatFloatCounter];
+				ds._y += COMBAT_FLOAT_Y[_combatFloatCounter];
+			}
+		}
+	}
 	// TODO
 }
 
diff --git a/engines/xeen/resources.cpp b/engines/xeen/resources.cpp
index b54779d..803fea2 100644
--- a/engines/xeen/resources.cpp
+++ b/engines/xeen/resources.cpp
@@ -404,14 +404,21 @@ const int INDOOR_OBJECT_Y[2][12] = {
 	{ -65, -6, -6, -6, 36, 36, 36, 54, 54, 54, 54, 54 }
 };
 
+const int INDOOR_MONSTERS_Y[4] = { 2, 34, 53, 59 };
+
 const int OUTDOOR_OBJECT_X[2][12] = {
 	{ -5, -7, -112, 98, -8, -77, 61, -9, -43, 25, -74, 56 },
 	{ -35, -35, -142, 68, -35, -95, 19, -35, -62, -24, -98, 16 }
 };
 
-const int OUTDOOR_OBJECT_Y[2][12] = {
-	{ 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 69 },
-	{ 70, 71, 72, 73, 74, 75, 90, 91, 92, 93, 94, 112 }
+const int OUTDOOR_MONSTER_INDEXES[26] = {
+	42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 69, 70,
+	71, 72, 73, 74, 75, 90, 91, 92, 93, 94, 112, 115, 118
+};
+
+const int OUTDOOR_MONSTERS_Y[26] = {
+	59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 53, 53,
+	53, 53, 53, 53, 53, 34, 34, 34, 34, 34, 2, 2, 2
 };
 
 const int DIRECTION_ANIM_POSITIONS[4][4] = {
diff --git a/engines/xeen/resources.h b/engines/xeen/resources.h
index 58ac405..98c30f4 100644
--- a/engines/xeen/resources.h
+++ b/engines/xeen/resources.h
@@ -98,9 +98,13 @@ extern const int INDOOR_OBJECT_X[2][12];
 
 extern const int INDOOR_OBJECT_Y[2][12];
 
+extern const int INDOOR_MONSTERS_Y[4];
+
 extern const int OUTDOOR_OBJECT_X[2][12];
 
-extern const int OUTDOOR_OBJECT_Y[2][12];
+extern const int OUTDOOR_MONSTER_INDEXES[26];
+
+extern const int OUTDOOR_MONSTERS_Y[26];
 
 extern const int DIRECTION_ANIM_POSITIONS[4][4];
 


Commit: 409edeb1e8bb77db8cfa7b3621be41f8772fd2e1
    https://github.com/scummvm/scummvm/commit/409edeb1e8bb77db8cfa7b3621be41f8772fd2e1
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-01-24T14:15:24-05:00

Commit Message:
XEEN: Implemented drawOutdoorsObjects

Changed paths:
    engines/xeen/interface_map.cpp
    engines/xeen/resources.cpp
    engines/xeen/resources.h



diff --git a/engines/xeen/interface_map.cpp b/engines/xeen/interface_map.cpp
index 9c3d7b7..a699b8f 100644
--- a/engines/xeen/interface_map.cpp
+++ b/engines/xeen/interface_map.cpp
@@ -2672,7 +2672,7 @@ void InterfaceMap::setIndoorsObjects() {
 			&& (mazePos.y + SCREEN_POSITIONING_Y[dir][2]) == mazeObject._position.y
 			&& _indoorList._objects0._frame == -1) {
 			_indoorList._objects0._x = INDOOR_OBJECT_X[listOffset][0];
-			_indoorList._objects0._y = INDOOR_OBJECT_Y[listOffset][0];
+			_indoorList._objects0._y = MAP_OBJECT_Y[listOffset][0];
 			_indoorList._objects0._frame = mazeObject._frame;
 			_indoorList._objects0._sprites = mazeObject._sprites;
 			_indoorList._objects0._flags &= ~SPRFLAG_HORIZ_FLIPPED;
@@ -2686,7 +2686,7 @@ void InterfaceMap::setIndoorsObjects() {
 			&& (mazePos.y + SCREEN_POSITIONING_Y[dir][7]) == mazeObject._position.y
 			&& !_wo[27] && _indoorList._objects1._frame == -1) {
 			_indoorList._objects1._x = INDOOR_OBJECT_X[listOffset][1];
-			_indoorList._objects1._y = INDOOR_OBJECT_Y[listOffset][1];
+			_indoorList._objects1._y = MAP_OBJECT_Y[listOffset][1];
 			_indoorList._objects1._frame = mazeObject._frame;
 			_indoorList._objects1._sprites = mazeObject._sprites;
 			_indoorList._objects1._flags &= ~SPRFLAG_HORIZ_FLIPPED;
@@ -2703,7 +2703,7 @@ void InterfaceMap::setIndoorsObjects() {
 			} else if (_wo[23] && _wo[28]) {
 			} else if (_indoorList._objects2._frame == -1) {
 				_indoorList._objects2._x = INDOOR_OBJECT_X[listOffset][2];
-				_indoorList._objects2._y = INDOOR_OBJECT_Y[listOffset][2];
+				_indoorList._objects2._y = MAP_OBJECT_Y[listOffset][2];
 				_indoorList._objects2._frame = mazeObject._frame;
 				_indoorList._objects2._sprites = mazeObject._sprites;
 				_indoorList._objects2._flags &= ~SPRFLAG_HORIZ_FLIPPED;
@@ -2721,7 +2721,7 @@ void InterfaceMap::setIndoorsObjects() {
 			} else if (_wo[24] && _wo[29]) {
 			} else if (_indoorList._objects3._frame == -1) {
 				_indoorList._objects3._x = INDOOR_OBJECT_X[listOffset][3];
-				_indoorList._objects3._y = INDOOR_OBJECT_Y[listOffset][3];
+				_indoorList._objects3._y = MAP_OBJECT_Y[listOffset][3];
 				_indoorList._objects3._frame = mazeObject._frame;
 				_indoorList._objects3._sprites = mazeObject._sprites;
 				_indoorList._objects3._flags &= ~SPRFLAG_HORIZ_FLIPPED;
@@ -2735,7 +2735,7 @@ void InterfaceMap::setIndoorsObjects() {
 			&& (mazePos.y + SCREEN_POSITIONING_Y[dir][14]) == mazeObject._position.y) {
 			if (!_wo[22] && !_wo[27] && _indoorList._objects4._frame == -1) {
 				_indoorList._objects4._x = INDOOR_OBJECT_X[listOffset][4];
-				_indoorList._objects4._y = INDOOR_OBJECT_Y[listOffset][4];
+				_indoorList._objects4._y = MAP_OBJECT_Y[listOffset][4];
 				_indoorList._objects4._frame = mazeObject._frame;
 				_indoorList._objects4._sprites = mazeObject._sprites;
 				_indoorList._objects4._flags &= ~SPRFLAG_HORIZ_FLIPPED;
@@ -2754,7 +2754,7 @@ void InterfaceMap::setIndoorsObjects() {
 			} else if (_wo[20] && _wo[17]) {
 			} else if (_indoorList._objects5._frame == -1) {
 				_indoorList._objects5._x = INDOOR_OBJECT_X[listOffset][5];
-				_indoorList._objects5._y = INDOOR_OBJECT_Y[listOffset][5];
+				_indoorList._objects5._y = MAP_OBJECT_Y[listOffset][5];
 				_indoorList._objects5._frame = mazeObject._frame;
 				_indoorList._objects5._sprites = mazeObject._sprites;
 				_indoorList._objects5._flags &= ~SPRFLAG_HORIZ_FLIPPED;
@@ -2773,7 +2773,7 @@ void InterfaceMap::setIndoorsObjects() {
 			} else if (_wo[21] && _wo[19]) {
 			} else if (_indoorList._objects6._frame == -1) {
 				_indoorList._objects6._x = INDOOR_OBJECT_X[listOffset][6];
-				_indoorList._objects6._y = INDOOR_OBJECT_Y[listOffset][6];
+				_indoorList._objects6._y = MAP_OBJECT_Y[listOffset][6];
 				_indoorList._objects6._frame = mazeObject._frame;
 				_indoorList._objects6._sprites = mazeObject._sprites;
 				_indoorList._objects6._flags &= ~SPRFLAG_HORIZ_FLIPPED;
@@ -2787,7 +2787,7 @@ void InterfaceMap::setIndoorsObjects() {
 			&& (mazePos.y + SCREEN_POSITIONING_Y[dir][27]) == mazeObject._position.y) {
 			if (!_wo[27] && !_wo[22] && !_wo[15] && _indoorList._objects7._frame == -1) {
 				_indoorList._objects7._x = INDOOR_OBJECT_X[listOffset][7];
-				_indoorList._objects7._y = INDOOR_OBJECT_Y[listOffset][7];
+				_indoorList._objects7._y = MAP_OBJECT_Y[listOffset][7];
 				_indoorList._objects7._frame = mazeObject._frame;
 				_indoorList._objects7._sprites = mazeObject._sprites;
 				_indoorList._objects7._flags &= ~SPRFLAG_HORIZ_FLIPPED;
@@ -2806,7 +2806,7 @@ void InterfaceMap::setIndoorsObjects() {
 			} else if (_wo[17] && _wo[7]) {
 			} else if (_indoorList._objects8._frame == -1) {
 				_indoorList._objects8._x = INDOOR_OBJECT_X[listOffset][8];
-				_indoorList._objects8._y = INDOOR_OBJECT_Y[listOffset][8];
+				_indoorList._objects8._y = MAP_OBJECT_Y[listOffset][8];
 				_indoorList._objects8._frame = mazeObject._frame;
 				_indoorList._objects8._sprites = mazeObject._sprites;
 				_indoorList._objects8._flags &= ~SPRFLAG_HORIZ_FLIPPED;
@@ -2825,7 +2825,7 @@ void InterfaceMap::setIndoorsObjects() {
 			} else if (_wo[23] && _wo[17]) {
 			} else if (!_wo[12] && !_wo[8] && _indoorList._objects9._frame == -1) {
 				_indoorList._objects9._x = INDOOR_OBJECT_X[listOffset][9];
-				_indoorList._objects9._y = INDOOR_OBJECT_Y[listOffset][9];
+				_indoorList._objects9._y = MAP_OBJECT_Y[listOffset][9];
 				_indoorList._objects9._frame = mazeObject._frame;
 				_indoorList._objects9._sprites = mazeObject._sprites;
 				_indoorList._objects9._flags &= ~SPRFLAG_HORIZ_FLIPPED;
@@ -2844,7 +2844,7 @@ void InterfaceMap::setIndoorsObjects() {
 			} else if (_wo[19] && _wo[9]) {
 			} else if (_indoorList._objects10._frame == -1) {
 				_indoorList._objects10._x = INDOOR_OBJECT_X[listOffset][10];
-				_indoorList._objects10._y = INDOOR_OBJECT_Y[listOffset][10];
+				_indoorList._objects10._y = MAP_OBJECT_Y[listOffset][10];
 				_indoorList._objects10._frame = mazeObject._frame;
 				_indoorList._objects10._sprites = mazeObject._sprites;
 				_indoorList._objects10._flags &= ~SPRFLAG_HORIZ_FLIPPED;
@@ -2863,7 +2863,7 @@ void InterfaceMap::setIndoorsObjects() {
 			} else if (_wo[24] && _wo[19]) {
 			} else if (!_wo[14] && !_wo[10] && _indoorList._objects11._frame == -1) {
 				_indoorList._objects11._x = INDOOR_OBJECT_X[listOffset][11];
-				_indoorList._objects11._y = INDOOR_OBJECT_Y[listOffset][11];
+				_indoorList._objects11._y = MAP_OBJECT_Y[listOffset][11];
 				_indoorList._objects11._frame = mazeObject._frame;
 				_indoorList._objects11._sprites = mazeObject._sprites;
 				_indoorList._objects11._flags &= ~SPRFLAG_HORIZ_FLIPPED;
@@ -3103,6 +3103,9 @@ void InterfaceMap::setIndoorsWallPics() {
 	}
 }
 
+/**
+ * Set up the draw structures for displaying monsters on outdoor maps
+ */
 void InterfaceMap::setOutdoorsMonsters() {
 	Combat &combat = *_vm->_combat;
 	Map &map = *_vm->_map;
@@ -3356,8 +3359,182 @@ void InterfaceMap::setOutdoorsMonsters() {
 	// TODO
 }
 
+/**
+ * Set up the draw structures for displaying objects on outdoor maps
+ */
 void InterfaceMap::setOutdoorsObjects() {
-	// TODO
+	Map &map = *_vm->_map;
+	Party &party = *_vm->_party;
+	const Common::Point &pt = party._mazePosition;
+	Direction dir = party._mazeDirection;
+	int posIndex;
+
+	for (uint idx = 0; idx < map._mobData._objects.size(); ++idx) {
+		MazeObject &obj = map._mobData._objects[idx];
+
+		if (_vm->_files->_isDarkCc) {
+			posIndex = obj._spriteId == 47 ? 1 : 0;
+		} else {
+			posIndex = obj._spriteId == 113 ? 1 : 0;
+		}
+
+		if (obj._position.x == (pt.x + SCREEN_POSITIONING_X[dir][2]) &&
+				obj._position.y == (pt.y + SCREEN_POSITIONING_Y[dir][2]) &&
+				_outdoorList[111]._frame == -1) {
+			DrawStruct &ds = _outdoorList[111];
+			ds._x = OUTDOOR_OBJECT_X[posIndex][0];
+			ds._y = MAP_OBJECT_Y[posIndex][0];
+			ds._sprites = obj._sprites;
+
+			ds._flags &= ~SPRFLAG_HORIZ_FLIPPED;
+			if (obj._flipped)
+				ds._flags |= SPRFLAG_HORIZ_FLIPPED;
+			_objNumber = idx;
+		}
+
+		if (obj._position.x == (pt.x + SCREEN_POSITIONING_X[dir][7]) &&
+				obj._position.y == (pt.y + SCREEN_POSITIONING_Y[dir][7]) &&
+				_outdoorList[87]._frame == -1) {
+			DrawStruct &ds = _outdoorList[87];
+			ds._x = OUTDOOR_OBJECT_X[posIndex][1];
+			ds._y = MAP_OBJECT_Y[posIndex][1];
+			ds._sprites = obj._sprites;
+
+			ds._flags &= ~SPRFLAG_HORIZ_FLIPPED;
+			if (obj._flipped)
+				ds._flags |= SPRFLAG_HORIZ_FLIPPED;
+		}
+
+		if (obj._position.x == (pt.x + SCREEN_POSITIONING_X[dir][5]) &&
+				obj._position.y == (pt.y + SCREEN_POSITIONING_Y[dir][5]) &&
+				_outdoorList[88]._frame == -1) {
+			DrawStruct &ds = _outdoorList[88];
+			ds._x = OUTDOOR_OBJECT_X[posIndex][2];
+			ds._y = MAP_OBJECT_Y[posIndex][2];
+			ds._sprites = obj._sprites;
+
+			ds._flags &= ~SPRFLAG_HORIZ_FLIPPED;
+			if (obj._flipped)
+				ds._flags |= SPRFLAG_HORIZ_FLIPPED;
+		}
+
+		if (obj._position.x == (pt.x + SCREEN_POSITIONING_X[dir][9]) &&
+				obj._position.y == (pt.y + SCREEN_POSITIONING_Y[dir][9]) &&
+				_outdoorList[89]._frame == -1) {
+			DrawStruct &ds = _outdoorList[89];
+			ds._x = OUTDOOR_OBJECT_X[posIndex][3];
+			ds._y = MAP_OBJECT_Y[posIndex][3];
+			ds._sprites = obj._sprites;
+
+			ds._flags &= ~SPRFLAG_HORIZ_FLIPPED;
+			if (obj._flipped)
+				ds._flags |= SPRFLAG_HORIZ_FLIPPED;
+		}
+
+		if (obj._position.x == (pt.x + SCREEN_POSITIONING_X[dir][14]) &&
+				obj._position.y == (pt.y + SCREEN_POSITIONING_Y[dir][14]) &&
+				_outdoorList[66]._frame == -1) {
+			DrawStruct &ds = _outdoorList[66];
+			ds._x = OUTDOOR_OBJECT_X[posIndex][4];
+			ds._y = MAP_OBJECT_Y[posIndex][4];
+			ds._sprites = obj._sprites;
+
+			ds._flags &= ~SPRFLAG_HORIZ_FLIPPED;
+			if (obj._flipped)
+				ds._flags |= SPRFLAG_HORIZ_FLIPPED;
+		}
+
+		if (obj._position.x == (pt.x + SCREEN_POSITIONING_X[dir][12]) &&
+				obj._position.y == (pt.y + SCREEN_POSITIONING_Y[dir][12]) &&
+				_outdoorList[67]._frame == -1) {
+			DrawStruct &ds = _outdoorList[67];
+			ds._x = OUTDOOR_OBJECT_X[posIndex][5];
+			ds._y = MAP_OBJECT_Y[posIndex][5];
+			ds._sprites = obj._sprites;
+
+			ds._flags &= ~SPRFLAG_HORIZ_FLIPPED;
+			if (obj._flipped)
+				ds._flags |= SPRFLAG_HORIZ_FLIPPED;
+		}
+
+		if (obj._position.x == (pt.x + SCREEN_POSITIONING_X[dir][16]) &&
+				obj._position.y == (pt.y + SCREEN_POSITIONING_Y[dir][16]) &&
+				_outdoorList[68]._frame == -1) {
+			DrawStruct &ds = _outdoorList[68];
+			ds._x = OUTDOOR_OBJECT_X[posIndex][6];
+			ds._y = MAP_OBJECT_Y[posIndex][6];
+			ds._sprites = obj._sprites;
+
+			ds._flags &= ~SPRFLAG_HORIZ_FLIPPED;
+			if (obj._flipped)
+				ds._flags |= SPRFLAG_HORIZ_FLIPPED;
+		}
+
+		if (obj._position.x == (pt.x + SCREEN_POSITIONING_X[dir][27]) &&
+				obj._position.y == (pt.y + SCREEN_POSITIONING_Y[dir][27]) &&
+				_outdoorList[37]._frame == -1) {
+			DrawStruct &ds = _outdoorList[37];
+			ds._x = OUTDOOR_OBJECT_X[posIndex][7];
+			ds._y = MAP_OBJECT_Y[posIndex][7];
+			ds._sprites = obj._sprites;
+
+			ds._flags &= ~SPRFLAG_HORIZ_FLIPPED;
+			if (obj._flipped)
+				ds._flags |= SPRFLAG_HORIZ_FLIPPED;
+		}
+
+		if (obj._position.x == (pt.x + SCREEN_POSITIONING_X[dir][25]) &&
+				obj._position.y == (pt.y + SCREEN_POSITIONING_Y[dir][25]) &&
+				_outdoorList[38]._frame == -1) {
+			DrawStruct &ds = _outdoorList[38];
+			ds._x = OUTDOOR_OBJECT_X[posIndex][8];
+			ds._y = MAP_OBJECT_Y[posIndex][8];
+			ds._sprites = obj._sprites;
+
+			ds._flags &= ~SPRFLAG_HORIZ_FLIPPED;
+			if (obj._flipped)
+				ds._flags |= SPRFLAG_HORIZ_FLIPPED;
+		}
+
+		if (obj._position.x == (pt.x + SCREEN_POSITIONING_X[dir][23]) &&
+				obj._position.y == (pt.y + SCREEN_POSITIONING_Y[dir][23]) &&
+				_outdoorList[40]._frame == -1) {
+			DrawStruct &ds = _outdoorList[40];
+			ds._x = OUTDOOR_OBJECT_X[posIndex][10];
+			ds._y = MAP_OBJECT_Y[posIndex][10];
+			ds._sprites = obj._sprites;
+
+			ds._flags &= ~SPRFLAG_HORIZ_FLIPPED;
+			if (obj._flipped)
+				ds._flags |= SPRFLAG_HORIZ_FLIPPED;
+		}
+
+		if (obj._position.x == (pt.x + SCREEN_POSITIONING_X[dir][29]) &&
+				obj._position.y == (pt.y + SCREEN_POSITIONING_Y[dir][29]) &&
+				_outdoorList[39]._frame == -1) {
+			DrawStruct &ds = _outdoorList[39];
+			ds._x = OUTDOOR_OBJECT_X[posIndex][9];
+			ds._y = MAP_OBJECT_Y[posIndex][9];
+			ds._sprites = obj._sprites;
+
+			ds._flags &= ~SPRFLAG_HORIZ_FLIPPED;
+			if (obj._flipped)
+				ds._flags |= SPRFLAG_HORIZ_FLIPPED;
+		}
+
+		if (obj._position.x == (pt.x + SCREEN_POSITIONING_X[dir][31]) &&
+				obj._position.y == (pt.y + SCREEN_POSITIONING_Y[dir][31]) &&
+				_outdoorList[41]._frame == -1) {
+			DrawStruct &ds = _outdoorList[41];
+			ds._x = OUTDOOR_OBJECT_X[posIndex][11];
+			ds._y = MAP_OBJECT_Y[posIndex][11];
+			ds._sprites = obj._sprites;
+
+			ds._flags &= ~SPRFLAG_HORIZ_FLIPPED;
+			if (obj._flipped)
+				ds._flags |= SPRFLAG_HORIZ_FLIPPED;
+		}
+	}
 }
 
 /**
diff --git a/engines/xeen/resources.cpp b/engines/xeen/resources.cpp
index 803fea2..26c33ca 100644
--- a/engines/xeen/resources.cpp
+++ b/engines/xeen/resources.cpp
@@ -399,7 +399,7 @@ const int INDOOR_OBJECT_X[2][12] = {
 	{ -35, -35, -142, 68, -35, -95, 19, -35, -62, -14, -98, 16 }
 };
 
-const int INDOOR_OBJECT_Y[2][12] = {
+const int MAP_OBJECT_Y[2][12] = {
 	{ 2, 25, 25, 25, 50, 50, 50, 58, 58, 58, 58, 58 },
 	{ -65, -6, -6, -6, 36, 36, 36, 54, 54, 54, 54, 54 }
 };
diff --git a/engines/xeen/resources.h b/engines/xeen/resources.h
index 98c30f4..2e77e95 100644
--- a/engines/xeen/resources.h
+++ b/engines/xeen/resources.h
@@ -96,7 +96,7 @@ extern const int8 SCREEN_POSITIONING_Y[4][48];
 
 extern const int INDOOR_OBJECT_X[2][12];
 
-extern const int INDOOR_OBJECT_Y[2][12];
+extern const int MAP_OBJECT_Y[2][12];
 
 extern const int INDOOR_MONSTERS_Y[4];
 


Commit: 177f47a5355fdbe6e45b51328274db02baace79b
    https://github.com/scummvm/scummvm/commit/177f47a5355fdbe6e45b51328274db02baace79b
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-01-24T14:48:00-05:00

Commit Message:
XEEN: Implement drawOutdoors

Changed paths:
    engines/xeen/interface_map.cpp
    engines/xeen/interface_map.h
    engines/xeen/map.cpp



diff --git a/engines/xeen/interface_map.cpp b/engines/xeen/interface_map.cpp
index a699b8f..04f7355 100644
--- a/engines/xeen/interface_map.cpp
+++ b/engines/xeen/interface_map.cpp
@@ -27,9 +27,9 @@
 
 namespace Xeen {
 
-OutdoorDrawList::OutdoorDrawList() : _skySprite(_data[1]), _groundSprite(_data[2]),
-	_combatImgs1(&_data[124]), _combatImgs2(&_data[95]),
-	_combatImgs3(&_data[76]), _combatImgs4(&_data[53]) {
+OutdoorDrawList::OutdoorDrawList() : _sky1(_data[0]), _sky2(_data[1]), 
+	_groundSprite(_data[2]), _combatImgs1(&_data[124]), _combatImgs2(&_data[95]),
+	_combatImgs3(&_data[76]), _combatImgs4(&_data[53]), _groundTiles(&_data[3]) {
 	_data[0] = DrawStruct(0, 8, 8);
 	_data[1] = DrawStruct(1, 8, 25);
 	_data[2] = DrawStruct(0, 8, 67);
@@ -4390,7 +4390,72 @@ void InterfaceMap::drawIndoors() {
  * Draw the contents of the current 3d view of an outdoor map
  */
 void InterfaceMap::drawOutdoors() {
-	// TODO
+	Map &map = *_vm->_map;
+	Party &party = *_vm->_party;
+	Screen &screen = *_vm->_screen;
+	int surfaceId;
+
+	// Draw any surface tiles on top of the default ground
+	for (int cellIndex = 0; cellIndex < 25; ++cellIndex) {
+		map.getCell(cellIndex == 24 ? 2 : DRAW_NUMBERS[cellIndex]);
+
+		DrawStruct &drawStruct = _indoorList._groundTiles[cellIndex];
+		SpriteResource &sprites = map._surfaceSprites[map._currentSurfaceId];
+		drawStruct._sprites = sprites.empty() ? (SpriteResource *)nullptr : &sprites;
+
+		surfaceId = map.mazeData()._surfaceTypes[map._currentSurfaceId];
+		if (surfaceId == SURFTYPE_DWATER || surfaceId == SURFTYPE_LAVA) {
+			drawStruct._frame = DRAW_FRAMES[cellIndex][_flipWater ? 1 : 0];
+			drawStruct._flags = _flipWater ? SPRFLAG_HORIZ_FLIPPED : 0;
+		} else {
+			drawStruct._frame = DRAW_FRAMES[cellIndex][_flipGround ? 1 : 0];
+			drawStruct._flags = _flipGround ? SPRFLAG_HORIZ_FLIPPED : 0;
+		}
+	}
+
+	party.handleLight();
+
+	// Set up terrain draw entries
+	const int TERRAIN_INDEXES1[9] = { 44, 36, 37, 38, 45, 43, 42, 41, 39 };
+	const int TERRAIN_INDEXES2[5] = { 22, 24, 31, 29, 26 };
+	const int TERRAIN_INDEXES3[3] = { 11, 16, 13 };
+	const int TERRAIN_INDEXES4[5] = { 5, 9, 7, 0, 4 };
+
+	for (int idx = 0; idx < 9; ++idx) {
+		map.getCell(TERRAIN_INDEXES1[idx]);
+		_outdoorList[36 + idx]._sprites = &map._wallSprites._surfaces[map._currentWall._data];
+	}
+	for (int idx = 0; idx < 5; ++idx) {
+		map.getCell(TERRAIN_INDEXES2[idx]);
+		_outdoorList[61 + idx]._sprites = &map._wallSprites._surfaces[map._currentWall._data];
+	}
+	for (int idx = 0; idx < 3; ++idx) {
+		map.getCell(TERRAIN_INDEXES3[idx]);
+		_outdoorList[84 + idx]._sprites = &map._wallSprites._surfaces[map._currentWall._data];
+	}
+	for (int idx = 0; idx < 5; ++idx) {
+		map.getCell(TERRAIN_INDEXES4[idx]);
+		_outdoorList[103 + idx]._sprites = &map._wallSprites._surfaces[map._currentWall._data];
+	}
+
+	map.getCell(1);
+	_outdoorList[108]._sprites = &map._wallSprites._surfaces[map._currentWall._data];
+	_outdoorList[109]._sprites = &map._wallSprites._surfaces[map._currentWall._data];
+	_outdoorList[110]._sprites = &map._wallSprites._surfaces[map._currentWall._data];
+	_outdoorList._sky1._flags = _outdoorList._sky2._flags = _flipSky ? SPRFLAG_HORIZ_FLIPPED : 0;
+	_outdoorList._groundSprite._flags = _flipWater ? SPRFLAG_HORIZ_FLIPPED : 0;
+
+	// Finally render the outdoor scene
+	screen._windows[3].drawList(&_outdoorList[0], _outdoorList.size());
+
+	// Check for any character shooting
+	_isShooting = false;
+	for (int i = 0; i < _vm->_party->_partyCount; ++i) {
+		if (_vm->_combat->_shooting[i])
+			_isShooting = true;
+	}
+
+	_charsShooting = _isShooting;
 }
 
 
diff --git a/engines/xeen/interface_map.h b/engines/xeen/interface_map.h
index 4a4ff13..3ee2c43 100644
--- a/engines/xeen/interface_map.h
+++ b/engines/xeen/interface_map.h
@@ -34,8 +34,9 @@ class XeenEngine;
 class OutdoorDrawList {
 public:
 	DrawStruct _data[132];
-	DrawStruct &_skySprite;
+	DrawStruct &_sky1, &_sky2;
 	DrawStruct &_groundSprite;
+	DrawStruct * const _groundTiles;
 	DrawStruct * const _combatImgs1;
 	DrawStruct * const _combatImgs2;
 	DrawStruct * const _combatImgs3;
diff --git a/engines/xeen/map.cpp b/engines/xeen/map.cpp
index 043f8c0..ae38b77 100644
--- a/engines/xeen/map.cpp
+++ b/engines/xeen/map.cpp
@@ -1088,7 +1088,7 @@ void Map::load(int mapId) {
 
 		_groundSprites.load("water.out");
 		_tileSprites.load("outdoor.til");
-		outdoorList._skySprite._sprites = &_skySprites[0];
+		outdoorList._sky2._sprites = &_skySprites[0];
 		outdoorList._groundSprite._sprites = &_groundSprites;
 		
 		for (int i = 0; i < TOTAL_SURFACES; ++i) {


Commit: 339dfcb2cc9fde227abc15ad9b298f7b16194785
    https://github.com/scummvm/scummvm/commit/339dfcb2cc9fde227abc15ad9b298f7b16194785
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-01-24T15:14:57-05:00

Commit Message:
XEEN: Restrict drawing in windows to drawing within their bounds

Changed paths:
    engines/xeen/screen.cpp
    engines/xeen/sprites.cpp
    engines/xeen/sprites.h



diff --git a/engines/xeen/screen.cpp b/engines/xeen/screen.cpp
index 42182cc..16e4955 100644
--- a/engines/xeen/screen.cpp
+++ b/engines/xeen/screen.cpp
@@ -38,7 +38,7 @@ Window::Window(XeenEngine *vm, const Common::Rect &bounds, int a, int border,
 		_vm(vm), _enabled(false), _a(a), _border(border), 
 		_xLo(xLo), _ycL(ycL), _xHi(xHi), _ycH(ycH) {
 	setBounds(bounds);
-	create(_vm->_screen, Common::Rect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT));
+	create(_vm->_screen, bounds);
 }
 
 void Window::setBounds(const Common::Rect &r) {
@@ -167,17 +167,12 @@ void Window::writeString(const Common::String &s) {
 }
 
 void Window::drawList(DrawStruct *items, int count) {
-	Screen &screen = *_vm->_screen;
-
 	for (int i = 0; i < count; ++i, ++items) {
 		if (items->_frame == -1 || items->_scale == -1 || items->_sprites == nullptr)
 			continue;
-
-		Common::Rect bounds = _innerBounds;
-		bounds.translate(items->_x, items->_y);
-
+			
 		// TODO: There are two sprite calls in this method. Figure out why
-		items->_sprites->draw(screen, items->_frame,
+		items->_sprites->draw(*this, items->_frame,
 			Common::Point(items->_x, items->_y), items->_flags, items->_scale);
 	}
 }
diff --git a/engines/xeen/sprites.cpp b/engines/xeen/sprites.cpp
index 62074ed..5adc0e5 100644
--- a/engines/xeen/sprites.cpp
+++ b/engines/xeen/sprites.cpp
@@ -104,9 +104,10 @@ void SpriteResource::drawOffset(XSurface &dest, uint16 offset, const Common::Poi
 	bool flipped = (flags & SPRFLAG_HORIZ_FLIPPED) != 0;
 	int xInc = flipped ? -1 : 1;
 
-	if (dest.w < (xOffset + width) || dest.h < (yOffset + height))
-		dest.create(xOffset + width, yOffset + height);
-
+	if (flags & SPRFLAG_RESIZE) {
+		if (dest.w < (xOffset + width) || dest.h < (yOffset + height))
+			dest.create(xOffset + width, yOffset + height);
+	}
 	// The pattern steps used in the pattern command
 	const int patternSteps[] = { 0, 1, 1, 1, 2, 2, 3, 3, 0, -1, -1, -1, -2, -2, -3, -3 };
 
diff --git a/engines/xeen/sprites.h b/engines/xeen/sprites.h
index d1a801e..15a3b7c 100644
--- a/engines/xeen/sprites.h
+++ b/engines/xeen/sprites.h
@@ -34,7 +34,7 @@ namespace Xeen {
 class XeenEngine;
 
 enum SpriteFlags { SPRFLAG_2000 = 0x2000, SPRFLAG_4000 = 0x4000, 
-	SPRFLAG_HORIZ_FLIPPED = 0x8000 };
+	SPRFLAG_HORIZ_FLIPPED = 0x8000, SPRFLAG_RESIZE = 0x10000 };
 
 class SpriteResource {
 private:


Commit: c01120aedd2eb32f15f48b780dddcccc3189acea
    https://github.com/scummvm/scummvm/commit/c01120aedd2eb32f15f48b780dddcccc3189acea
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-01-24T15:29:02-05:00

Commit Message:
XEEN: Extra comments to sprite resource class

Changed paths:
    engines/xeen/sprites.cpp



diff --git a/engines/xeen/sprites.cpp b/engines/xeen/sprites.cpp
index 5adc0e5..7bffa68 100644
--- a/engines/xeen/sprites.cpp
+++ b/engines/xeen/sprites.cpp
@@ -43,6 +43,9 @@ SpriteResource::~SpriteResource() {
 	clear();
 }
 
+/**
+ * Copy operator for duplicating a sprite resource
+ */
 SpriteResource &SpriteResource::operator=(const SpriteResource &src) {
 	delete[] _data;
 	_index.clear();
@@ -58,16 +61,25 @@ SpriteResource &SpriteResource::operator=(const SpriteResource &src) {
 	return *this;
 }
 
+/**
+ * Load a sprite resource from a given file
+ */
 void SpriteResource::load(const Common::String &filename) {
 	File f(filename);
 	load(f);
 }
 
+/**
+ * Load a sprite resource from a given file and archive
+ */
 void SpriteResource::load(const Common::String &filename, Common::Archive &archive) {
 	File f(filename, archive);
 	load(f);
 }
 
+/**
+ * Load a sprite resource from a stream
+ */
 void SpriteResource::load(Common::SeekableReadStream &f) {
 	// Read in a copy of the file
 	_filesize = f.size();
@@ -86,12 +98,18 @@ void SpriteResource::load(Common::SeekableReadStream &f) {
 	}
 }
 
+/**
+ * Clears the sprite resource
+ */
 void SpriteResource::clear() {
 	delete[] _data;
 	_data = nullptr;
 	_filesize = 0;
 }
 
+/**
+ * Draws a frame using data at a specific offset in the sprite resource
+ */
 void SpriteResource::drawOffset(XSurface &dest, uint16 offset, const Common::Point &destPos, int flags) const {
 	// Get cell header
 	Common::MemoryReadStream f(_data, _filesize);
@@ -229,8 +247,12 @@ void SpriteResource::drawOffset(XSurface &dest, uint16 offset, const Common::Poi
 		dest.addDirtyRect(r);
 }
 
+/**
+ * Draw the sprite onto the given surface
+ */
 void SpriteResource::draw(XSurface &dest, int frame, const Common::Point &destPos, 
 		int flags, int scale) const {
+	assert(scale != 0x8000); // TODO: TO test when I find scale value used
 
 	if (scale == 0) {
 		drawOffset(dest, _index[frame]._offset1, destPos, flags);
@@ -261,6 +283,9 @@ void SpriteResource::draw(XSurface &dest, int frame, const Common::Point &destPo
 	}
 }
 
+/**
+ * Draw the sprite onto the given surface
+ */
 void SpriteResource::draw(XSurface &dest, int frame) const {
 	draw(dest, frame, Common::Point());
 }


Commit: 41f7664fa854d49d20935b2a0db61fab9e46af41
    https://github.com/scummvm/scummvm/commit/41f7664fa854d49d20935b2a0db61fab9e46af41
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-01-24T16:10:45-05:00

Commit Message:
XEEN: Implemented cmdIf opcode

Changed paths:
    engines/xeen/scripts.cpp
    engines/xeen/scripts.h



diff --git a/engines/xeen/scripts.cpp b/engines/xeen/scripts.cpp
index 10ba972..e63cd7b 100644
--- a/engines/xeen/scripts.cpp
+++ b/engines/xeen/scripts.cpp
@@ -132,8 +132,6 @@ void Scripts::checkEvents() {
 						(_currentPos.x | _currentPos.y) && event._line == _lineNum) {
 					if (event._direction == party._mazeDirection || event._direction == DIR_ALL) {
 						_vm->_mode = MODE_9;
-						_paramText = event._parameters.size() == 0 ? "" :
-							map._events._text[event._parameters[0]];
 						doOpcode(event);
 						break;
 					} else {
@@ -197,7 +195,8 @@ void Scripts::doOpcode(MazeEvent &event) {
  */
 void Scripts::cmdDisplay1(Common::Array<byte> &params) {
 	Screen &screen = *_vm->_screen;
-	Common::String msg = Common::String::format("\r\x03""c%s", _paramText.c_str());
+	Common::String paramText = _vm->_map->_events._text[_event->_parameters[0]];
+	Common::String msg = Common::String::format("\r\x03""c%s", paramText.c_str());
 
 	screen._windows[12].close();
 	if (screen._windows[38]._enabled)
@@ -214,8 +213,10 @@ void Scripts::cmdDisplay1(Common::Array<byte> &params) {
  */
 void Scripts::cmdDoorTextSml(Common::Array<byte> &params) {
 	Interface &intf = *_vm->_interface;
+
+	Common::String paramText = _vm->_map->_events._text[_event->_parameters[0]];
 	intf._screenText = Common::String::format("\x02\f""08\x03""c\t116\v025%s\x03""l\fd""\x01", 
-		_paramText.c_str());
+		paramText.c_str());
 	intf._upDoorText = true;
 	intf.draw3d(true);
 
@@ -228,8 +229,10 @@ void Scripts::cmdDoorTextSml(Common::Array<byte> &params) {
  */
 void Scripts::cmdDoorTextLrg(Common::Array<byte> &params) {
 	Interface &intf = *_vm->_interface;
+
+	Common::String paramText = _vm->_map->_events._text[_event->_parameters[0]];
 	intf._screenText = Common::String::format("\f04\x03""c\t116\v030%s\x03""l\fd",
-		_paramText.c_str());
+		paramText.c_str());
 	intf._upDoorText = true;
 	intf.draw3d(true);
 
@@ -242,8 +245,10 @@ void Scripts::cmdDoorTextLrg(Common::Array<byte> &params) {
  */
 void Scripts::cmdSignText(Common::Array<byte> &params) {
 	Interface &intf = *_vm->_interface;
+
+	Common::String paramText = _vm->_map->_events._text[_event->_parameters[0]];
 	intf._screenText = Common::String::format("\f08\x03""c\t120\v088%s\x03""l\fd",
-		_paramText.c_str());
+		paramText.c_str());
 	intf._upDoorText = true;
 	intf.draw3d(true);
 
@@ -273,21 +278,47 @@ void Scripts::cmdTeleport(Common::Array<byte> &params) {
  * Do a conditional check
  */
 void Scripts::cmdIf(Common::Array<byte> &params) {
+	Party &party = *_vm->_party;
+	uint32 mask;
+	int newLineNum;
+
 	switch (params[0]) {
 	case 16:
 	case 34:
 	case 100:
-		// TODO
+		mask = (params[4] << 24) | (params[3] << 16) | (params[2] << 8) | params[1];
+		newLineNum = params[5];
 		break;
 	case 25:
 	case 35:
 	case 101:
 	case 106:
-		// TODO
+		mask = (params[2] << 8) | params[1];
+		newLineNum = params[3];
 		break;
 	default:
+		mask = params[1];
+		newLineNum = params[2];
 		break;
 	}
+
+	bool result;
+	if ((_charIndex != 0 && _charIndex != 8) || params[0] == 44) {
+		result = ifProc(params[0], mask, _event->_opcode - 8, _charIndex);
+	} else {
+		result = false;
+		for (int idx = 0; idx < party._partyCount && !result; ++idx) {
+			if (_charIndex == 0 || (_charIndex == 8 && idx != _v2)) {
+				result = ifProc(params[0], mask, _event->_opcode - 8, idx);
+			}
+		}
+	}
+
+	if (result)
+		_lineNum = newLineNum - 1;
+
+	_var4F = true;
+	cmdNoAction(params);
 }
 
 /**
diff --git a/engines/xeen/scripts.h b/engines/xeen/scripts.h
index fb415ca..9725825 100644
--- a/engines/xeen/scripts.h
+++ b/engines/xeen/scripts.h
@@ -138,7 +138,6 @@ private:
 	int _v2;
 	int _var4F;
 	int _nEdamageType;
-	Common::String _paramText;
 	MazeEvent *_event;
 	Common::Point _currentPos;
 	Common::Stack<StackEntry> _stack;


Commit: f742dc8d33abda26e47ebd4c73aa8b901e69d608
    https://github.com/scummvm/scummvm/commit/f742dc8d33abda26e47ebd4c73aa8b901e69d608
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-01-24T17:33:47-05:00

Commit Message:
XEEN: Fixes to ifProc

Changed paths:
    engines/xeen/files.cpp
    engines/xeen/scripts.cpp



diff --git a/engines/xeen/files.cpp b/engines/xeen/files.cpp
index 0c3402f..50949b7 100644
--- a/engines/xeen/files.cpp
+++ b/engines/xeen/files.cpp
@@ -200,7 +200,7 @@ FileManager::FileManager(XeenEngine *vm) {
 	Common::File f;
 	int sideNum = 0;
 
-	_isDarkCc = vm->getGameID() != GType_Clouds;
+	_isDarkCc = vm->getGameID() == GType_DarkSide;
 	_sideArchives[0] = _sideArchives[1] = nullptr;
 
 	if (vm->getGameID() != GType_DarkSide) {
diff --git a/engines/xeen/scripts.cpp b/engines/xeen/scripts.cpp
index e63cd7b..6df5345 100644
--- a/engines/xeen/scripts.cpp
+++ b/engines/xeen/scripts.cpp
@@ -116,7 +116,7 @@ void Scripts::checkEvents() {
 		_nEdamageType = 0;
 //		int var40 = -1;
 
-		while (_lineNum >= 0) {
+		while (!_vm->shouldQuit() && _lineNum >= 0) {
 			// Break out of the events if there's an attacking monster
 			if (combat._attackMonsters[0] != -1) {
 				_eventSkipped = true;
@@ -140,9 +140,9 @@ void Scripts::checkEvents() {
 				}
 			}
 			if (eventIndex == map._events.size())
-				break;
+				_lineNum = -1;
 		}
-	} while (0);
+	} while (!_vm->shouldQuit() && _lineNum != -1);
 
 	// TODO
 }
@@ -304,7 +304,7 @@ void Scripts::cmdIf(Common::Array<byte> &params) {
 
 	bool result;
 	if ((_charIndex != 0 && _charIndex != 8) || params[0] == 44) {
-		result = ifProc(params[0], mask, _event->_opcode - 8, _charIndex);
+		result = ifProc(params[0], mask, _event->_opcode - 8, _charIndex - 1);
 	} else {
 		result = false;
 		for (int idx = 0; idx < party._partyCount && !result; ++idx) {
@@ -826,8 +826,7 @@ bool Scripts::ifProc(int action, uint32 mask, int mode, int charIndex) {
 		if (_vm->_files->_isDarkCc)
 			mask += 0x100;
 		assert(mask < 0x200);
-		if (party._gameFlags[mask])
-			v = mask;
+		v = party._gameFlags[mask] ? mask : 0xffffffff;
 		break;
 	case 21:
 		// Scans inventories for given item number
@@ -1063,8 +1062,7 @@ bool Scripts::ifProc(int action, uint32 mask, int mode, int charIndex) {
 		break;
 	case 99:
 		// Party skills check
-		if (party.checkSkill((Skill)mask))
-			v = mask;
+		v = party.checkSkill((Skill)mask) ? mask : 0xffffffff;
 		break;
 	case 102:
 		// Thievery skill
@@ -1072,13 +1070,12 @@ bool Scripts::ifProc(int action, uint32 mask, int mode, int charIndex) {
 		break;
 	case 103:
 		// Get value of world flag
-		if (party._worldFlags[mask])
-			v = mask;
+		v = party._worldFlags[mask] ? mask : 0xffffffff;
 		break;
 	case 104:
 		// Get value of quest flag
-		if (party._quests[mask + (_vm->_files->_isDarkCc ? 30 : 0)])
-			v = mask;
+		v = party._quests[mask + (_vm->_files->_isDarkCc ? 30 : 0)] ?
+			mask : 0xffffffff;
 		break;
 	case 105:
 		// Test number of Megacredits in party. Only used by King's Engineer in Castle Burlock


Commit: 0d8d66cb82c4b6236af4b05e36f5a69461597580
    https://github.com/scummvm/scummvm/commit/0d8d66cb82c4b6236af4b05e36f5a69461597580
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-01-24T18:31:54-05:00

Commit Message:
XEEN: Fix center aligning text in writeString

Changed paths:
    engines/xeen/font.cpp



diff --git a/engines/xeen/font.cpp b/engines/xeen/font.cpp
index aee05f9..1668ef5 100644
--- a/engines/xeen/font.cpp
+++ b/engines/xeen/font.cpp
@@ -113,8 +113,10 @@ Common::String FontSurface::writeString(const Common::String &s, const Common::R
 				}
 			} else {
 				// Found word break, find end of previous word 
-				while (displayEnd > _displayString && (*displayEnd & 0x7f) == ' ')
-					--displayEnd;
+				while (endP > _displayString && (*endP & 0x7f) == ' ')
+					--endP;
+
+				displayEnd = endP;
 			}
 		}
 
@@ -123,9 +125,12 @@ Common::String FontSurface::writeString(const Common::String &s, const Common::R
 			// Figure out the width of the selected portion of the string
 			int totalWidth = 0;
 			while (!getNextCharWidth(totalWidth)) {
-				if (_displayString > displayEnd && *displayEnd == ' ') {
-					// Don't include any ending space as part of the total
-					totalWidth -= _fontReduced ? 4 : 5;
+				if (_displayString > displayEnd) {
+					if (*displayEnd == ' ') {
+						// Don't include any ending space as part of the total
+						totalWidth -= _fontReduced ? 4 : 5;
+					}
+					break;
 				}
 			}
 


Commit: fe6b580ff11e3ee7b518e478f20a5a7423afb425
    https://github.com/scummvm/scummvm/commit/fe6b580ff11e3ee7b518e478f20a5a7423afb425
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-01-24T19:38:58-05:00

Commit Message:
XEEN: Implement cmdCheckProtection and cmdAlterEvent opcodes

Changed paths:
    engines/xeen/scripts.cpp
    engines/xeen/scripts.h



diff --git a/engines/xeen/scripts.cpp b/engines/xeen/scripts.cpp
index 6df5345..5abd63a 100644
--- a/engines/xeen/scripts.cpp
+++ b/engines/xeen/scripts.cpp
@@ -178,7 +178,7 @@ void Scripts::doOpcode(MazeEvent &event) {
 		&Scripts::cmdAlterHed, &Scripts::cmdDisplayStat, &Scripts::cmdTakeOrGive,
 		&Scripts::cmdSeatTextSml, &Scripts::cmdPlayEventVoc, &Scripts::cmdDisplayBottom,
 		&Scripts::cmdIfMapFlag, &Scripts::cmdSelRndChar, &Scripts::cmdGiveEnchanted,
-		&Scripts::cmdItemType, &Scripts::cmdMakeNothingHere, &Scripts::cmdNoAction2,
+		&Scripts::cmdItemType, &Scripts::cmdMakeNothingHere, &Scripts::cmdCheckProtection,
 		&Scripts::cmdChooseNumeric, &Scripts::cmdDisplayBottomTwoLines,
 		&Scripts::cmdDisplayLarge, &Scripts::cmdExchObj, &Scripts::cmdFallToMap,
 		&Scripts::cmdDisplayMain, &Scripts::cmdGoto, &Scripts::cmdConfirmWord,
@@ -534,7 +534,25 @@ void Scripts::cmdJumpRnd(Common::Array<byte> &params) {
 	cmdNoAction(params);
 }
 
-void Scripts::cmdAlterEvent(Common::Array<byte> &params) { error("TODO"); }
+/**
+ * Alter an existing event
+ */
+void Scripts::cmdAlterEvent(Common::Array<byte> &params) {
+	Map &map = *_vm->_map;
+	Party &party = *_vm->_party;
+
+	for (uint idx = 0; idx < map._events.size(); ++idx) {
+		MazeEvent &evt = map._events[idx];
+		if (evt._position == party._mazePosition &&
+				(evt._direction == DIR_ALL || evt._direction == party._mazeDirection) &&
+				evt._line == params[0]) {
+			evt._opcode = (Opcode)params[1];
+		}
+	}
+
+	_var4F = true;
+	cmdNoAction(params);
+}
 
 /**
  * Stores the current location and line for later resuming, and set up to execute
@@ -607,7 +625,13 @@ void Scripts::cmdMakeNothingHere(Common::Array<byte> &params) {
 	cmdExit(params);
 }
 
-void Scripts::cmdNoAction2(Common::Array<byte> &params) { error("TODO"); }
+void Scripts::cmdCheckProtection(Common::Array<byte> &params) {
+	if (copyProtectionCheck())
+		cmdNoAction(params);
+	else
+		cmdExit(params);
+}
+
 void Scripts::cmdChooseNumeric(Common::Array<byte> &params) { error("TODO"); }
 void Scripts::cmdDisplayBottomTwoLines(Common::Array<byte> &params) { error("TODO"); }
 void Scripts::cmdDisplayLarge(Common::Array<byte> &params) { error("TODO"); }
@@ -907,8 +931,7 @@ bool Scripts::ifProc(int action, uint32 mask, int mode, int charIndex) {
 		break;
 	case 44:
 		v = YesNo::show(_vm, mask, 0);
-		if (!mask && v)
-			v = 0;
+		v = (!v && !mask) ? 2 : mask;
 		break;
 	case 45:
 		// Might base (before bonus)
@@ -1101,4 +1124,9 @@ bool Scripts::ifProc(int action, uint32 mask, int mode, int charIndex) {
 	}
 }
 
+bool Scripts::copyProtectionCheck() {
+	// Currentl not implemented
+	return true;
+}
+
 } // End of namespace Xeen
diff --git a/engines/xeen/scripts.h b/engines/xeen/scripts.h
index 9725825..66dcb9b 100644
--- a/engines/xeen/scripts.h
+++ b/engines/xeen/scripts.h
@@ -183,7 +183,7 @@ private:
 	void cmdGiveEnchanted(Common::Array<byte> &params);
 	void cmdItemType(Common::Array<byte> &params);
 	void cmdMakeNothingHere(Common::Array<byte> &params);
-	void cmdNoAction2(Common::Array<byte> &params);
+	void cmdCheckProtection(Common::Array<byte> &params);
 	void cmdChooseNumeric(Common::Array<byte> &params);
 	void cmdDisplayBottomTwoLines(Common::Array<byte> &params);
 	void cmdDisplayLarge(Common::Array<byte> &params);
@@ -208,6 +208,8 @@ private:
 	void doEnding(const Common::String &endStr, int v2);
 
 	bool ifProc(int action, uint32 mask, int mode, int charIndex);
+
+	bool copyProtectionCheck();
 public:
 	int _animCounter;
 	bool _eventSkipped;


Commit: 2a9c00cb963b00f8255e95684d78dfe01c943fc5
    https://github.com/scummvm/scummvm/commit/2a9c00cb963b00f8255e95684d78dfe01c943fc5
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-01-24T22:15:57-05:00

Commit Message:
XEEN: Fix to cmdSpawn, and implemented cmdSetValue

Changed paths:
    engines/xeen/party.cpp
    engines/xeen/party.h
    engines/xeen/scripts.cpp
    engines/xeen/scripts.h



diff --git a/engines/xeen/party.cpp b/engines/xeen/party.cpp
index 2822e41..388b8de 100644
--- a/engines/xeen/party.cpp
+++ b/engines/xeen/party.cpp
@@ -182,7 +182,7 @@ int Character::getMaxHP() const {
 int Character::getMaxSP() const {
 	int result = 0;
 	bool flag = false;
-	int amount;
+	int amount = 0;
 	Attribute attrib;
 	Skill skill;
 
@@ -550,6 +550,213 @@ int Character::conditionMod(Attribute attrib) const {
 	return v[attrib];
 }
 
+void Character::setValue(int id, uint value) {
+	Party &party = *Party::_vm->_party;
+	Scripts &scripts = *Party::_vm->_scripts;
+
+	switch (id) {
+	case 3:
+		// Set character sex
+		_sex = (Sex)value;
+		break;
+	case 4:
+		// Set race
+		_race = (Race)value;
+		break;
+	case 5:
+		// Set class
+		_class = (CharacterClass)value;
+		break;
+	case 8:
+		// Set the current Hp
+		_currentHp = value;
+		break;
+	case 9:
+		// Set the current Sp
+		_currentSp = value;
+		break;
+	case 10:
+	case 77:
+		// Set temporary armor class
+		_ACTemp = value;
+		break;
+	case 11:
+		// Set temporary level
+		_level._temporary = value;
+		break;
+	case 12:
+		// Set the character's temporary age
+		_tempAge = value;
+		break;
+	case 16:
+		// Set character experience
+		_experience = value;
+		break;
+	case 17:
+		// Set party poison resistence
+		party._poisonResistence = value;
+		break;
+	case 18:
+		// Set condition
+		if (value == 16) {
+			// Clear all the conditions
+			Common::fill(&_conditions[CURSED], &_conditions[NO_CONDITION], false);
+		} else if (value == 6) {
+			_conditions[value] = 1;
+		} else {
+			++_conditions[value];
+		}
+
+		if (value >= DEAD && value <= ERADICATED && _currentHp > 0)
+			_currentHp = 0;
+		break;
+	case 25:
+		// Set time of day in minutes (0-1440)
+		party._minutes = value;
+		break;
+	case 34:
+		// Set party gold
+		party._gold = value;
+		break;
+	case 35:
+		// Set party gems
+		party._gems = value;
+		break;
+	case 37:
+		_might._temporary = value;
+		break;
+	case 38:
+		_intellect._temporary = value;
+		break;
+	case 39:
+		_personality._temporary = value;
+		break;
+	case 40:
+		_endurance._temporary = value;
+		break;
+	case 41:
+		_speed._temporary = value;
+		break;
+	case 42:
+		_accuracy._temporary = value;
+		break;
+	case 43:
+		_luck._temporary = value;
+		break;
+	case 45:
+		_might._permanent = value;
+		break;
+	case 46:
+		_intellect._permanent = value;
+		break;
+	case 47:
+		_personality._permanent = value;
+		break;
+	case 48:
+		_endurance._permanent = value;
+		break;
+	case 49:
+		_speed._permanent = value;
+		break;
+	case 50:
+		_accuracy._permanent = value;
+		break;
+	case 51:
+		_luck._permanent = value;
+		break;
+	case 52:
+		_fireResistence._permanent = value;
+		break;
+	case 53:
+		_electricityResistence._permanent = value;
+		break;
+	case 54:
+		_coldResistence._permanent = value;
+		break;
+	case 55:
+		_poisonResistence._permanent = value;
+		break;
+	case 56:
+		_energyResistence._permanent = value;
+		break;
+	case 57:
+		_magicResistence._permanent = value;
+		break;
+	case 58:
+		_fireResistence._temporary = value;
+		break;
+	case 59:
+		_electricityResistence._temporary = value;
+		break;
+	case 60:
+		_coldResistence._temporary = value;
+		break;
+	case 61:
+		_poisonResistence._temporary = value;
+		break;
+	case 62:
+		_energyResistence._temporary = value;
+		break;
+	case 63:
+		_magicResistence._temporary = value;
+		break;
+	case 64:
+		_level._permanent = value;
+		break;
+	case 65:
+		// Set party food
+		party._food = value;
+		break;
+	case 69:
+		// Set levitate active
+		party._levitateActive = value != 0;
+		break;
+	case 70:
+		party._lightCount = value;
+		break;
+	case 71:
+		party._fireResistence = value;
+		break;
+	case 72:
+		party._electricityResistence = value;
+		break;
+	case 73:
+		party._coldResistence = value;
+		break;
+	case 74:
+		party._walkOnWaterActive = value != 0;
+		party._poisonResistence = value;
+		party._wizardEyeActive = value != 0;
+		party._coldResistence = value;
+		party._electricityResistence = value;
+		party._fireResistence = value;
+		party._lightCount = value;
+		party._levitateActive = value != 0;
+		break;
+	case 76:
+		// Set day of the year (0-99)
+		party._day = value;
+		break;
+	case 79:
+		party._wizardEyeActive = true;
+		break;
+	case 83:
+		scripts._nEdamageType = value;
+		break;
+	case 84:
+		party._mazeDirection = (Direction)value;
+		break;
+	case 85:
+		party._year = value;
+		break;
+	case 94:
+		party._walkOnWaterActive = value != 0;
+		break;
+	default:
+		break;
+	}
+}
+
 /*------------------------------------------------------------------------*/
 
 void Roster::synchronize(Common::Serializer &s) {
diff --git a/engines/xeen/party.h b/engines/xeen/party.h
index dc87e88..c77364b 100644
--- a/engines/xeen/party.h
+++ b/engines/xeen/party.h
@@ -165,6 +165,8 @@ public:
 	int getCurrentLevel() const;
 
 	int itemScan(int itemId) const;
+
+	void setValue(int id, uint value);
 };
 
 class Roster: public Common::Array<Character> {
diff --git a/engines/xeen/scripts.cpp b/engines/xeen/scripts.cpp
index 5abd63a..57196af 100644
--- a/engines/xeen/scripts.cpp
+++ b/engines/xeen/scripts.cpp
@@ -381,6 +381,10 @@ void Scripts::cmdSetChar(Common::Array<byte> &params) {
  * Spawn a monster
  */
 void Scripts::cmdSpawn(Common::Array<byte> &params) {
+	Map &map = *_vm->_map;
+	if (params[0] >= map._mobData._monsters.size())
+		map._mobData._monsters.resize(params[0] + 1);
+
 	MazeMonster &monster = _vm->_map->_mobData._monsters[params[0]];
 	MonsterStruct &monsterData = _vm->_map->_monsterData[monster._spriteId];
 	monster._position.x = params[1];
@@ -580,7 +584,43 @@ void Scripts::cmdReturn(Common::Array<byte> &params) {
 	cmdNoAction(params);
 }
 
-void Scripts::cmdSetVar(Common::Array<byte> &params) { error("TODO"); }
+void Scripts::cmdSetVar(Common::Array<byte> &params) { 
+	Party &party = *_vm->_party;
+	bool flag = true;
+	uint val;
+
+	switch (params[0]) {
+	case 25:
+	case 35:
+	case 101:
+	case 106:
+		val = (params[2] << 8) | params[1];
+		break;
+	case 16:
+	case 34:
+	case 100:
+		val = (params[4] << 24) | (params[3] << 16) | (params[2] << 8) | params[3];
+		break;
+	default:
+		val = params[1];
+		break;
+	}
+
+	if (_charIndex != 0 && _charIndex != 8) {
+		party._activeParty[_charIndex - 1].setValue(params[0], val);
+	} else {
+		// Set value for entire party
+		for (int idx = 0; idx < party._partyCount; ++idx) {
+			if (_charIndex == 0 || (_charIndex == 8 && _v2 != idx)) {
+				party._activeParty[idx].setValue(params[0], val);
+			}
+		}
+	}
+
+	_var4F = true;
+	cmdNoAction(params);
+}
+
 void Scripts::cmdCutsceneEndClouds(Common::Array<byte> &params) { error("TODO"); }
 
 void Scripts::cmdWhoWill(Common::Array<byte> &params) { 
diff --git a/engines/xeen/scripts.h b/engines/xeen/scripts.h
index 66dcb9b..6193153 100644
--- a/engines/xeen/scripts.h
+++ b/engines/xeen/scripts.h
@@ -137,7 +137,6 @@ private:
 
 	int _v2;
 	int _var4F;
-	int _nEdamageType;
 	MazeEvent *_event;
 	Common::Point _currentPos;
 	Common::Stack<StackEntry> _stack;
@@ -214,6 +213,7 @@ public:
 	int _animCounter;
 	bool _eventSkipped;
 	int _whoWill;
+	int _nEdamageType;
 public:
 	Scripts(XeenEngine *vm);
 


Commit: b695934a1e5a62aa854bfc02bb4f10f562efe62b
    https://github.com/scummvm/scummvm/commit/b695934a1e5a62aa854bfc02bb4f10f562efe62b
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-01-24T23:12:30-05:00

Commit Message:
XEEN: Implemented cmdTeleport opcode

Changed paths:
    engines/xeen/dialogs_string_input.cpp
    engines/xeen/items.h
    engines/xeen/screen.cpp
    engines/xeen/screen.h
    engines/xeen/scripts.cpp
    engines/xeen/scripts.h



diff --git a/engines/xeen/dialogs_string_input.cpp b/engines/xeen/dialogs_string_input.cpp
index 03191f8..ced4ad3 100644
--- a/engines/xeen/dialogs_string_input.cpp
+++ b/engines/xeen/dialogs_string_input.cpp
@@ -21,6 +21,7 @@
  */
 
 #include "xeen/dialogs_string_input.h"
+#include "xeen/scripts.h"
 #include "xeen/xeen.h"
 
 namespace Xeen {
@@ -38,6 +39,7 @@ int StringInput::execute(bool type, const Common::String &expected,
 		const Common::String &title, int opcode) {
 	Interface &intf = *_vm->_interface;
 	Screen &screen = *_vm->_screen;
+	Scripts &scripts = *_vm->_scripts;
 	Window &w = screen._windows[6];
 	SoundManager &sound = *_vm->_sound;
 	int result = 0;
@@ -58,8 +60,13 @@ int StringInput::execute(bool type, const Common::String &expected,
 			// Load in the mirror list
 			File f(Common::String::format("%smirr.txt",
 				_vm->_files->_isDarkCc ? "dark" : "xeen"));
-			for (int idx = 0; f.pos() < f.size(); ++idx) {
-				if (line == f.readLine()) {
+			MirrorEntry me;
+			scripts._mirror.clear();
+			while (me.synchronize(f))
+				scripts._mirror.push_back(me);
+
+			for (uint idx = 0; idx < scripts._mirror.size(); ++idx) {
+				if (line == scripts._mirror[idx]._name) {
 					result = idx;
 					sound.playFX(_vm->_files->_isDarkCc ? 35 : 61);
 					break;
diff --git a/engines/xeen/items.h b/engines/xeen/items.h
index 9141def..95a5519 100644
--- a/engines/xeen/items.h
+++ b/engines/xeen/items.h
@@ -33,7 +33,7 @@ namespace Xeen {
 class XeenItem {
 public:
 	int _material;
-	int _name;
+	uint _name;
 	int _bonusFlags;
 	bool _equipped;
 public:
diff --git a/engines/xeen/screen.cpp b/engines/xeen/screen.cpp
index 16e4955..4eabc2b 100644
--- a/engines/xeen/screen.cpp
+++ b/engines/xeen/screen.cpp
@@ -180,9 +180,7 @@ void Window::drawList(DrawStruct *items, int count) {
 /**
  * Allows the user to enter a string
  */
-int Window::getString(Common::String &line, int maxLen, int maxWidth) {
-	Interface &intf = *_vm->_interface;
-
+int Window::getString(Common::String &line, uint maxLen, int maxWidth) {
 	_vm->_noDirectionSense = true;
 	Common::String msg = Common::String::format("\x03""l\t000\x04%03d\x03""c", maxWidth);
 	writeString(msg);
diff --git a/engines/xeen/screen.h b/engines/xeen/screen.h
index 5e4e46c..6e805c2 100644
--- a/engines/xeen/screen.h
+++ b/engines/xeen/screen.h
@@ -95,7 +95,7 @@ public:
 
 	void drawList(DrawStruct *items, int count);
 
-	int getString(Common::String &line, int maxLen, int maxWidth);
+	int getString(Common::String &line, uint maxLen, int maxWidth);
 };
 
 class Screen: public FontSurface {
diff --git a/engines/xeen/scripts.cpp b/engines/xeen/scripts.cpp
index 57196af..39202c0 100644
--- a/engines/xeen/scripts.cpp
+++ b/engines/xeen/scripts.cpp
@@ -69,6 +69,24 @@ void MazeEvents::synchronize(XeenSerializer &s) {
 
 /*------------------------------------------------------------------------*/
 
+bool MirrorEntry::synchronize(Common::SeekableReadStream &s) {
+	if (s.pos() >= s.size())
+		return false;
+
+	char buffer[28];
+	s.read(buffer, 28);
+	buffer[27] = '\0';
+
+	_name = Common::String(buffer);
+	_mapId = s.readByte();
+	_position.x = s.readSByte();
+	_position.y = s.readSByte();
+	_direction = s.readSByte();
+	return true;
+}
+
+/*------------------------------------------------------------------------*/
+
 Scripts::Scripts(XeenEngine *vm) : _vm(vm) {
 	Common::fill(&_charFX[0], &_charFX[MAX_ACTIVE_PARTY], 0);
 	_whoWill = 0;
@@ -82,6 +100,7 @@ Scripts::Scripts(XeenEngine *vm) : _vm(vm) {
 	_nEdamageType = 0;
 	_animCounter = 0;
 	_eventSkipped = false;
+	_mirrorId = -1;
 }
 
 void Scripts::checkEvents() {
@@ -271,7 +290,67 @@ void Scripts::cmdPlayFX(Common::Array<byte> &params) {
 }
 
 void Scripts::cmdTeleport(Common::Array<byte> &params) {
-	error("TODO");
+	EventsManager &events = *_vm->_events;
+	Interface &intf = *_vm->_interface;
+	Map &map = *_vm->_map;
+	Party &party = *_vm->_party;
+	Screen &screen = *_vm->_screen;
+	SoundManager &sound = *_vm->_sound;
+
+	screen.closeWindows();
+	_var4F = true;
+
+	int mapId;
+	Common::Point pt;
+
+	if (params[0]) {
+		mapId = params[0];
+		pt = Common::Point((int8)params[1], (int8)params[2]);
+	} else {
+		assert(_mirrorId > 0);
+		MirrorEntry &me = _mirror[_mirrorId - 1];
+		mapId = me._mapId;
+		pt = me._position;
+		if (me._direction != -1)
+			party._mazeDirection = (Direction)me._direction;
+
+		if (pt.x == 0 && pt.y == 0)
+			pt.x = 999;
+
+		sound.playFX(51);
+	}
+
+	party._stepped = true;
+	if (mapId != party._mazeId) {
+		switch (map._mobData._objects[intf._objNumber - 1]._spriteId) {
+		case 47:
+			sound.playFX(45);
+			break;
+		case 48:
+			sound.playFX(44);
+			break;
+		default:
+			break;
+		}
+
+		// Load the new map
+		map.load(mapId);
+	}
+
+	if (pt.x == 999) {
+		party._mazePosition = map.mazeData()._runPosition;
+	} else {
+		party._mazePosition = pt;
+	}
+
+	events.clearEvents();
+
+	if (_event->_opcode == OP_TeleportAndContinue) {
+		intf.draw3d(true);
+		_lineNum = 0;
+	} else {
+		cmdExit(params);
+	}
 }
 
 /**
@@ -586,7 +665,6 @@ void Scripts::cmdReturn(Common::Array<byte> &params) {
 
 void Scripts::cmdSetVar(Common::Array<byte> &params) { 
 	Party &party = *_vm->_party;
-	bool flag = true;
 	uint val;
 
 	switch (params[0]) {
@@ -898,22 +976,22 @@ bool Scripts::ifProc(int action, uint32 mask, int mode, int charIndex) {
 		if (mask < 82) {
 			for (int idx = 0; idx < 9; ++idx) {
 				if (mask == 35) {
-					if ((int)ps._weapons[idx]._name == mask) {
+					if (ps._weapons[idx]._name == mask) {
 						v = mask;
 						break;
 					}
 				} else if (mask < 49) {
-					if ((int)ps._armor[idx]._name == (mask - 35)) {
+					if (ps._armor[idx]._name == (mask - 35)) {
 						v = mask;
 						break;
 					}
 				} else if (mask < 60) {
-					if ((int)ps._accessories[idx]._name == (mask - 49)) {
+					if (ps._accessories[idx]._name == (mask - 49)) {
 						v = mask;
 						break;
 					}
 				} else {
-					if ((int)ps._misc[idx]._name == (mask - 60)) {
+					if (ps._misc[idx]._name == (mask - 60)) {
 						v = mask;
 						break;
 					}
diff --git a/engines/xeen/scripts.h b/engines/xeen/scripts.h
index 6193153..c0168e2 100644
--- a/engines/xeen/scripts.h
+++ b/engines/xeen/scripts.h
@@ -29,6 +29,7 @@
 #include "common/stack.h"
 #include "common/str-array.h"
 #include "xeen/files.h"
+#include "xeen/party.h"
 
 namespace Xeen {
 
@@ -124,6 +125,17 @@ struct StackEntry : public Common::Point {
 	StackEntry(const Common::Point &pt, int l) : Common::Point(pt), line(l) {}
 };
 
+struct MirrorEntry {
+	Common::String _name;
+	int _mapId;
+	Common::Point _position;
+	int _direction;
+
+	MirrorEntry() : _mapId(0), _direction(DIR_ALL) {}
+	
+	bool synchronize(Common::SeekableReadStream &s);
+};
+
 class Scripts {
 private:
 	XeenEngine *_vm;
@@ -134,6 +146,7 @@ private:
 	int _treasureGems;
 	int _lineNum;
 	int _charIndex;
+	int _mirrorId;
 
 	int _v2;
 	int _var4F;
@@ -214,6 +227,7 @@ public:
 	bool _eventSkipped;
 	int _whoWill;
 	int _nEdamageType;
+	Common::Array<MirrorEntry> _mirror;
 public:
 	Scripts(XeenEngine *vm);
 


Commit: 51dba2606e1cf202d73d7c77ba15939268bb6efd
    https://github.com/scummvm/scummvm/commit/51dba2606e1cf202d73d7c77ba15939268bb6efd
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-01-24T23:49:12-05:00

Commit Message:
XEEN: Simplify _currentWall back to int for now

Changed paths:
    engines/xeen/interface.cpp
    engines/xeen/interface_map.cpp
    engines/xeen/map.cpp
    engines/xeen/map.h
    engines/xeen/scripts.cpp



diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp
index 44e2326..f85e19d 100644
--- a/engines/xeen/interface.cpp
+++ b/engines/xeen/interface.cpp
@@ -809,7 +809,7 @@ bool Interface::checkMoveDirection(int key) {
 	if (map._isOutdoors) {
 		party._mazeDirection = dir;
 
-		switch ((int)map._currentWall._outdoors._surfaceId) {
+		switch (map._currentWall) {
 		case 5:
 			if (_vm->_files->_isDarkCc)
 				goto check;
diff --git a/engines/xeen/interface_map.cpp b/engines/xeen/interface_map.cpp
index 04f7355..43a467d 100644
--- a/engines/xeen/interface_map.cpp
+++ b/engines/xeen/interface_map.cpp
@@ -1176,7 +1176,7 @@ void InterfaceMap::setMazeBits() {
 		break;
 	}
 
-	_thinWall = (_vm->_map->_currentWall._data != INVALID_CELL) && _wo[27];
+	_thinWall = (_vm->_map->_currentWall != INVALID_CELL) && _wo[27];
 
 	switch (_vm->_map->getCell(8) - 1) {
 	case 1:
@@ -4423,25 +4423,25 @@ void InterfaceMap::drawOutdoors() {
 
 	for (int idx = 0; idx < 9; ++idx) {
 		map.getCell(TERRAIN_INDEXES1[idx]);
-		_outdoorList[36 + idx]._sprites = &map._wallSprites._surfaces[map._currentWall._data];
+		_outdoorList[36 + idx]._sprites = &map._wallSprites._surfaces[map._currentWall];
 	}
 	for (int idx = 0; idx < 5; ++idx) {
 		map.getCell(TERRAIN_INDEXES2[idx]);
-		_outdoorList[61 + idx]._sprites = &map._wallSprites._surfaces[map._currentWall._data];
+		_outdoorList[61 + idx]._sprites = &map._wallSprites._surfaces[map._currentWall];
 	}
 	for (int idx = 0; idx < 3; ++idx) {
 		map.getCell(TERRAIN_INDEXES3[idx]);
-		_outdoorList[84 + idx]._sprites = &map._wallSprites._surfaces[map._currentWall._data];
+		_outdoorList[84 + idx]._sprites = &map._wallSprites._surfaces[map._currentWall];
 	}
 	for (int idx = 0; idx < 5; ++idx) {
 		map.getCell(TERRAIN_INDEXES4[idx]);
-		_outdoorList[103 + idx]._sprites = &map._wallSprites._surfaces[map._currentWall._data];
+		_outdoorList[103 + idx]._sprites = &map._wallSprites._surfaces[map._currentWall];
 	}
 
 	map.getCell(1);
-	_outdoorList[108]._sprites = &map._wallSprites._surfaces[map._currentWall._data];
-	_outdoorList[109]._sprites = &map._wallSprites._surfaces[map._currentWall._data];
-	_outdoorList[110]._sprites = &map._wallSprites._surfaces[map._currentWall._data];
+	_outdoorList[108]._sprites = &map._wallSprites._surfaces[map._currentWall];
+	_outdoorList[109]._sprites = &map._wallSprites._surfaces[map._currentWall];
+	_outdoorList[110]._sprites = &map._wallSprites._surfaces[map._currentWall];
 	_outdoorList._sky1._flags = _outdoorList._sky2._flags = _flipSky ? SPRFLAG_HORIZ_FLIPPED : 0;
 	_outdoorList._groundSprite._flags = _flipWater ? SPRFLAG_HORIZ_FLIPPED : 0;
 
diff --git a/engines/xeen/map.cpp b/engines/xeen/map.cpp
index ae38b77..52dc427 100644
--- a/engines/xeen/map.cpp
+++ b/engines/xeen/map.cpp
@@ -866,7 +866,7 @@ Map::Map(XeenEngine *vm) : _vm(vm), _mobData(vm) {
 	_mazeDataIndex = 0;
 	_currentSteppedOn = false;
 	_currentSurfaceId = 0;
-	_currentWall._data = 0;
+	_currentWall = 0;
 	_currentTile = 0;
 	_currentIsGrate = false;
 	_currentCantRest = false;
@@ -1398,7 +1398,7 @@ int Map::getCell(int idx) {
 		} else {
 			_currentSurfaceId = (mapId >= 25 && mapId <= 27) ? 7 : 0;
 		}
-		_currentWall._data = INVALID_CELL;
+		_currentWall = INVALID_CELL;
 		return INVALID_CELL;
 	} 
 
@@ -1418,7 +1418,7 @@ int Map::getCell(int idx) {
 		if (!mapId) {
 			if (_isOutdoors) {
 				_currentSurfaceId = SURFTYPE_SPACE;
-				_currentWall._data = 0;
+				_currentWall = 0;
 				return 0;
 			} else {
 				if (_vm->_files->_isDarkCc) {
@@ -1432,7 +1432,7 @@ int Map::getCell(int idx) {
 					_currentSurfaceId = (mapId >= 25 && mapId <= 27) ? SURFTYPE_ROAD : SURFTYPE_DEFAULT;
 				}
 
-				_currentWall._data = INVALID_CELL;
+				_currentWall = INVALID_CELL;
 				return INVALID_CELL;
 			}
 		
@@ -1454,7 +1454,7 @@ int Map::getCell(int idx) {
 		if (!mapId) {
 			if (_isOutdoors) {
 				_currentSurfaceId = SURFTYPE_SPACE;
-				_currentWall._data = 0;
+				_currentWall = 0;
 				return 0;
 			} else {
 				if (_vm->_files->_isDarkCc) {
@@ -1468,7 +1468,7 @@ int Map::getCell(int idx) {
 					_currentSurfaceId = (mapId >= 25 && mapId <= 27) ? SURFTYPE_ROAD : SURFTYPE_DEFAULT;
 				}
 
-				_currentWall._data = INVALID_CELL;
+				_currentWall = INVALID_CELL;
 				return INVALID_CELL;
 			}
 		}
@@ -1478,16 +1478,16 @@ int Map::getCell(int idx) {
 			++_mazeDataIndex;
 	}
 
-	MazeWallLayers &wallLayers = _mazeData[_mazeDataIndex]._wallData[pt.y][pt.x];
+	int wallData = _mazeData[_mazeDataIndex]._wallData[pt.y][pt.x]._data;
 	if (_isOutdoors) {
 		if (mapId) {
 			// TODO: tile is set to word of (wallLayers >> 8) && 0xff? Makes no sense
-			_currentTile = wallLayers._outdoors._surfaceId;
-			_currentWall = wallLayers;
-			_currentSurfaceId = wallLayers._outdoors._surfaceId;
+			_currentTile = (wallData >> 8) & 0xFF;
+			_currentWall = (wallData >> 4) & 0xF;
+			_currentSurfaceId = wallData & 0xF;
 		} else {
 			_currentSurfaceId = SURFTYPE_DEFAULT;
-			_currentWall._data = 0;
+			_currentWall = 0;
 			_currentTile = 0;
 		}
 	} else {
@@ -1499,11 +1499,11 @@ int Map::getCell(int idx) {
 		else
 			_currentSurfaceId = _mazeData[_mazeDataIndex]._cells[pt.y][pt.x]._surfaceId;
 
-		_currentWall = wallLayers;
-		return (_currentWall._data >> WALL_SHIFTS[dir][idx]) & 0xF;
+		_currentWall = wallData;
+		return (_currentWall >> WALL_SHIFTS[dir][idx]) & 0xF;
 	}
 
-	return _currentWall._data;
+	return _currentWall;
 }
 
 void Map::loadSky() {
diff --git a/engines/xeen/map.h b/engines/xeen/map.h
index 499b451..f878a0d 100644
--- a/engines/xeen/map.h
+++ b/engines/xeen/map.h
@@ -370,7 +370,7 @@ public:
 	bool _currentIsEvent;
 	int _currentSky;
 	int _currentMonsterFlags;
-	MazeWallLayers _currentWall;
+	int _currentWall;
 	int _currentTile;
 	int _currentSurfaceId;
 	bool _currentSteppedOn;
diff --git a/engines/xeen/scripts.cpp b/engines/xeen/scripts.cpp
index 39202c0..ad24985 100644
--- a/engines/xeen/scripts.cpp
+++ b/engines/xeen/scripts.cpp
@@ -322,7 +322,10 @@ void Scripts::cmdTeleport(Common::Array<byte> &params) {
 
 	party._stepped = true;
 	if (mapId != party._mazeId) {
-		switch (map._mobData._objects[intf._objNumber - 1]._spriteId) {
+		int spriteId = (intf._objNumber == 0) ? -1 :
+			map._mobData._objects[intf._objNumber - 1]._spriteId;
+
+		switch (spriteId) {
 		case 47:
 			sound.playFX(45);
 			break;


Commit: 482c2b2ac8cff51d435d20b348e668dd77386af2
    https://github.com/scummvm/scummvm/commit/482c2b2ac8cff51d435d20b348e668dd77386af2
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-01-24T23:53:56-05:00

Commit Message:
XEEN: Fix immediate crash in outdoors rendering

Changed paths:
    engines/xeen/interface_map.cpp



diff --git a/engines/xeen/interface_map.cpp b/engines/xeen/interface_map.cpp
index 43a467d..23b709d 100644
--- a/engines/xeen/interface_map.cpp
+++ b/engines/xeen/interface_map.cpp
@@ -4423,25 +4423,30 @@ void InterfaceMap::drawOutdoors() {
 
 	for (int idx = 0; idx < 9; ++idx) {
 		map.getCell(TERRAIN_INDEXES1[idx]);
-		_outdoorList[36 + idx]._sprites = &map._wallSprites._surfaces[map._currentWall];
+		SpriteResource &spr = map._wallSprites._surfaces[map._currentWall];
+		_outdoorList[36 + idx]._sprites = spr.size() == 0 ? (SpriteResource *)nullptr : &spr;
 	}
 	for (int idx = 0; idx < 5; ++idx) {
 		map.getCell(TERRAIN_INDEXES2[idx]);
-		_outdoorList[61 + idx]._sprites = &map._wallSprites._surfaces[map._currentWall];
+		SpriteResource &spr = map._wallSprites._surfaces[map._currentWall];
+		_outdoorList[61 + idx]._sprites = spr.size() == 0 ? (SpriteResource *)nullptr : &spr;
 	}
 	for (int idx = 0; idx < 3; ++idx) {
 		map.getCell(TERRAIN_INDEXES3[idx]);
-		_outdoorList[84 + idx]._sprites = &map._wallSprites._surfaces[map._currentWall];
+		SpriteResource &spr = map._wallSprites._surfaces[map._currentWall];
+		_outdoorList[84 + idx]._sprites = spr.size() == 0 ? (SpriteResource *)nullptr : &spr;
 	}
 	for (int idx = 0; idx < 5; ++idx) {
 		map.getCell(TERRAIN_INDEXES4[idx]);
-		_outdoorList[103 + idx]._sprites = &map._wallSprites._surfaces[map._currentWall];
+		SpriteResource &spr = map._wallSprites._surfaces[map._currentWall];
+		_outdoorList[103 + idx]._sprites = spr.size() == 0 ? (SpriteResource *)nullptr : &spr;
 	}
 
 	map.getCell(1);
-	_outdoorList[108]._sprites = &map._wallSprites._surfaces[map._currentWall];
-	_outdoorList[109]._sprites = &map._wallSprites._surfaces[map._currentWall];
-	_outdoorList[110]._sprites = &map._wallSprites._surfaces[map._currentWall];
+	SpriteResource &surface = map._wallSprites._surfaces[map._currentWall];
+	_outdoorList[108]._sprites = surface.size() == 0 ? (SpriteResource *)nullptr : &surface;
+	_outdoorList[109]._sprites = _outdoorList[108]._sprites;
+	_outdoorList[110]._sprites = _outdoorList[108]._sprites;
 	_outdoorList._sky1._flags = _outdoorList._sky2._flags = _flipSky ? SPRFLAG_HORIZ_FLIPPED : 0;
 	_outdoorList._groundSprite._flags = _flipWater ? SPRFLAG_HORIZ_FLIPPED : 0;
 


Commit: 3135d1e0a756e2d7927d3ffa1608351252654bd4
    https://github.com/scummvm/scummvm/commit/3135d1e0a756e2d7927d3ffa1608351252654bd4
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-01-25T08:24:18-05:00

Commit Message:
XEEN: Fix rendering in drawOutdoors

Changed paths:
    engines/xeen/interface_map.cpp



diff --git a/engines/xeen/interface_map.cpp b/engines/xeen/interface_map.cpp
index 23b709d..c0f5746 100644
--- a/engines/xeen/interface_map.cpp
+++ b/engines/xeen/interface_map.cpp
@@ -4399,7 +4399,7 @@ void InterfaceMap::drawOutdoors() {
 	for (int cellIndex = 0; cellIndex < 25; ++cellIndex) {
 		map.getCell(cellIndex == 24 ? 2 : DRAW_NUMBERS[cellIndex]);
 
-		DrawStruct &drawStruct = _indoorList._groundTiles[cellIndex];
+		DrawStruct &drawStruct = _outdoorList._groundTiles[cellIndex];
 		SpriteResource &sprites = map._surfaceSprites[map._currentSurfaceId];
 		drawStruct._sprites = sprites.empty() ? (SpriteResource *)nullptr : &sprites;
 


Commit: 7b387dbd89c303c73dd2763a5c05ff0d9d64e4b4
    https://github.com/scummvm/scummvm/commit/7b387dbd89c303c73dd2763a5c05ff0d9d64e4b4
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-01-25T09:01:21-05:00

Commit Message:
XEEN: Fix clearing Please Wait window after changing maps

Changed paths:
    engines/xeen/scripts.cpp
    engines/xeen/scripts.h



diff --git a/engines/xeen/scripts.cpp b/engines/xeen/scripts.cpp
index ad24985..6355c1c 100644
--- a/engines/xeen/scripts.cpp
+++ b/engines/xeen/scripts.cpp
@@ -101,15 +101,17 @@ Scripts::Scripts(XeenEngine *vm) : _vm(vm) {
 	_animCounter = 0;
 	_eventSkipped = false;
 	_mirrorId = -1;
+	_refreshIcons = false;
 }
 
 void Scripts::checkEvents() {
 	Combat &combat = *_vm->_combat;
-//	Interface &intf = *_vm->_interface;
+	Interface &intf = *_vm->_interface;
 	Map &map = *_vm->_map;
 	Party &party = *_vm->_party;
+	Screen &screen = *_vm->_screen;
 
-//	int var18 = 0;
+	_refreshIcons = false;
 	_itemType = 0;
 	_var4F = 0;
 	bool var50 = false;
@@ -163,6 +165,12 @@ void Scripts::checkEvents() {
 		}
 	} while (!_vm->shouldQuit() && _lineNum != -1);
 
+	intf._face1State = intf._face2State = 2;
+	if (_refreshIcons) {
+		screen.closeWindows();
+		intf.charIconsPrint(true);
+	}
+
 	// TODO
 }
 
@@ -669,6 +677,7 @@ void Scripts::cmdReturn(Common::Array<byte> &params) {
 void Scripts::cmdSetVar(Common::Array<byte> &params) { 
 	Party &party = *_vm->_party;
 	uint val;
+	_refreshIcons = true;
 
 	switch (params[0]) {
 	case 25:
diff --git a/engines/xeen/scripts.h b/engines/xeen/scripts.h
index c0168e2..72ddfbc 100644
--- a/engines/xeen/scripts.h
+++ b/engines/xeen/scripts.h
@@ -147,6 +147,7 @@ private:
 	int _lineNum;
 	int _charIndex;
 	int _mirrorId;
+	int _refreshIcons;
 
 	int _v2;
 	int _var4F;


Commit: ef283252b36b361e3775d07e8f9fe887af1ab9ba
    https://github.com/scummvm/scummvm/commit/ef283252b36b361e3775d07e8f9fe887af1ab9ba
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-01-25T11:18:00-05:00

Commit Message:
XEEN: Fix keyboard keys in YesNo dialog

Changed paths:
    engines/xeen/dialogs_yesno.cpp



diff --git a/engines/xeen/dialogs_yesno.cpp b/engines/xeen/dialogs_yesno.cpp
index 6f74d86..940f5b6 100644
--- a/engines/xeen/dialogs_yesno.cpp
+++ b/engines/xeen/dialogs_yesno.cpp
@@ -53,8 +53,8 @@ bool YesNo::execute(bool type, int v2) {
 		confirmSprites.draw(screen, 2, Common::Point(260, 75));
 		screen._windows[34].update();
 
-		addButton(Common::Rect(235, 75, 259, 95), 'Y', &confirmSprites);
-		addButton(Common::Rect(260, 75, 284, 95), 'N', &confirmSprites);
+		addButton(Common::Rect(235, 75, 259, 95), Common::KEYCODE_y, &confirmSprites);
+		addButton(Common::Rect(260, 75, 284, 95), Common::KEYCODE_n, &confirmSprites);
 
 		intf._face1State = map._headData[party._mazePosition.y][party._mazePosition.x]._left;
 		intf._face2State = map._headData[party._mazePosition.y][party._mazePosition.x]._right;
@@ -76,10 +76,10 @@ bool YesNo::execute(bool type, int v2) {
 		if (!_buttonValue)
 			continue;
 
-		if (type || _buttonValue == 'Y') {
+		if (type || _buttonValue == Common::KEYCODE_y) {
 			result = true;
 			break;
-		} else if (_buttonValue == 'N' || _buttonValue == Common::KEYCODE_ESCAPE)
+		} else if (_buttonValue == Common::KEYCODE_n || _buttonValue == Common::KEYCODE_ESCAPE)
 			break;
 	}
 


Commit: 50d3d79d7ff415be7210cc251d29716634a6292d
    https://github.com/scummvm/scummvm/commit/50d3d79d7ff415be7210cc251d29716634a6292d
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-01-25T12:06:23-05:00

Commit Message:
XEEN: Revert window restriction, since all window draws use absolute x,y

Changed paths:
    engines/xeen/screen.cpp



diff --git a/engines/xeen/screen.cpp b/engines/xeen/screen.cpp
index 4eabc2b..5088829 100644
--- a/engines/xeen/screen.cpp
+++ b/engines/xeen/screen.cpp
@@ -38,7 +38,7 @@ Window::Window(XeenEngine *vm, const Common::Rect &bounds, int a, int border,
 		_vm(vm), _enabled(false), _a(a), _border(border), 
 		_xLo(xLo), _ycL(ycL), _xHi(xHi), _ycH(ycH) {
 	setBounds(bounds);
-	create(_vm->_screen, bounds);
+	create(_vm->_screen, Common::Rect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT));
 }
 
 void Window::setBounds(const Common::Rect &r) {


Commit: 94ce2c1e6f46a858725dfab2c587f5069acdef8b
    https://github.com/scummvm/scummvm/commit/94ce2c1e6f46a858725dfab2c587f5069acdef8b
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-01-25T19:32:57-05:00

Commit Message:
XEEN: Fix display of outdoors objects

Changed paths:
    engines/xeen/interface_map.cpp



diff --git a/engines/xeen/interface_map.cpp b/engines/xeen/interface_map.cpp
index c0f5746..107f9ec 100644
--- a/engines/xeen/interface_map.cpp
+++ b/engines/xeen/interface_map.cpp
@@ -3384,6 +3384,7 @@ void InterfaceMap::setOutdoorsObjects() {
 			DrawStruct &ds = _outdoorList[111];
 			ds._x = OUTDOOR_OBJECT_X[posIndex][0];
 			ds._y = MAP_OBJECT_Y[posIndex][0];
+			ds._frame = obj._frame;
 			ds._sprites = obj._sprites;
 
 			ds._flags &= ~SPRFLAG_HORIZ_FLIPPED;
@@ -3398,6 +3399,7 @@ void InterfaceMap::setOutdoorsObjects() {
 			DrawStruct &ds = _outdoorList[87];
 			ds._x = OUTDOOR_OBJECT_X[posIndex][1];
 			ds._y = MAP_OBJECT_Y[posIndex][1];
+			ds._frame = obj._frame;
 			ds._sprites = obj._sprites;
 
 			ds._flags &= ~SPRFLAG_HORIZ_FLIPPED;
@@ -3411,6 +3413,7 @@ void InterfaceMap::setOutdoorsObjects() {
 			DrawStruct &ds = _outdoorList[88];
 			ds._x = OUTDOOR_OBJECT_X[posIndex][2];
 			ds._y = MAP_OBJECT_Y[posIndex][2];
+			ds._frame = obj._frame;
 			ds._sprites = obj._sprites;
 
 			ds._flags &= ~SPRFLAG_HORIZ_FLIPPED;
@@ -3424,6 +3427,7 @@ void InterfaceMap::setOutdoorsObjects() {
 			DrawStruct &ds = _outdoorList[89];
 			ds._x = OUTDOOR_OBJECT_X[posIndex][3];
 			ds._y = MAP_OBJECT_Y[posIndex][3];
+			ds._frame = obj._frame;
 			ds._sprites = obj._sprites;
 
 			ds._flags &= ~SPRFLAG_HORIZ_FLIPPED;
@@ -3437,6 +3441,7 @@ void InterfaceMap::setOutdoorsObjects() {
 			DrawStruct &ds = _outdoorList[66];
 			ds._x = OUTDOOR_OBJECT_X[posIndex][4];
 			ds._y = MAP_OBJECT_Y[posIndex][4];
+			ds._frame = obj._frame;
 			ds._sprites = obj._sprites;
 
 			ds._flags &= ~SPRFLAG_HORIZ_FLIPPED;
@@ -3450,6 +3455,7 @@ void InterfaceMap::setOutdoorsObjects() {
 			DrawStruct &ds = _outdoorList[67];
 			ds._x = OUTDOOR_OBJECT_X[posIndex][5];
 			ds._y = MAP_OBJECT_Y[posIndex][5];
+			ds._frame = obj._frame;
 			ds._sprites = obj._sprites;
 
 			ds._flags &= ~SPRFLAG_HORIZ_FLIPPED;
@@ -3463,6 +3469,7 @@ void InterfaceMap::setOutdoorsObjects() {
 			DrawStruct &ds = _outdoorList[68];
 			ds._x = OUTDOOR_OBJECT_X[posIndex][6];
 			ds._y = MAP_OBJECT_Y[posIndex][6];
+			ds._frame = obj._frame;
 			ds._sprites = obj._sprites;
 
 			ds._flags &= ~SPRFLAG_HORIZ_FLIPPED;
@@ -3476,6 +3483,7 @@ void InterfaceMap::setOutdoorsObjects() {
 			DrawStruct &ds = _outdoorList[37];
 			ds._x = OUTDOOR_OBJECT_X[posIndex][7];
 			ds._y = MAP_OBJECT_Y[posIndex][7];
+			ds._frame = obj._frame;
 			ds._sprites = obj._sprites;
 
 			ds._flags &= ~SPRFLAG_HORIZ_FLIPPED;
@@ -3489,6 +3497,7 @@ void InterfaceMap::setOutdoorsObjects() {
 			DrawStruct &ds = _outdoorList[38];
 			ds._x = OUTDOOR_OBJECT_X[posIndex][8];
 			ds._y = MAP_OBJECT_Y[posIndex][8];
+			ds._frame = obj._frame;
 			ds._sprites = obj._sprites;
 
 			ds._flags &= ~SPRFLAG_HORIZ_FLIPPED;
@@ -3502,6 +3511,7 @@ void InterfaceMap::setOutdoorsObjects() {
 			DrawStruct &ds = _outdoorList[40];
 			ds._x = OUTDOOR_OBJECT_X[posIndex][10];
 			ds._y = MAP_OBJECT_Y[posIndex][10];
+			ds._frame = obj._frame;
 			ds._sprites = obj._sprites;
 
 			ds._flags &= ~SPRFLAG_HORIZ_FLIPPED;
@@ -3515,6 +3525,7 @@ void InterfaceMap::setOutdoorsObjects() {
 			DrawStruct &ds = _outdoorList[39];
 			ds._x = OUTDOOR_OBJECT_X[posIndex][9];
 			ds._y = MAP_OBJECT_Y[posIndex][9];
+			ds._frame = obj._frame;
 			ds._sprites = obj._sprites;
 
 			ds._flags &= ~SPRFLAG_HORIZ_FLIPPED;
@@ -3528,6 +3539,7 @@ void InterfaceMap::setOutdoorsObjects() {
 			DrawStruct &ds = _outdoorList[41];
 			ds._x = OUTDOOR_OBJECT_X[posIndex][11];
 			ds._y = MAP_OBJECT_Y[posIndex][11];
+			ds._frame = obj._frame;
 			ds._sprites = obj._sprites;
 
 			ds._flags &= ~SPRFLAG_HORIZ_FLIPPED;
@@ -4421,10 +4433,11 @@ void InterfaceMap::drawOutdoors() {
 	const int TERRAIN_INDEXES3[3] = { 11, 16, 13 };
 	const int TERRAIN_INDEXES4[5] = { 5, 9, 7, 0, 4 };
 
+	// Loops to set draw entries for the terrain
 	for (int idx = 0; idx < 9; ++idx) {
 		map.getCell(TERRAIN_INDEXES1[idx]);
 		SpriteResource &spr = map._wallSprites._surfaces[map._currentWall];
-		_outdoorList[36 + idx]._sprites = spr.size() == 0 ? (SpriteResource *)nullptr : &spr;
+		_outdoorList[28 + idx]._sprites = spr.size() == 0 ? (SpriteResource *)nullptr : &spr;
 	}
 	for (int idx = 0; idx < 5; ++idx) {
 		map.getCell(TERRAIN_INDEXES2[idx]);


Commit: 84741d73a09f45232b0dccd26df5b05eb6c80476
    https://github.com/scummvm/scummvm/commit/84741d73a09f45232b0dccd26df5b05eb6c80476
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-01-25T20:05:35-05:00

Commit Message:
XEEN: Properly clear previous MazeData when loading a new map

Changed paths:
    engines/xeen/map.cpp
    engines/xeen/map.h



diff --git a/engines/xeen/map.cpp b/engines/xeen/map.cpp
index 52dc427..51e87ef 100644
--- a/engines/xeen/map.cpp
+++ b/engines/xeen/map.cpp
@@ -491,6 +491,10 @@ void MonsterData::synchronize(Common::SeekableReadStream &s) {
 /*------------------------------------------------------------------------*/
 
 SurroundingMazes::SurroundingMazes() {
+	clear();
+}
+
+void SurroundingMazes::clear() {
 	_north = 0;
 	_east = 0;
 	_south = 0;
@@ -541,6 +545,10 @@ void MazeDifficulties::synchronize(Common::SeekableReadStream &s) {
 /*------------------------------------------------------------------------*/
 
 MazeData::MazeData() {
+	clear();
+}
+
+void MazeData::clear() {
 	for (int y = 0; y < MAP_HEIGHT; ++y) {
 		for (int x = 0; x < MAP_WIDTH; ++x)
 			_wallData[y][x]._data = 0;
@@ -550,6 +558,7 @@ MazeData::MazeData() {
 		_surfaceTypes[y] = 0;
 	}
 	_mazeNumber = 0;
+	_surroundingMazes.clear();
 	_mazeFlags = _mazeFlags2  = 0;
 	_floorType = 0;
 	_trapDamage = 0;
@@ -963,7 +972,9 @@ void Map::load(int mapId) {
 	for (int idx = 0; idx < 9; ++idx, ++mazeDataP) {
 		mazeDataP->_mazeId = mapId;
 
-		if (mapId != 0) {
+		if (mapId == 0) {
+			mazeDataP->clear();
+		} else {
 			// Load in the maze's data file
 			Common::String datName = Common::String::format("maze%c%03d.dat",
 				(mapId >= 100) ? 'x' : '0', mapId);
diff --git a/engines/xeen/map.h b/engines/xeen/map.h
index f878a0d..7d268ef 100644
--- a/engines/xeen/map.h
+++ b/engines/xeen/map.h
@@ -112,6 +112,8 @@ public:
 public:
 	SurroundingMazes();
 
+	void clear();
+
 	void synchronize(Common::SeekableReadStream &s);
 
 	int &operator[](int idx);
@@ -199,6 +201,8 @@ public:
 public:
 	MazeData();
 
+	void clear();
+
 	void synchronize(Common::SeekableReadStream &s);
 
 	void setAllTilesStepped();


Commit: 2abce62b8fd1b29d2c351ca7502f21010882674f
    https://github.com/scummvm/scummvm/commit/2abce62b8fd1b29d2c351ca7502f21010882674f
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-01-25T21:19:59-05:00

Commit Message:
XEEN: Add skeleton for spells class

Changed paths:
  A engines/xeen/spells.cpp
  A engines/xeen/spells.h
    engines/xeen/module.mk
    engines/xeen/resources.cpp
    engines/xeen/resources.h
    engines/xeen/scripts.cpp
    engines/xeen/scripts.h
    engines/xeen/xeen.cpp
    engines/xeen/xeen.h



diff --git a/engines/xeen/module.mk b/engines/xeen/module.mk
index ea6ea8c..c534844 100644
--- a/engines/xeen/module.mk
+++ b/engines/xeen/module.mk
@@ -26,6 +26,7 @@ MODULE_OBJS := \
 	screen.o \
 	scripts.o \
 	sound.o \
+	spells.o \
 	sprites.o \
 	xeen.o \
 	xsurface.o
diff --git a/engines/xeen/resources.cpp b/engines/xeen/resources.cpp
index 26c33ca..0f48073 100644
--- a/engines/xeen/resources.cpp
+++ b/engines/xeen/resources.cpp
@@ -75,6 +75,8 @@ const char *const WHATS_THE_PASSWORD = "What's the Password?";
 
 const char *const IN_NO_CONDITION = "\x0B""007%s is not in any condition to perform actions!";
 
+const char *const NOTHING_HERE = "\x03""c\x0B""010Nothing here.";
+
 const char *const TERRAIN_TYPES[6] = {
 	"town", "cave", "towr", "cstl", "dung", "scfi"
 };
diff --git a/engines/xeen/resources.h b/engines/xeen/resources.h
index 2e77e95..8537835 100644
--- a/engines/xeen/resources.h
+++ b/engines/xeen/resources.h
@@ -40,6 +40,8 @@ extern const char *const WHATS_THE_PASSWORD;
 
 extern const char *const IN_NO_CONDITION;
 
+extern const char *const NOTHING_HERE;
+
 extern const char *const TERRAIN_TYPES[6];
 
 extern const char *const SURFACE_TYPE_NAMES[15];
diff --git a/engines/xeen/scripts.cpp b/engines/xeen/scripts.cpp
index 6355c1c..665fd0d 100644
--- a/engines/xeen/scripts.cpp
+++ b/engines/xeen/scripts.cpp
@@ -96,25 +96,30 @@ Scripts::Scripts(XeenEngine *vm) : _vm(vm) {
 	_treasureGems = 0;
 	_lineNum = 0;
 	_charIndex = 0;
-	_v2 = 0;
+	_v2 = false;
 	_nEdamageType = 0;
 	_animCounter = 0;
 	_eventSkipped = false;
 	_mirrorId = -1;
 	_refreshIcons = false;
+	_scriptResult = false;
+	_scriptExecuted = false;
+	_var50 = false;
 }
 
-void Scripts::checkEvents() {
+bool Scripts::checkEvents() {
 	Combat &combat = *_vm->_combat;
+	EventsManager &events = *_vm->_events;
 	Interface &intf = *_vm->_interface;
 	Map &map = *_vm->_map;
 	Party &party = *_vm->_party;
 	Screen &screen = *_vm->_screen;
+	SoundManager &sound = *_vm->_sound;
 
 	_refreshIcons = false;
 	_itemType = 0;
-	_var4F = 0;
-	bool var50 = false;
+	_scriptExecuted = false;
+	_var50 = false;
 	_whoWill = 0;
 	Mode oldMode = _vm->_mode;
 	Common::fill(&_charFX[0], &_charFX[MAX_ACTIVE_PARTY], 0);
@@ -128,12 +133,12 @@ void Scripts::checkEvents() {
 
 	do {
 		_lineNum = 0;
-//		int varA = 0;
+		_scriptResult = false;
 		_animCounter = 0;
 //		int var4E = 0;
 		_currentPos = party._mazePosition;
 		_charIndex = 1;
-		_v2 = 1;
+		_v2 = true;
 		_nEdamageType = 0;
 //		int var40 = -1;
 
@@ -156,7 +161,7 @@ void Scripts::checkEvents() {
 						doOpcode(event);
 						break;
 					} else {
-						var50 = true;
+						_var50 = true;
 					}
 				}
 			}
@@ -172,6 +177,35 @@ void Scripts::checkEvents() {
 	}
 
 	// TODO
+
+	_animCounter = 0;
+	_vm->_mode = oldMode;
+	screen.closeWindows();
+
+	if (_scriptExecuted || !intf._objNumber || _var50) {
+		if (_var50 && !_scriptExecuted && intf._objNumber && !map._currentIsEvent) {
+			sound.playFX(21);
+		}
+	} else {
+		Window &w = screen._windows[38];
+		w.open();
+		w.writeString(NOTHING_HERE);
+		w.update();
+
+		do {
+			intf.draw3d(true);
+			events.updateGameCounter();
+			events.wait(1, true);
+		} while (!events.isKeyMousePressed());
+		events.clearEvents();
+
+		w.close();
+	}
+
+	_v2 = true;
+	Common::fill(&_charFX[0], &_charFX[6], 0);
+
+	return _scriptResult;
 }
 
 void Scripts::giveTreasure() {
@@ -231,7 +265,6 @@ void Scripts::cmdDisplay1(Common::Array<byte> &params) {
 	screen._windows[38].writeString(msg);
 	screen._windows[38].update();
 
-	_var4F = true;
 	cmdNoAction(params);
 }
 
@@ -247,7 +280,6 @@ void Scripts::cmdDoorTextSml(Common::Array<byte> &params) {
 	intf._upDoorText = true;
 	intf.draw3d(true);
 
-	_var4F = true;
 	cmdNoAction(params);
 }
 
@@ -263,7 +295,6 @@ void Scripts::cmdDoorTextLrg(Common::Array<byte> &params) {
 	intf._upDoorText = true;
 	intf.draw3d(true);
 
-	_var4F = true;
 	cmdNoAction(params);
 }
 
@@ -279,7 +310,6 @@ void Scripts::cmdSignText(Common::Array<byte> &params) {
 	intf._upDoorText = true;
 	intf.draw3d(true);
 
-	_var4F = true;
 	cmdNoAction(params);
 }
 
@@ -293,7 +323,6 @@ void Scripts::cmdNPC(Common::Array<byte> &params) {
 void Scripts::cmdPlayFX(Common::Array<byte> &params) {
 	_vm->_sound->playFX(params[0]);
 
-	_var4F = true;
 	cmdNoAction(params);
 }
 
@@ -306,7 +335,6 @@ void Scripts::cmdTeleport(Common::Array<byte> &params) {
 	SoundManager &sound = *_vm->_sound;
 
 	screen.closeWindows();
-	_var4F = true;
 
 	int mapId;
 	Common::Point pt;
@@ -407,7 +435,6 @@ void Scripts::cmdIf(Common::Array<byte> &params) {
 	if (result)
 		_lineNum = newLineNum - 1;
 
-	_var4F = true;
 	cmdNoAction(params);
 }
 
@@ -463,7 +490,7 @@ void Scripts::cmdSetChar(Common::Array<byte> &params) {
 		_charIndex = _vm->getRandomNumber(1, _vm->_party->_partyCount);
 	}
 
-	_v2 = 1;
+	_v2 = true;
 	cmdNoAction(params);
 }
 
@@ -484,11 +511,15 @@ void Scripts::cmdSpawn(Common::Array<byte> &params) {
 	monster._isAttacking = params[1] != 0;
 	monster._hp = monsterData._hp;
 
-	_var4F = 1;
 	cmdNoAction(params);
 }
 
-void Scripts::cmdDoTownEvent(Common::Array<byte> &params) { error("TODO"); }
+void Scripts::cmdDoTownEvent(Common::Array<byte> &params) {
+	_scriptResult = doTownEvent(params[0]);
+	_vm->_party->_stepped = true;
+	
+	cmdExit(params);
+}
 
 /**
  * Stop executing the script
@@ -510,7 +541,6 @@ void Scripts::cmdAlterMap(Common::Array<byte> &params) {
 		map.setWall(Common::Point(params[0], params[1]), (Direction)params[2], params[3]);
 	}
 
-	_var4F = true;
 	cmdNoAction(params);
 }
 
@@ -554,7 +584,6 @@ void Scripts::cmdGiveExtended(Common::Array<byte> &params) {
 	if (result)
 		_lineNum = newLineNum - 1;
 
-	_var4F = true;
 	cmdNoAction(params);
 }
 
@@ -610,7 +639,6 @@ void Scripts::cmdConfirmWord(Common::Array<byte> &params) {
 		}
 	}
 
-	_var4F = true;
 	cmdNoAction(params);
 }
 
@@ -624,7 +652,6 @@ void Scripts::cmdJumpRnd(Common::Array<byte> &params) {
 	if (v == params[1])
 		_lineNum = params[2] - 1;
 
-	_var4F = true;
 	cmdNoAction(params);
 }
 
@@ -644,7 +671,6 @@ void Scripts::cmdAlterEvent(Common::Array<byte> &params) {
 		}
 	}
 
-	_var4F = true;
 	cmdNoAction(params);
 }
 
@@ -657,7 +683,6 @@ void Scripts::cmdCallEvent(Common::Array<byte> &params) {
 	_currentPos = Common::Point(params[0], params[1]);
 	_lineNum = params[2] - 1;
 
-	_var4F = true;
 	cmdNoAction(params);
 }
 
@@ -670,7 +695,6 @@ void Scripts::cmdReturn(Common::Array<byte> &params) {
 	_currentPos = se;
 	_lineNum = se.line;
 
-	_var4F = true;
 	cmdNoAction(params);
 }
 
@@ -707,7 +731,6 @@ void Scripts::cmdSetVar(Common::Array<byte> &params) {
 		}
 	}
 
-	_var4F = true;
 	cmdNoAction(params);
 }
 
@@ -716,7 +739,6 @@ void Scripts::cmdCutsceneEndClouds(Common::Array<byte> &params) { error("TODO");
 void Scripts::cmdWhoWill(Common::Array<byte> &params) { 
 	_charIndex = WhoWill::show(_vm, params[0], params[1], true);
 
-	_var4F = true;
 	if (_charIndex == 0)
 		cmdExit(params);
 	else
@@ -751,7 +773,6 @@ void Scripts::cmdMakeNothingHere(Common::Array<byte> &params) {
 			evt._opcode = OP_None;
 	}
 
-	_var4F = true;
 	cmdExit(params);
 }
 
@@ -777,7 +798,6 @@ void Scripts::cmdExchObj(Common::Array<byte> &params) {
 	obj1._position = obj2._position;
 	obj2._position = pt;
 
-	_var4F = true;
 	cmdNoAction(params);
 }
 
@@ -787,7 +807,6 @@ void Scripts::cmdFallToMap(Common::Array<byte> &params) {
 	party._fallPosition = Common::Point(params[1], params[2]);
 	party._fallDamage = params[3];
 
-	_var4F = true;
 	_lineNum = -1;
 }
 
@@ -806,7 +825,6 @@ void Scripts::cmdGoto(Common::Array<byte> &params) {
 	if (params[0] == map._currentSurfaceId)
 		_lineNum = params[1] - 1;
 
-	_var4F = true;
 	cmdNoAction(params);
 }
 
@@ -815,7 +833,6 @@ void Scripts::cmdGoto(Common::Array<byte> &params) {
  */
 void Scripts::cmdGotoRandom(Common::Array<byte> &params) { 
 	_lineNum = params[_vm->getRandomNumber(1, params[0])] - 1;
-	_var4F = true;
 	cmdNoAction(params);
 }
 
@@ -1254,6 +1271,15 @@ bool Scripts::ifProc(int action, uint32 mask, int mode, int charIndex) {
 	}
 }
 
+bool Scripts::doTownEvent(int actionId) {
+	if (actionId == 12)
+		return false;
+
+
+
+	return false;
+}
+
 bool Scripts::copyProtectionCheck() {
 	// Currentl not implemented
 	return true;
diff --git a/engines/xeen/scripts.h b/engines/xeen/scripts.h
index 72ddfbc..44290ee 100644
--- a/engines/xeen/scripts.h
+++ b/engines/xeen/scripts.h
@@ -148,9 +148,10 @@ private:
 	int _charIndex;
 	int _mirrorId;
 	int _refreshIcons;
-
-	int _v2;
-	int _var4F;
+	int _scriptResult;
+	bool _v2;
+	bool _scriptExecuted;
+	bool _var50;
 	MazeEvent *_event;
 	Common::Point _currentPos;
 	Common::Stack<StackEntry> _stack;
@@ -222,6 +223,8 @@ private:
 
 	bool ifProc(int action, uint32 mask, int mode, int charIndex);
 
+	bool doTownEvent(int actionId);
+
 	bool copyProtectionCheck();
 public:
 	int _animCounter;
@@ -232,7 +235,7 @@ public:
 public:
 	Scripts(XeenEngine *vm);
 
-	void checkEvents();
+	bool checkEvents();
 
 	void giveTreasure();
 
diff --git a/engines/xeen/spells.cpp b/engines/xeen/spells.cpp
new file mode 100644
index 0000000..8a5126c
--- /dev/null
+++ b/engines/xeen/spells.cpp
@@ -0,0 +1,40 @@
+/* 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 "xeen/spells.h"
+#include "xeen/files.h"
+#include "xeen/xeen.h"
+
+namespace Xeen {
+
+Spells::Spells(XeenEngine *vm) : _vm(vm) {
+	load();
+}
+
+void Spells::load() {
+	File f("spells.xen");
+	while (f.pos() < f.size())
+		_spellNames.push_back(f.readString());
+	f.close();
+}
+
+} // End of namespace Xeen
diff --git a/engines/xeen/spells.h b/engines/xeen/spells.h
new file mode 100644
index 0000000..adb957c
--- /dev/null
+++ b/engines/xeen/spells.h
@@ -0,0 +1,46 @@
+/* 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_SPELLS_H
+#define XEEN_SPELLS_H
+
+#include "common/scummsys.h"
+#include "common/str-array.h"
+
+namespace Xeen {
+
+class XeenEngine;
+
+class Spells {
+private:
+	XeenEngine *_vm;
+
+	void load();
+public:
+	Common::StringArray _spellNames;
+public:
+	Spells(XeenEngine *vm);
+};
+
+} // End of namespace Xeen
+
+#endif /* XEEN_SPELLS_H */
diff --git a/engines/xeen/xeen.cpp b/engines/xeen/xeen.cpp
index 8489f86..8879b15 100644
--- a/engines/xeen/xeen.cpp
+++ b/engines/xeen/xeen.cpp
@@ -47,6 +47,7 @@ XeenEngine::XeenEngine(OSystem *syst, const XeenGameDescription *gameDesc)
 	_screen = nullptr;
 	_scripts = nullptr;
 	_sound = nullptr;
+	_spells = nullptr;
 	_eventData = nullptr;
 	_dangerSenseAllowed = false;
 	_noDirectionSense = false;
@@ -67,6 +68,7 @@ XeenEngine::~XeenEngine() {
 	delete _screen;
 	delete _scripts;
 	delete _sound;
+	delete _spells;
 	delete _eventData;
 	delete _files;
 }
@@ -91,6 +93,7 @@ void XeenEngine::initialize() {
 	_scripts = new Scripts(this);
 	_screen->setupWindows();
 	_sound = new SoundManager(this);
+	_spells = new Spells(this);
 
 	File f("029.obj");
 	_eventData = f.readStream(f.size());
diff --git a/engines/xeen/xeen.h b/engines/xeen/xeen.h
index b60908d..38c7beb 100644
--- a/engines/xeen/xeen.h
+++ b/engines/xeen/xeen.h
@@ -43,6 +43,7 @@
 #include "xeen/screen.h"
 #include "xeen/scripts.h"
 #include "xeen/sound.h"
+#include "xeen/spells.h"
 
 /**
  * This is the namespace of the Xeen engine.
@@ -140,6 +141,7 @@ public:
 	Screen *_screen;
 	Scripts *_scripts;
 	SoundManager *_sound;
+	Spells *_spells;
 	Treasure _treasure;
 	Mode _mode;
 	GameEvent _gameEvent;


Commit: f11e11006b5cbe7d9bcd547f98ab2b4dba358764
    https://github.com/scummvm/scummvm/commit/f11e11006b5cbe7d9bcd547f98ab2b4dba358764
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-01-25T23:59:16-05:00

Commit Message:
XEEN: Beginnings of Town class, implemented handleAction

Changed paths:
  A engines/xeen/town.cpp
  A engines/xeen/town.h
    engines/xeen/interface.cpp
    engines/xeen/interface.h
    engines/xeen/interface_map.cpp
    engines/xeen/interface_map.h
    engines/xeen/module.mk
    engines/xeen/resources.cpp
    engines/xeen/resources.h
    engines/xeen/scripts.cpp
    engines/xeen/scripts.h
    engines/xeen/sound.h
    engines/xeen/spells.cpp
    engines/xeen/spells.h
    engines/xeen/xeen.cpp
    engines/xeen/xeen.h



diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp
index f85e19d..0126cd6 100644
--- a/engines/xeen/interface.cpp
+++ b/engines/xeen/interface.cpp
@@ -780,6 +780,14 @@ void Interface::doFalling() {
 	// TODO
 }
 
+void Interface::highlightChar(int charId) {
+	error("TODO: highlightChar");
+}
+
+void Interface::unhighlightChar() {
+	error("TODO: unhighlight");
+}
+
 bool Interface::checkMoveDirection(int key) {
 	Map &map = *_vm->_map;
 	Party &party = *_vm->_party;
diff --git a/engines/xeen/interface.h b/engines/xeen/interface.h
index 3d8116d..ab30654 100644
--- a/engines/xeen/interface.h
+++ b/engines/xeen/interface.h
@@ -99,6 +99,10 @@ public:
 
 	void doFalling();
 
+	void highlightChar(int charId);
+
+	void unhighlightChar();
+
 	void perform();
 };
 
diff --git a/engines/xeen/interface_map.cpp b/engines/xeen/interface_map.cpp
index 107f9ec..c9ea258 100644
--- a/engines/xeen/interface_map.cpp
+++ b/engines/xeen/interface_map.cpp
@@ -4964,7 +4964,7 @@ void InterfaceMap::drawMiniMap() {
 	party._wizardEyeActive = eyeActive;
 }
 
-void InterfaceMap::drawTownAnim(int v) {
+void InterfaceMap::drawTownAnim(bool v) {
 	warning("TODO");
 }
 
diff --git a/engines/xeen/interface_map.h b/engines/xeen/interface_map.h
index 3ee2c43..153abba 100644
--- a/engines/xeen/interface_map.h
+++ b/engines/xeen/interface_map.h
@@ -114,18 +114,12 @@ protected:
 	bool _charsShooting;
 	bool _thinWall;
 	bool _isAnimReset;
-	int _batUIFrame;
-	int _spotDoorsUIFrame;
-	int _dangerSenseUIFrame;
-	int _face1UIFrame;
-	int _face2UIFrame;
 	int _blessedUIFrame;
 	int _powerShieldUIFrame;
 	int _holyBonusUIFrame;
 	int _heroismUIFrame;
 	int _flipUIFrame;
 	bool _flag1;
-	int _overallFrame;
 
 	void setMazeBits();
 
@@ -135,8 +129,6 @@ protected:
 
 	void drawMiniMap();
 
-	void assembleBorder();
-
 	virtual void setup();
 public:
 	OutdoorDrawList _outdoorList;
@@ -144,10 +136,14 @@ public:
 	SpriteResource _globalSprites;
 	bool _upDoorText;
 	Common::String _screenText;
-	int _face1State;
-	int _face2State;
+	int _face1State, _face2State;
+	int _face1UIFrame, _face2UIFrame;
+	int _spotDoorsUIFrame;
+	int _dangerSenseUIFrame;
 	byte _tillMove;
 	int _objNumber;
+	int _overallFrame;
+	int _batUIFrame;
 public:
 	InterfaceMap(XeenEngine *vm);
 
@@ -169,7 +165,9 @@ public:
 
 	void drawOutdoors();
 
-	void drawTownAnim(int v);
+	void drawTownAnim(bool v);
+
+	void assembleBorder();
 };
 
 } // End of namespace Xeen
diff --git a/engines/xeen/module.mk b/engines/xeen/module.mk
index c534844..c9ea03f 100644
--- a/engines/xeen/module.mk
+++ b/engines/xeen/module.mk
@@ -28,6 +28,7 @@ MODULE_OBJS := \
 	sound.o \
 	spells.o \
 	sprites.o \
+	town.o \
 	xeen.o \
 	xsurface.o
 
diff --git a/engines/xeen/resources.cpp b/engines/xeen/resources.cpp
index 0f48073..9e11a17 100644
--- a/engines/xeen/resources.cpp
+++ b/engines/xeen/resources.cpp
@@ -68,7 +68,7 @@ const char *const OPTIONS_TITLE =
 
 const char *const THE_PARTY_NEEDS_REST = "\x0B""012The Party needs rest!";
 
-const char *const WHO_WILL = "\X03""c\X0B""000\x09""000%s\x0A\x0A"
+const char *const WHO_WILL = "\x03""c\x0B""000\x09""000%s\x0A\x0A"
 	"Who will\x0A%s?\x0A\x0B""055F1 - F%d";
 
 const char *const WHATS_THE_PASSWORD = "What's the Password?";
@@ -566,4 +566,23 @@ const int OUTDOOR_DRAWSTRCT_INDEXES[44] = {
 	93, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120
 };
 
+const int TOWN_MAXES[2][11] = {
+	{ 23, 13, 32, 16, 26, 16, 16, 16, 16, 16, 16 },
+	{ 26, 19, 48, 27, 26, 37, 16, 16, 16, 16, 16 }
+};
+
+const char *const TOWN_ACTION_MUSIC[14] = {
+	"bank.m", "smith.m", "guild.m", "tavern.m", "temple.m",
+	"grounds.m", "endgame.m", "bank.m", "sf09.m", "guild.m",
+	"tavern.m", "temple.m", "smith.m", "endgame.m"
+};
+
+const char *const TOWN_ACTION_SHAPES[4] = {
+	"bankr", "blck", "gild", "tvrn"
+};
+
+const int TOWN_ACTION_FILES[2][7] = {
+	{ 3, 2, 4, 2, 4, 2, 1 }, { 5, 3, 7, 5, 4, 6, 1 }
+};
+
 } // End of namespace Xeen
diff --git a/engines/xeen/resources.h b/engines/xeen/resources.h
index 8537835..ff19202 100644
--- a/engines/xeen/resources.h
+++ b/engines/xeen/resources.h
@@ -150,6 +150,14 @@ extern const int ARMOR_STRENGTHS[14];
 
 extern const int OUTDOOR_DRAWSTRCT_INDEXES[44];
 
+extern const int TOWN_MAXES[2][11];
+
+extern const char *const TOWN_ACTION_MUSIC[14];
+
+extern const char *const TOWN_ACTION_SHAPES[4];
+
+extern const int TOWN_ACTION_FILES[2][7];
+
 } // End of namespace Xeen
 
 #endif	/* XEEN_RESOURCES_H */
diff --git a/engines/xeen/scripts.cpp b/engines/xeen/scripts.cpp
index 665fd0d..0972165 100644
--- a/engines/xeen/scripts.cpp
+++ b/engines/xeen/scripts.cpp
@@ -96,7 +96,7 @@ Scripts::Scripts(XeenEngine *vm) : _vm(vm) {
 	_treasureGems = 0;
 	_lineNum = 0;
 	_charIndex = 0;
-	_v2 = false;
+	_v2 = 0;
 	_nEdamageType = 0;
 	_animCounter = 0;
 	_eventSkipped = false;
@@ -123,7 +123,7 @@ bool Scripts::checkEvents() {
 	_whoWill = 0;
 	Mode oldMode = _vm->_mode;
 	Common::fill(&_charFX[0], &_charFX[MAX_ACTIVE_PARTY], 0);
-	int items = _treasureItems;
+	//int items = _treasureItems;
 	
 	if (_treasureGold & _treasureItems) {
 		// TODO
@@ -138,7 +138,7 @@ bool Scripts::checkEvents() {
 //		int var4E = 0;
 		_currentPos = party._mazePosition;
 		_charIndex = 1;
-		_v2 = true;
+		_v2 = 1;
 		_nEdamageType = 0;
 //		int var40 = -1;
 
@@ -202,7 +202,7 @@ bool Scripts::checkEvents() {
 		w.close();
 	}
 
-	_v2 = true;
+	_v2 = 1;
 	Common::fill(&_charFX[0], &_charFX[6], 0);
 
 	return _scriptResult;
@@ -490,7 +490,7 @@ void Scripts::cmdSetChar(Common::Array<byte> &params) {
 		_charIndex = _vm->getRandomNumber(1, _vm->_party->_partyCount);
 	}
 
-	_v2 = true;
+	_v2 = 1;
 	cmdNoAction(params);
 }
 
@@ -515,7 +515,7 @@ void Scripts::cmdSpawn(Common::Array<byte> &params) {
 }
 
 void Scripts::cmdDoTownEvent(Common::Array<byte> &params) {
-	_scriptResult = doTownEvent(params[0]);
+	_scriptResult = _vm->_town->townAction(params[0]);
 	_vm->_party->_stepped = true;
 	
 	cmdExit(params);
@@ -1271,15 +1271,6 @@ bool Scripts::ifProc(int action, uint32 mask, int mode, int charIndex) {
 	}
 }
 
-bool Scripts::doTownEvent(int actionId) {
-	if (actionId == 12)
-		return false;
-
-
-
-	return false;
-}
-
 bool Scripts::copyProtectionCheck() {
 	// Currentl not implemented
 	return true;
diff --git a/engines/xeen/scripts.h b/engines/xeen/scripts.h
index 44290ee..59f202e 100644
--- a/engines/xeen/scripts.h
+++ b/engines/xeen/scripts.h
@@ -149,7 +149,7 @@ private:
 	int _mirrorId;
 	int _refreshIcons;
 	int _scriptResult;
-	bool _v2;
+	int _v2;
 	bool _scriptExecuted;
 	bool _var50;
 	MazeEvent *_event;
@@ -223,8 +223,6 @@ private:
 
 	bool ifProc(int action, uint32 mask, int mode, int charIndex);
 
-	bool doTownEvent(int actionId);
-
 	bool copyProtectionCheck();
 public:
 	int _animCounter;
diff --git a/engines/xeen/sound.h b/engines/xeen/sound.h
index c121524..d38e16b 100644
--- a/engines/xeen/sound.h
+++ b/engines/xeen/sound.h
@@ -37,6 +37,8 @@ public:
 
 	void proc2(Common::SeekableReadStream &f);
 
+	void loadMusic(const Common::String &name, int v2) {}
+
 	void startMusic(int v1);
 
 	void playSong(Common::SeekableReadStream &f) {}
diff --git a/engines/xeen/spells.cpp b/engines/xeen/spells.cpp
index 8a5126c..29c22b1 100644
--- a/engines/xeen/spells.cpp
+++ b/engines/xeen/spells.cpp
@@ -31,10 +31,15 @@ Spells::Spells(XeenEngine *vm) : _vm(vm) {
 }
 
 void Spells::load() {
-	File f("spells.xen");
-	while (f.pos() < f.size())
-		_spellNames.push_back(f.readString());
-	f.close();
+	File f1("spells.xen");
+	while (f1.pos() < f1.size())
+		_spellNames.push_back(f1.readString());
+	f1.close();
+
+	File f2("mae.xen");
+	while (f2.pos() < f2.size())
+		_maeNames.push_back(f2.readString());
+	f2.close();
 }
 
 } // End of namespace Xeen
diff --git a/engines/xeen/spells.h b/engines/xeen/spells.h
index adb957c..48c0f9a 100644
--- a/engines/xeen/spells.h
+++ b/engines/xeen/spells.h
@@ -37,6 +37,7 @@ private:
 	void load();
 public:
 	Common::StringArray _spellNames;
+	Common::StringArray _maeNames;
 public:
 	Spells(XeenEngine *vm);
 };
diff --git a/engines/xeen/town.cpp b/engines/xeen/town.cpp
new file mode 100644
index 0000000..214454b
--- /dev/null
+++ b/engines/xeen/town.cpp
@@ -0,0 +1,321 @@
+/* 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 "xeen/town.h"
+#include "xeen/resources.h"
+#include "xeen/xeen.h"
+
+namespace Xeen {
+
+Town::Town(XeenEngine *vm) : _vm(vm) {
+	_townMaxId = 0;
+	_townActionId = 0;
+	_townCurrent = 0;
+	_v1 = 0;
+	_v2 = 0;
+	Common::fill(&_arr1[0], &_arr1[6], 0);
+}
+
+void Town::loadStrings(const Common::String &name) {
+	File f(name);
+	_textStrings.clear();
+	while (f.pos() < f.size())
+		_textStrings.push_back(f.readString());
+	f.close();
+}
+
+int Town::townAction(int actionId) {
+	Interface &intf = *_vm->_interface;
+	Map &map = *_vm->_map;
+	Party &party = *_vm->_party;
+	Screen &screen = *_vm->_screen;
+	SoundManager &sound = *_vm->_sound;
+	bool isDarkCc = _vm->_files->_isDarkCc;
+
+	if (actionId == 12) {
+		pyramidEvent();
+		return 0;
+	}
+
+	_townMaxId = TOWN_MAXES[_vm->_files->_isDarkCc][actionId];
+	_townActionId = actionId;
+	_townCurrent = 0;
+	_v1 = 0;
+	_townPos = Common::Point(8, 8);
+	intf._overallFrame = 0;
+
+	// This area sets up the GUI buttos and startup sample to play for the
+	// given town action
+	Common::String vocName = "hello1.voc";
+	clearButtons();
+	_icons1.clear();
+	_icons2.clear();
+
+	switch (actionId) {
+	case 0:
+		// Bank
+		_icons1.load("bank.icn");
+		_icons2.load("bank2.icn");
+		addButton(Common::Rect(234, 108, 259, 128), Common::KEYCODE_d, &_icons1);
+		addButton(Common::Rect(261, 108, 285, 128), Common::KEYCODE_w, &_icons1);
+		addButton(Common::Rect(288, 108, 312, 128), Common::KEYCODE_ESCAPE, &_icons1);
+		intf._overallFrame = 1;
+
+		sound.playSample(nullptr, 0);
+		vocName = isDarkCc ? "bank1.voc" : "banker.voc";
+		break;
+	
+	case 1:
+		// Blacksmith
+		_icons1.load("esc.icn");
+		addButton(Common::Rect(261, 100, 285, 120), Common::KEYCODE_ESCAPE, &_icons1, true);
+		addButton(Common::Rect(234, 54, 308, 62), 0, &_icons1, false);
+		addButton(Common::Rect(234, 64, 308, 72), Common::KEYCODE_b, &_icons1, false);
+		addButton(Common::Rect(234, 74, 308, 82), 0, &_icons1, false);
+		addButton(Common::Rect(234, 84, 308, 92), 0, &_icons1, false);
+
+		sound.playSample(nullptr, 0);
+		vocName = isDarkCc ? "see2.voc" : "whaddayo.voc";
+		break;
+
+	case 2:
+		// Guild
+		loadStrings("spldesc.bin");
+		_icons1.load("esc.icn");
+		addButton(Common::Rect(261, 100, 285, 120), Common::KEYCODE_ESCAPE, &_icons1, true);
+		addButton(Common::Rect(234, 54, 308, 62), 0, &_icons1, false);
+		addButton(Common::Rect(234, 64, 308, 72), Common::KEYCODE_b, &_icons1, false);
+		addButton(Common::Rect(234, 74, 308, 82), Common::KEYCODE_s, &_icons1, false);
+		addButton(Common::Rect(234, 84, 308, 92), 0, &_icons1, false);
+		_vm->_mode = MODE_17;
+
+		sound.playSample(nullptr, 0);
+		vocName = isDarkCc ? "parrot1.voc" : "guild10.voc";
+		break;
+
+	case 3:
+		// Tavern
+		loadStrings("tavern.bin");
+		_icons1.load("tavern.icn");
+		addButton(Common::Rect(281, 108, 305, 128), Common::KEYCODE_ESCAPE, &_icons1, true);
+		addButton(Common::Rect(242, 108, 266, 128), Common::KEYCODE_s, &_icons1, true);
+		addButton(Common::Rect(234, 54, 308, 62), Common::KEYCODE_d, &_icons1, false);
+		addButton(Common::Rect(234, 64, 308, 72), Common::KEYCODE_f, &_icons1, false);
+		addButton(Common::Rect(234, 74, 308, 82), Common::KEYCODE_t, &_icons1, false);
+		addButton(Common::Rect(234, 84, 308, 92), Common::KEYCODE_r, &_icons1, false);
+		_vm->_mode = MODE_17;
+
+		sound.playSample(nullptr, 0);
+		vocName = isDarkCc ? "hello1.voc" : "hello.voc";
+		break;
+
+	case 4:
+		// Temple
+		_icons1.load("esc.icn");
+		addButton(Common::Rect(261, 100, 285, 120), Common::KEYCODE_ESCAPE, &_icons1, true);
+		addButton(Common::Rect(234, 54, 308, 62), Common::KEYCODE_h, &_icons1, false);
+		addButton(Common::Rect(234, 64, 308, 72), Common::KEYCODE_d, &_icons1, false);
+		addButton(Common::Rect(234, 74, 308, 82), Common::KEYCODE_u, &_icons1, false);
+		addButton(Common::Rect(234, 84, 308, 92), 0, &_icons1, false);
+
+		sound.playSample(nullptr, 0);
+		vocName = isDarkCc ? "help2.voc" : "maywe2.voc";
+		break;
+
+	case 5:
+		// Training
+		Common::fill(&_arr1[0], &_arr1[6], 0);
+		_v2 = 0;
+
+		_icons1.load("train.icn");
+		addButton(Common::Rect(281, 108, 305, 128), Common::KEYCODE_ESCAPE, &_icons1, true);
+		addButton(Common::Rect(242, 108, 266, 128), Common::KEYCODE_t, &_icons1, false);
+
+		sound.playSample(nullptr, 0);
+		vocName = isDarkCc ? "training.voc" : "youtrn1.voc";
+		break;
+
+	case 6:
+		// Arena event
+		arenaEvent();
+		return false;
+
+	case 8:
+		// Reaper event
+		reaperEvent();
+		return false;
+
+	case 9:
+		// Golem event
+		golemEvent();
+		return false;
+
+	case 10:
+	case 13:
+		dwarfEvent();
+		return false;
+
+	case 11:
+		sphinxEvent();
+		return false;
+
+	default:
+		break;
+	}
+
+	sound.loadMusic(TOWN_ACTION_MUSIC[actionId], 223);
+
+	_townSprites.clear();
+	for (int idx = 0; idx < TOWN_ACTION_FILES[isDarkCc][actionId]; ++idx) {
+		Common::String shapesName = Common::String::format("%s%d.twn",
+			TOWN_ACTION_SHAPES[actionId], idx + 1);
+		_townSprites[idx].load(shapesName);
+	}
+
+	Common::String title = createTownText();
+	intf._face1UIFrame = intf._face2UIFrame = 0;
+	intf._dangerSenseUIFrame = 0; 
+	intf._spotDoorsUIFrame = 0;
+	intf._batUIFrame = 0;
+
+	_townSprites[_townCurrent / 8].draw(screen, _townCurrent % 8, _townPos);
+	if (actionId == 0 && isDarkCc) {
+		_townSprites[4].draw(screen, _vm->getRandomNumber(13, 18),
+			Common::Point(8, 30));
+	}
+
+	intf.assembleBorder();
+
+	// Open up the window and write the string
+	screen._windows[10].open();
+	screen._windows[10].writeString(title);
+	drawButtons(&screen);
+
+	screen._windows[0].update();
+	intf.highlightChar(0);
+	intf.drawTownAnim(1);
+
+	if (actionId == 0)
+		intf._overallFrame = 2;
+
+	File voc(vocName);
+	sound.playSample(&voc, 1);
+
+	do {
+		townWait();
+		doTownOptions();
+		screen._windows[10].writeString(title);
+		drawButtons(&screen);
+	} while (!_vm->shouldQuit() && _buttonValue != Common::KEYCODE_ESCAPE);
+
+	switch (actionId) {
+	case 1:
+		// Leave blacksmith
+		if (isDarkCc) {
+			sound.playSample(nullptr, 0);
+			File f("come1.voc");
+			sound.playSample(&f, 1);
+		}
+		break;
+
+	case 3: {
+		// Leave Tavern
+		sound.playSample(nullptr, 0);
+		File f(isDarkCc ? "gdluck1.voc" : "goodbye.voc");
+		sound.playSample(&f, 1);
+
+		map.mazeData()._mazeNumber = party._mazeId;
+		break;
+	}
+	default:
+		break;
+	}
+
+	int result;
+	if (party._mazeId != 0) {
+		map.load(party._mazeId);
+		_v1 += 1440;
+		party.addTime(_v1);
+		result = 0;
+	} else {
+		_vm->_saves->saveChars();
+		result = 2;
+	}
+
+	for (uint idx = 0; idx < _townSprites.size(); ++idx)
+		_townSprites[idx].clear();
+	intf.mainIconsPrint();
+	_buttonValue = 0;
+
+	return result;
+}
+
+void Town::townWait() {
+	EventsManager &events = *_vm->_events;
+	Interface &intf = *_vm->_interface;
+
+	while (!_vm->shouldQuit()) {
+		events.updateGameCounter();
+		while (!_vm->shouldQuit() && !_buttonValue && events.timeElapsed() < 3) {
+			checkEvents(_vm);
+		}
+		if (_buttonValue)
+			return;
+
+		intf.drawTownAnim(!_vm->_screen->_windows[11]._enabled);
+	}
+}
+
+void Town::pyramidEvent() {
+	error("TODO: pyramidEvent");
+}
+
+void Town::arenaEvent() {
+	error("TODO: arenaEvent");
+}
+
+void Town::reaperEvent() {
+	error("TODO: repearEvent");
+}
+
+void Town::golemEvent() {
+	error("TODO: golemEvent");
+}
+
+void Town::sphinxEvent() {
+	error("TODO: sphinxEvent");
+}
+
+void Town::dwarfEvent() {
+	error("TODO: dwarfEvent");
+}
+
+Common::String Town::createTownText() {
+	error("TODO");
+}
+
+void Town::doTownOptions() {
+	error("TODO: doTownOptions");
+}
+
+
+} // End of namespace Xeen
diff --git a/engines/xeen/town.h b/engines/xeen/town.h
new file mode 100644
index 0000000..2221ed5
--- /dev/null
+++ b/engines/xeen/town.h
@@ -0,0 +1,75 @@
+/* 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_TOWN_H
+#define XEEN_TOWN_H
+
+#include "common/scummsys.h"
+#include "common/str-array.h"
+#include "xeen/dialogs.h"
+
+namespace Xeen {
+
+class XeenEngine;
+
+class Town: public ButtonContainer {
+private:
+	XeenEngine *_vm;
+	SpriteResource _icons1, _icons2;
+	Common::StringArray _textStrings;
+	Common::Array<SpriteResource> _townSprites;
+	int _townMaxId;
+	int _townActionId;
+	int _townCurrent;
+	int _v1;
+	int _v2;
+	Common::Point _townPos;
+	int _arr1[6];
+
+	void loadStrings(const Common::String &name);
+
+	void pyramidEvent();
+
+	void arenaEvent();
+
+	void reaperEvent();
+
+	void golemEvent();
+
+	void sphinxEvent();
+
+	void dwarfEvent();
+
+	Common::String createTownText();
+
+	void townWait();
+
+	void doTownOptions();
+public:
+	Town(XeenEngine *vm);
+
+	int townAction(int actionId);
+};
+
+} // End of namespace Xeen
+
+#endif /* XEEN_SPELLS_H */
diff --git a/engines/xeen/xeen.cpp b/engines/xeen/xeen.cpp
index 8879b15..8d646fb 100644
--- a/engines/xeen/xeen.cpp
+++ b/engines/xeen/xeen.cpp
@@ -48,6 +48,7 @@ XeenEngine::XeenEngine(OSystem *syst, const XeenGameDescription *gameDesc)
 	_scripts = nullptr;
 	_sound = nullptr;
 	_spells = nullptr;
+	_town = nullptr;
 	_eventData = nullptr;
 	_dangerSenseAllowed = false;
 	_noDirectionSense = false;
@@ -69,6 +70,7 @@ XeenEngine::~XeenEngine() {
 	delete _scripts;
 	delete _sound;
 	delete _spells;
+	delete _town;
 	delete _eventData;
 	delete _files;
 }
@@ -94,6 +96,7 @@ void XeenEngine::initialize() {
 	_screen->setupWindows();
 	_sound = new SoundManager(this);
 	_spells = new Spells(this);
+	_town = new Town(this);
 
 	File f("029.obj");
 	_eventData = f.readStream(f.size());
diff --git a/engines/xeen/xeen.h b/engines/xeen/xeen.h
index 38c7beb..1145072 100644
--- a/engines/xeen/xeen.h
+++ b/engines/xeen/xeen.h
@@ -44,6 +44,7 @@
 #include "xeen/scripts.h"
 #include "xeen/sound.h"
 #include "xeen/spells.h"
+#include "xeen/town.h"
 
 /**
  * This is the namespace of the Xeen engine.
@@ -142,6 +143,7 @@ public:
 	Scripts *_scripts;
 	SoundManager *_sound;
 	Spells *_spells;
+	Town *_town;
 	Treasure _treasure;
 	Mode _mode;
 	GameEvent _gameEvent;


Commit: 81e1bd2930bf4192fa8bfdbb805c65795e68c6e1
    https://github.com/scummvm/scummvm/commit/81e1bd2930bf4192fa8bfdbb805c65795e68c6e1
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-01-26T21:35:50-05:00

Commit Message:
XEEN: Implemented createTownText

Changed paths:
    engines/xeen/party.cpp
    engines/xeen/party.h
    engines/xeen/resources.cpp
    engines/xeen/resources.h
    engines/xeen/town.cpp
    engines/xeen/town.h
    engines/xeen/xeen.cpp
    engines/xeen/xeen.h



diff --git a/engines/xeen/party.cpp b/engines/xeen/party.cpp
index 388b8de..1baa254 100644
--- a/engines/xeen/party.cpp
+++ b/engines/xeen/party.cpp
@@ -757,6 +757,65 @@ void Character::setValue(int id, uint value) {
 	}
 }
 
+bool Character::guildMember() const {
+	Party &party = *Party::_vm->_party;
+
+	if (party._mazeId == 49 && !Party::_vm->_files->_isDarkCc) {
+		return hasAward(5);
+	}
+
+	switch (party._mazeId) {
+	case 29:
+		return hasAward(83);
+	case 31:
+		return hasAward(84);
+	case 33:
+		return hasAward(85);
+	case 35:
+		return hasAward(86);
+	default:
+		return hasAward(87);
+	}
+}
+
+uint Character::nextExperienceLevel() const {
+	uint base = currentExperienceLevel();
+	uint curr = getCurrentExperience();
+	return (curr < base) ? 0 : curr - base;
+}
+
+uint Character::currentExperienceLevel() const {
+	int shift, base;
+	if (_level._permanent >= 12) {
+		base = _level._permanent - 12;
+		shift = 10;
+	} else {
+		base = 0;
+		shift = _level._permanent;
+	}
+	
+	return (base * 1024000) + (CLASS_EXP_LEVELS[_class] << shift);
+}
+
+uint Character::getCurrentExperience() const {
+	int lev = _level._permanent - 1;
+	int shift, base;
+
+	if (lev > 0 && lev < 12)
+		return _experience;
+
+	if (lev >= 12) {
+		base = lev - 12;
+		shift = 10;
+	} else {
+		base = 0;
+		shift = lev - 1;
+	}
+
+	return (base * 1024000) + (CLASS_EXP_LEVELS[_class] << shift) +
+		_experience;
+}
+
 /*------------------------------------------------------------------------*/
 
 void Roster::synchronize(Common::Serializer &s) {
diff --git a/engines/xeen/party.h b/engines/xeen/party.h
index c77364b..0b7572c 100644
--- a/engines/xeen/party.h
+++ b/engines/xeen/party.h
@@ -167,6 +167,14 @@ public:
 	int itemScan(int itemId) const;
 
 	void setValue(int id, uint value);
+
+	bool guildMember() const;
+
+	uint nextExperienceLevel() const;
+
+	uint currentExperienceLevel() const;
+
+	uint getCurrentExperience() const;
 };
 
 class Roster: public Common::Array<Character> {
diff --git a/engines/xeen/resources.cpp b/engines/xeen/resources.cpp
index 9e11a17..c1951d7 100644
--- a/engines/xeen/resources.cpp
+++ b/engines/xeen/resources.cpp
@@ -290,6 +290,10 @@ const char *const CLASS_NAMES[11] = {
 	"Ninja", "Barbarian", "Druid", "Ranger", nullptr
 };
 
+const uint CLASS_EXP_LEVELS[10] = {
+	1500, 2000, 2000, 1500, 2000, 1000, 1500, 1500, 1500, 2000
+};
+
 const char *const CONDITION_NAMES[18] = {
 	nullptr, "Cursed", "Heart Broken", "Weak", "Poisoned", "Diseased", 
 	"Insane", "In Love", "Drunk", "Asleep", "Depressed", "Confused", 
@@ -585,4 +589,64 @@ const int TOWN_ACTION_FILES[2][7] = {
 	{ 3, 2, 4, 2, 4, 2, 1 }, { 5, 3, 7, 5, 4, 6, 1 }
 };
 
+const char *const BANK_TEXT = "\x0D\x02\x03""c\x0B""122\x09""013"
+	"\x0C""37D\x0C""dep\x09""040\x0C""37W\x0C""dith\x09""067ESC"
+	"\x01\x09""000\x0B""000Bank of Xeen\x0B""015\n"
+	"Bank\x03l\n"
+	"Gold\x03r\x09""000%s\x03l\n"
+	"Gems\x03r\x09""000%s\x03""c\n"
+	"\n"
+	"Party\x03l\n"
+	"Gold\x03r\x09""000%s\x03l\n"
+	"Gems\x03r\x09""000%s";
+
+const char *const BLACKSMITH_TEXT = "\x01\x0D\x03""c\x0B""000\x09""000"
+	"Store Options for\x09""039\x0B""027%s\x03""l\x0B""046\n"
+	"\x09""011\x0C""37B\x0C""drowse\n"
+	"\x09""000\x0B""090Gold\x03r\x09""000%s"
+	"\x02\x03""c\x0B""122\x09""040ESC\x01";
+
+const char *const GUILD_NOT_MEMBER_TEXT =
+	"\n\nYou have to be a member to shop here.";
+
+const char *const GUILD_TEXT = "\x03""c\x0B""027\x09""039%s"
+	"\x03l\x0B""046\n"
+	"\x09""012\x0C""37B\x0C""duy Spells\n"
+	"\x09""012\x0C""37S\x0C""dpell Info";
+
+const char *const TAVERN_TEXT =
+	"\x0D\x03""c\x0B""000\x09""000Tavern Options for\x09""039"
+	"\x0B""027%s%s\x03l\x09""000"
+	"\x0B""090Gold\x03r\x09""000%s\x02\x03""c\x0B""122"
+	"\x09""021\x0C""37S\x0C""dign in\x09""060ESC\x01";
+
+const char *const FOOD_AND_DRINK =
+	"\x03l\x09""017\x0B""046\x0C""37D\x0C""drink\n"
+	"\x09""017\x0C""37F\x0C""dood\n"
+	"\x09""017\x0C""37T\x0C""dip\n"
+	"\x09""017\x0C""37R\x0C""dumors";
+
+const char *const TEMPLE_TEXT =
+	"\x0D\x03""c\x0B""000\x09""000Temple Options for"
+	"\x09""039\x0B""027%s\x03l\x09""000\x0B""046"
+	"\x0C""37H\x0C""deal\x03r\x09""000%lu\x03l\n"
+	"\x0C""37D\x0C""donation\x03r\x09""000%lu\x03l\n"
+	"\x0C""37U\x0C""dnCurse\x03r\x09""000%s"
+	"\x03l\x09""000\x0B""090Gold\x03r\x09""000%s"
+	"\x02\x03""c\x0B""122\x09""040ESC\x01";
+
+const char *const EXPERIENCE_FOR_LEVEL = 
+	"%s needs %lu experience for level %u.";
+
+const char *const LEARNED_ALL = "%s has learned all we can teach!";
+
+const char *const ELIGIBLE_FOR_LEVEL = "%s is eligible for level %d.";
+
+const char *const TRAINING_TEXT =
+	"\x0D\x03""cTraining Options\n"
+	"\n"
+	"%s\x03l\x0B""090\x09""000Gold\x03r\x09"
+	"000%s\x02\x03""c\x0B""122\x09""021"
+	"\x0C""37T\x0C""drain\x09""060ESC\x01";
+
 } // End of namespace Xeen
diff --git a/engines/xeen/resources.h b/engines/xeen/resources.h
index ff19202..a6f52cb 100644
--- a/engines/xeen/resources.h
+++ b/engines/xeen/resources.h
@@ -66,6 +66,8 @@ extern const int RACE_SP_BONUSES[5][2];
 
 extern const char *const CLASS_NAMES[11];
 
+extern const uint CLASS_EXP_LEVELS[10];
+
 extern const char *const ALIGNMENT_NAMES[3];
 
 extern const char *const SEX_NAMES[2];
@@ -158,6 +160,28 @@ extern const char *const TOWN_ACTION_SHAPES[4];
 
 extern const int TOWN_ACTION_FILES[2][7];
 
+extern const char *const BANK_TEXT;
+
+extern const char *const BLACKSMITH_TEXT;
+
+extern const char *const GUILD_NOT_MEMBER_TEXT;
+
+extern const char *const GUILD_TEXT;
+
+extern const char *const TAVERN_TEXT;
+
+extern const char *const FOOD_AND_DRINK;
+
+extern const char *const TEMPLE_TEXT;
+
+extern const char *const EXPERIENCE_FOR_LEVEL;
+
+extern const char *const LEARNED_ALL;
+
+extern const char *const ELIGIBLE_FOR_LEVEL;
+
+extern const char *const TRAINING_TEXT;
+
 } // End of namespace Xeen
 
 #endif	/* XEEN_RESOURCES_H */
diff --git a/engines/xeen/town.cpp b/engines/xeen/town.cpp
index 214454b..bb8590f 100644
--- a/engines/xeen/town.cpp
+++ b/engines/xeen/town.cpp
@@ -27,12 +27,23 @@
 namespace Xeen {
 
 Town::Town(XeenEngine *vm) : _vm(vm) {
+	Common::fill(&_arr1[0], &_arr1[6], 0);
 	_townMaxId = 0;
 	_townActionId = 0;
 	_townCurrent = 0;
+	_currentCharLevel = 0;
 	_v1 = 0;
 	_v2 = 0;
-	Common::fill(&_arr1[0], &_arr1[6], 0);
+	_donation = 0;
+	_healCost = 0;
+	_v5 = _v6 = 0;
+	_v10 = _v11 = 0;
+	_v12 = _v13 = 0;
+	_v14 = 0;
+	_v20 = 0;
+	_uncurseCost = 0;
+	_flag1 = false;
+	_nextExperienceLevel = 0;
 }
 
 void Town::loadStrings(const Common::String &name) {
@@ -191,7 +202,8 @@ int Town::townAction(int actionId) {
 		_townSprites[idx].load(shapesName);
 	}
 
-	Common::String title = createTownText();
+	Character *charP = &party._activeParty[0];
+	Common::String title = createTownText(*charP);
 	intf._face1UIFrame = intf._face2UIFrame = 0;
 	intf._dangerSenseUIFrame = 0; 
 	intf._spotDoorsUIFrame = 0;
@@ -222,7 +234,7 @@ int Town::townAction(int actionId) {
 
 	do {
 		townWait();
-		doTownOptions();
+		charP = doTownOptions(charP);
 		screen._windows[10].writeString(title);
 		drawButtons(&screen);
 	} while (!_vm->shouldQuit() && _buttonValue != Common::KEYCODE_ESCAPE);
@@ -309,11 +321,159 @@ void Town::dwarfEvent() {
 	error("TODO: dwarfEvent");
 }
 
-Common::String Town::createTownText() {
-	error("TODO");
+Common::String Town::createTownText(Character &ch) {
+	Interface &intf = *_vm->_interface;
+	Party &party = *_vm->_party;
+	Common::String msg;
+
+	switch (_townActionId) {
+	case 0:
+		// Bank
+		return Common::String::format(BANK_TEXT,
+			XeenEngine::printMil(party._bankGold).c_str(),
+			XeenEngine::printMil(party._bankGems).c_str(),
+			XeenEngine::printMil(party._gold).c_str(),
+			XeenEngine::printMil(party._gems).c_str());
+	case 1:
+		// Blacksmith
+		return Common::String::format(BLACKSMITH_TEXT,
+			XeenEngine::printMil(party._gold));
+
+	case 2:
+		// Guild
+		return !ch.guildMember() ? GUILD_NOT_MEMBER_TEXT :
+			Common::String::format(GUILD_TEXT, ch._name.c_str());
+
+	case 3:
+		// Tavern
+		return Common::String::format(TAVERN_TEXT, ch._name,
+			FOOD_AND_DRINK, XeenEngine::printMil(party._gold).c_str());
+
+	case 4:
+		// Temple
+		_donation = 0;
+		_uncurseCost = 0;
+		_v5 = 0;
+		_v6 = 0;
+		_healCost = 0;
+
+		if (party._mazeId == (_vm->_files->_isDarkCc ? 29 : 28)) {
+			_v10 = _v11 = _v12 = _v13 = 0;
+			_v14 = 10;
+		} else if (party._mazeId == (_vm->_files->_isDarkCc ? 31 : 30)) {
+			_v13 = 10;
+			_v12 = 50;
+			_v11 = 500;
+			_v10 = 100;
+			_v14 = 25;
+		} else if (party._mazeId == (_vm->_files->_isDarkCc ? 37 : 73)) {
+			_v13 = 20;
+			_v12 = 100;
+			_v11 = 1000;
+			_v10 = 200;
+			_v14 = 50;
+		} else if (_vm->_files->_isDarkCc || party._mazeId == 49) {
+			_v13 = 100;
+			_v12 = 500;
+			_v11 = 5000;
+			_v10 = 300;
+			_v14 = 100;
+		}
+
+		_currentCharLevel = ch.getCurrentLevel();
+		if (ch._currentHp < ch.getMaxHP()) {
+			_healCost = _currentCharLevel * 10 + _v13;
+		}
+
+		for (int attrib = HEART_BROKEN; attrib <= UNCONSCIOUS; ++attrib) {
+			if (ch._conditions[attrib])
+				_healCost += _currentCharLevel * 10;
+		}
+
+		_v6 = 0;
+		if (ch._conditions[DEAD]) {
+			_v6 += (_currentCharLevel * 100) + (ch._conditions[DEAD] * 50) + _v12;
+		}
+		if (ch._conditions[STONED]) {
+			_v6 += (_currentCharLevel * 100) + (ch._conditions[STONED] * 50) + _v12;
+		}
+		if (ch._conditions[ERADICATED]) {
+			_v5 = (_currentCharLevel * 1000) + (ch._conditions[ERADICATED] * 500) + _v11;
+		}
+
+		for (int idx = 0; idx < 9; ++idx) {
+			_uncurseCost |= ch._weapons[idx]._bonusFlags & 0x40;
+			_uncurseCost |= ch._armor[idx]._bonusFlags & 0x40;
+			_uncurseCost |= ch._accessories[idx]._bonusFlags & 0x40;
+			_uncurseCost |= ch._misc[idx]._bonusFlags & 0x40;
+		}
+
+		if (_uncurseCost || ch._conditions[CURSED])
+			_v5 = (_currentCharLevel * 20) + _v10;
+
+		_donation = _flag1 ? 0 : _v14;
+		_healCost += _v6 + _v5;
+
+		return Common::String::format(TEMPLE_TEXT, ch._name.c_str(),
+			_healCost, _donation, XeenEngine::printK(_uncurseCost).c_str(),
+			XeenEngine::printMil(party._gold).c_str());
+
+	case 5:
+		// Training
+		if (_vm->_files->_isDarkCc) {
+			switch (party._mazeId) {
+			case 29:
+				_v20 = 30;
+				break;
+			case 31:
+				_v20 = 50;
+				break;
+			case 37:
+				_v20 = 200;
+				break;
+			default:
+				_v20 = 100;
+				break;
+			}
+		} else {
+			switch (party._mazeId) {
+			case 28:
+				_v20 = 10;
+				break;
+			case 30:
+				_v20 = 15;
+				break;
+			default:
+				_v20 = 20;
+				break;
+			}
+		}
+
+		_nextExperienceLevel = ch.nextExperienceLevel();
+
+		if (_nextExperienceLevel >= 0x10000 && ch._level._permanent < _v20) {
+			int nextLevel = ch._level._permanent + 1;
+			return Common::String::format(EXPERIENCE_FOR_LEVEL,
+				ch._name.c_str(), _nextExperienceLevel, nextLevel);
+		} else if (ch._level._permanent >= 20) {
+			_nextExperienceLevel = 1;
+			msg = Common::String::format(LEARNED_ALL, ch._name.c_str());
+		} else {
+			msg = Common::String::format(ELIGIBLE_FOR_LEVEL,
+				ch._name.c_str(), ch._level._permanent + 1);
+		}
+
+		return Common::String::format(TRAINING_TEXT,
+			XeenEngine::printMil(party._gold).c_str());
+
+	default:
+		return "";
+	}
 }
 
-void Town::doTownOptions() {
+Character *Town::doTownOptions(Character *charP) {
+	Common::String result;
+
 	error("TODO: doTownOptions");
 }
 
diff --git a/engines/xeen/town.h b/engines/xeen/town.h
index 2221ed5..07e9bad 100644
--- a/engines/xeen/town.h
+++ b/engines/xeen/town.h
@@ -26,6 +26,7 @@
 #include "common/scummsys.h"
 #include "common/str-array.h"
 #include "xeen/dialogs.h"
+#include "xeen/party.h"
 
 namespace Xeen {
 
@@ -40,10 +41,19 @@ private:
 	int _townMaxId;
 	int _townActionId;
 	int _townCurrent;
-	int _v1;
-	int _v2;
+	int _v1, _v2;
+	int _donation;
+	int _healCost;
+	int _v5, _v6;
+	int _v10, _v11, _v12;
+	int _v13, _v14;
+	int _v20;
+	int _uncurseCost;
 	Common::Point _townPos;
 	int _arr1[6];
+	int _currentCharLevel;
+	bool _flag1;
+	uint _nextExperienceLevel;
 
 	void loadStrings(const Common::String &name);
 
@@ -59,11 +69,11 @@ private:
 
 	void dwarfEvent();
 
-	Common::String createTownText();
+	Common::String createTownText(Character &ch);
 
 	void townWait();
 
-	void doTownOptions();
+	Character *doTownOptions(Character *charP);
 public:
 	Town(XeenEngine *vm);
 
diff --git a/engines/xeen/xeen.cpp b/engines/xeen/xeen.cpp
index 8d646fb..d7a85fb 100644
--- a/engines/xeen/xeen.cpp
+++ b/engines/xeen/xeen.cpp
@@ -339,4 +339,14 @@ void XeenEngine::gameLoop() {
 	}
 }
 
+Common::String XeenEngine::printMil(uint value) {
+	return (value >= 1000000) ? Common::String::format("%lu mil", value / 1000000) :
+		Common::String::format("%lu", value);
+}
+
+Common::String XeenEngine::printK(uint value) {
+	return (value > 9999) ? Common::String::format("%uk", value / 1000) :
+		Common::String::format("%u", value);
+}
+
 } // End of namespace Xeen
diff --git a/engines/xeen/xeen.h b/engines/xeen/xeen.h
index 1145072..cb09c28 100644
--- a/engines/xeen/xeen.h
+++ b/engines/xeen/xeen.h
@@ -198,6 +198,10 @@ public:
 	 * Write out a savegame header
 	 */
 	void writeSavegameHeader(Common::OutSaveFile *out, XeenSavegameHeader &header);
+
+	static Common::String printMil(uint value);
+
+	static Common::String printK(uint value);
 };
 
 } // End of namespace Xeen


Commit: 88382b2d8f0f1fd27e2100a94ace74453d6186f7
    https://github.com/scummvm/scummvm/commit/88382b2d8f0f1fd27e2100a94ace74453d6186f7
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-01-27T08:02:54-05:00

Commit Message:
XEEN: Added NumericInput class and refactored existing string input

Changed paths:
  A engines/xeen/dialogs_input.cpp
  A engines/xeen/dialogs_input.h
  R engines/xeen/dialogs_string_input.cpp
  R engines/xeen/dialogs_string_input.h
    engines/xeen/module.mk
    engines/xeen/resources.cpp
    engines/xeen/resources.h
    engines/xeen/screen.cpp
    engines/xeen/screen.h
    engines/xeen/scripts.cpp
    engines/xeen/town.cpp
    engines/xeen/town.h



diff --git a/engines/xeen/dialogs_input.cpp b/engines/xeen/dialogs_input.cpp
new file mode 100644
index 0000000..1394379
--- /dev/null
+++ b/engines/xeen/dialogs_input.cpp
@@ -0,0 +1,187 @@
+/* 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 "xeen/dialogs_input.h"
+#include "xeen/scripts.h"
+#include "xeen/xeen.h"
+
+namespace Xeen {
+
+/**
+ * Allows the user to enter a string
+ */
+int Input::getString(Common::String &line, uint maxLen, int maxWidth, bool isNumeric) {
+	_vm->_noDirectionSense = true;
+	Common::String msg = Common::String::format("\x03""l\t000\x04%03d\x03""c", maxWidth);
+	_window->writeString(msg);
+	_window->update();
+
+	while (!_vm->shouldQuit()) {
+		Common::KeyCode keyCode = doCursor(msg);
+
+		if ((keyCode == Common::KEYCODE_BACKSPACE || keyCode == Common::KEYCODE_DELETE)
+			&& line.size() > 0)
+			line.deleteLastChar();
+		else if (line.size() < maxLen && (line.size() > 0 || keyCode != Common::KEYCODE_SPACE)
+				&& ((isNumeric && keyCode >= Common::KEYCODE_0 && keyCode < Common::KEYCODE_9) ||
+				   (!isNumeric && keyCode >= Common::KEYCODE_SPACE && keyCode < Common::KEYCODE_DELETE))) {
+			line += (char)keyCode;
+		} else if (keyCode == Common::KEYCODE_RETURN || keyCode == Common::KEYCODE_KP_ENTER) {
+			break;
+		} else if (keyCode == Common::KEYCODE_ESCAPE) {
+			line = "";
+			break;
+		}
+	}
+
+	_vm->_noDirectionSense = false;
+	return line.size();
+}
+
+/**
+ * Draws the cursor and waits until the user presses a key
+ */
+Common::KeyCode Input::doCursor(const Common::String &msg) {
+	EventsManager &events = *_vm->_events;
+	Interface &intf = *_vm->_interface;
+	Screen &screen = *_vm->_screen;
+
+	bool oldUpDoorText = intf._upDoorText;
+	byte oldTillMove = intf._tillMove;
+	intf._upDoorText = false;
+	intf._tillMove = 0;
+
+	bool flag = !_vm->_startupWindowActive && !screen._windows[25]._enabled
+		&& _vm->_mode != MODE_FF && _vm->_mode != MODE_17;
+
+	Common::KeyCode ch = Common::KEYCODE_INVALID;
+	while (!_vm->shouldQuit()) {
+		events.updateGameCounter();
+
+		if (flag)
+			intf.draw3d(false);
+		_window->writeString(msg);
+		_window->update();
+
+		if (flag)
+			screen._windows[3].update();
+
+		events.wait(1, true);
+		if (events.isKeyPending()) {
+			Common::KeyState keyState;
+			events.getKey(keyState);
+			ch = keyState.keycode;
+			break;
+		}
+	}
+
+	_window->writeString("");
+	_window->update();
+
+	intf._tillMove = oldTillMove;
+	intf._upDoorText = oldUpDoorText;
+
+	return ch;
+}
+
+/*------------------------------------------------------------------------*/
+
+StringInput::StringInput(XeenEngine *vm): Input(vm, &vm->_screen->_windows[6]) {
+}
+
+int StringInput::show(XeenEngine *vm, bool type, const Common::String &msg1,
+		const Common::String &msg2, int opcode) {
+	StringInput *dlg = new StringInput(vm);
+	int result = dlg->execute(type, msg1, msg2, opcode);
+	delete dlg;
+
+	return result;
+}
+
+int StringInput::execute(bool type, const Common::String &expected, 
+		const Common::String &title, int opcode) {
+	Interface &intf = *_vm->_interface;
+	Screen &screen = *_vm->_screen;
+	Scripts &scripts = *_vm->_scripts;
+	Window &w = screen._windows[6];
+	SoundManager &sound = *_vm->_sound;
+	int result = 0;
+
+	w.open();
+	w.writeString(Common::String::format("\r\x03""c%s\v024\t000", title.c_str()));
+	w.update();
+
+	Common::String line;
+	if (getString(line, 30, 200, false)) {
+		if (type) {
+			if (line == intf._interfaceText) {
+				result = true;
+			} else if (line == expected) {
+				result = (opcode == 55) ? -1 : 1;
+			}
+		} else {
+			// Load in the mirror list
+			File f(Common::String::format("%smirr.txt",
+				_vm->_files->_isDarkCc ? "dark" : "xeen"));
+			MirrorEntry me;
+			scripts._mirror.clear();
+			while (me.synchronize(f))
+				scripts._mirror.push_back(me);
+
+			for (uint idx = 0; idx < scripts._mirror.size(); ++idx) {
+				if (line == scripts._mirror[idx]._name) {
+					result = idx;
+					sound.playFX(_vm->_files->_isDarkCc ? 35 : 61);
+					break;
+				}
+			}
+		}
+	}
+
+	w.close();
+	return result;
+}
+
+/*------------------------------------------------------------------------*/
+
+NumericInput::NumericInput(XeenEngine *vm, int window) : Input(vm, &vm->_screen->_windows[window]) {
+}
+
+int NumericInput::show(XeenEngine *vm, int window, int maxLength, int maxWidth) {
+	NumericInput *dlg = new NumericInput(vm, window);
+	int result = dlg->execute(maxLength, maxWidth);
+	delete dlg;
+
+	return result;
+}
+
+int NumericInput::execute(int maxLength, int maxWidth) {
+	Common::String line;
+
+	if (getString(line, maxLength, maxWidth, true))
+		return atoi(line.c_str());
+	else
+		return 0;
+}
+
+
+} // End of namespace Xeen
diff --git a/engines/xeen/dialogs_input.h b/engines/xeen/dialogs_input.h
new file mode 100644
index 0000000..c6d832c
--- /dev/null
+++ b/engines/xeen/dialogs_input.h
@@ -0,0 +1,66 @@
+/* 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_STRING_INPUT_H
+#define XEEN_DIALOGS_STRING_INPUT_H
+
+#include "common/keyboard.h"
+#include "xeen/dialogs.h"
+#include "xeen/screen.h"
+
+namespace Xeen {
+
+class Input : public ButtonContainer {
+private:
+	Common::KeyCode doCursor(const Common::String &msg);
+protected:
+	XeenEngine *_vm;
+	Window *_window;
+
+	int getString(Common::String &line, uint maxLen, int maxWidth, bool isNumeric);
+
+	Input(XeenEngine *vm, Window *window) : _vm(vm), _window(window) {}
+};
+
+class StringInput : public Input {
+protected:
+	StringInput(XeenEngine *vm);
+
+	int execute(bool type, const Common::String &expected, 
+		const Common::String &title, int opcode);
+public:
+	static int show(XeenEngine *vm, bool type, const Common::String &msg1, 
+		const Common::String &msg2, int opcode);
+};
+
+class NumericInput : public Input {
+private:
+	NumericInput(XeenEngine *vm, int window);
+
+	int execute(int maxLength, int maxWidth);
+public:
+	static int show(XeenEngine *vm, int window, int maxLength, int maxWidth);
+};
+
+} // End of namespace Xeen
+
+#endif /* XEEN_DIALOGS_STRING_INPUT_H */
diff --git a/engines/xeen/dialogs_string_input.cpp b/engines/xeen/dialogs_string_input.cpp
deleted file mode 100644
index ced4ad3..0000000
--- a/engines/xeen/dialogs_string_input.cpp
+++ /dev/null
@@ -1,82 +0,0 @@
-/* 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 "xeen/dialogs_string_input.h"
-#include "xeen/scripts.h"
-#include "xeen/xeen.h"
-
-namespace Xeen {
-
-int StringInput::show(XeenEngine *vm, bool type, const Common::String &msg1,
-		const Common::String &msg2, int opcdoe) {
-	StringInput *dlg = new StringInput(vm);
-	int result = dlg->execute(type, msg1, msg2, opcdoe);
-	delete dlg;
-
-	return result;
-}
-
-int StringInput::execute(bool type, const Common::String &expected, 
-		const Common::String &title, int opcode) {
-	Interface &intf = *_vm->_interface;
-	Screen &screen = *_vm->_screen;
-	Scripts &scripts = *_vm->_scripts;
-	Window &w = screen._windows[6];
-	SoundManager &sound = *_vm->_sound;
-	int result = 0;
-
-	w.open();
-	w.writeString(Common::String::format("\r\x03""c%s\v024\t000", title.c_str()));
-	w.update();
-
-	Common::String line;
-	if (w.getString(line, 30, 200)) {
-		if (type) {
-			if (line == intf._interfaceText) {
-				result = true;
-			} else if (line == expected) {
-				result = (opcode == 55) ? -1 : 1;
-			}
-		} else {
-			// Load in the mirror list
-			File f(Common::String::format("%smirr.txt",
-				_vm->_files->_isDarkCc ? "dark" : "xeen"));
-			MirrorEntry me;
-			scripts._mirror.clear();
-			while (me.synchronize(f))
-				scripts._mirror.push_back(me);
-
-			for (uint idx = 0; idx < scripts._mirror.size(); ++idx) {
-				if (line == scripts._mirror[idx]._name) {
-					result = idx;
-					sound.playFX(_vm->_files->_isDarkCc ? 35 : 61);
-					break;
-				}
-			}
-		}
-	}
-
-	w.close();
-	return result;
-}
-
-} // End of namespace Xeen
diff --git a/engines/xeen/dialogs_string_input.h b/engines/xeen/dialogs_string_input.h
deleted file mode 100644
index 1e18726..0000000
--- a/engines/xeen/dialogs_string_input.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/* 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_STRING_INPUT_H
-#define XEEN_DIALOGS_STRING_INPUT_H
-
-#include "xeen/dialogs.h"
-
-namespace Xeen {
-
-class StringInput : public ButtonContainer {
-private:
-	XeenEngine *_vm;
-
-	StringInput(XeenEngine *vm) : ButtonContainer(), _vm(vm) {}
-
-	int execute(bool type, const Common::String &expected, 
-		const Common::String &title, int opcode);
-public:
-	static int show(XeenEngine *vm, bool type, const Common::String &msg1, 
-		const Common::String &msg2, int opcdoe);
-};
-
-} // End of namespace Xeen
-
-#endif /* XEEN_DIALOGS_STRING_INPUT_H */
diff --git a/engines/xeen/module.mk b/engines/xeen/module.mk
index c9ea03f..c361c47 100644
--- a/engines/xeen/module.mk
+++ b/engines/xeen/module.mk
@@ -10,7 +10,7 @@ MODULE_OBJS := \
 	dialogs.o \
 	dialogs_error.o \
 	dialogs_options.o \
-	dialogs_string_input.o \
+	dialogs_input.o \
 	dialogs_whowill.o \
 	dialogs_yesno.o \
 	events.o \
diff --git a/engines/xeen/resources.cpp b/engines/xeen/resources.cpp
index c1951d7..cab6e26 100644
--- a/engines/xeen/resources.cpp
+++ b/engines/xeen/resources.cpp
@@ -649,4 +649,31 @@ const char *const TRAINING_TEXT =
 	"000%s\x02\x03""c\x0B""122\x09""021"
 	"\x0C""37T\x0C""drain\x09""060ESC\x01";
 
+const char *const GOLD_GEMS =
+	"\x03""c\x0B""000\x09""000%s\x03l\n"
+	"\n"
+	"Gold\x03r\x09""000%s\x03l\n"
+	"Gems\x03r\x09""000%s\x02\x03""c\x0B""096\x09""013G"
+	"\x0C""37o\x0C""dld\x09""040G\x0C\x03""7e"
+	"\x0C""dms\x09""067ESC\x01";
+
+const char *const DEPOSIT_WITHDRAWL[2] = { "Deposit", "Withdrawl" };
+
+const char *const NOT_ENOUGH_X_IN_THE_Y =
+	"\x03""c\x0B""012Not enough %s in the %s!\x03l";
+
+const char *const NO_X_IN_THE_Y = "\x03""c\x0B""012No %s in the %s!\x03l";
+
+const char *const STAT_NAMES[16] = {
+	"Might", "Intellect", "Personality", "Endurance", "Speed",
+	"Accuracy", "Luck", "Age", "Level", "Armor Class", "Hit Points",
+	"Spell Points", "Resistances", "Skills", "Awards", "Experience"
+};
+
+const char *const CONSUMABLE_NAMES[4] = { "Gold", "Gems", "Food", "Condition" };
+
+const char *const WHERE_NAMES[2] = { "Party", "Bank" };
+
+const char *const AMOUNT = "\x03""c\x09""000\x0B""051Amount\x03l\n";
+
 } // End of namespace Xeen
diff --git a/engines/xeen/resources.h b/engines/xeen/resources.h
index a6f52cb..7461888 100644
--- a/engines/xeen/resources.h
+++ b/engines/xeen/resources.h
@@ -182,6 +182,22 @@ extern const char *const ELIGIBLE_FOR_LEVEL;
 
 extern const char *const TRAINING_TEXT;
 
+extern const char *const GOLD_GEMS;
+
+extern const char *const DEPOSIT_WITHDRAWL[2];
+
+extern const char *const NOT_ENOUGH_X_IN_THE_Y;
+
+extern const char *const NO_X_IN_THE_Y;
+
+extern const char *const STAT_NAMES[16];
+
+extern const char *const CONSUMABLE_NAMES[4];
+
+extern const char *const WHERE_NAMES[2];
+
+extern const char *const AMOUNT;
+
 } // End of namespace Xeen
 
 #endif	/* XEEN_RESOURCES_H */
diff --git a/engines/xeen/screen.cpp b/engines/xeen/screen.cpp
index 5088829..87062dc 100644
--- a/engines/xeen/screen.cpp
+++ b/engines/xeen/screen.cpp
@@ -177,82 +177,6 @@ void Window::drawList(DrawStruct *items, int count) {
 	}
 }
 
-/**
- * Allows the user to enter a string
- */
-int Window::getString(Common::String &line, uint maxLen, int maxWidth) {
-	_vm->_noDirectionSense = true;
-	Common::String msg = Common::String::format("\x03""l\t000\x04%03d\x03""c", maxWidth);
-	writeString(msg);
-	update();
-
-	while (!_vm->shouldQuit()) {
-		Common::KeyCode keyCode = doCursor(msg);
-		
-		if ((keyCode == Common::KEYCODE_BACKSPACE || keyCode == Common::KEYCODE_DELETE)
-				&& line.size() > 0)
-			line.deleteLastChar();
-		else if (keyCode >= Common::KEYCODE_SPACE && keyCode < Common::KEYCODE_DELETE
-				&& line.size() < maxLen && (line.size() > 0 || keyCode != Common::KEYCODE_SPACE)) {
-
-		} else if (keyCode == Common::KEYCODE_RETURN || keyCode == Common::KEYCODE_KP_ENTER) {
-			break;
-		} else if (keyCode == Common::KEYCODE_ESCAPE) {
-			line = "";
-			break;
-		}
-	}
-
-	_vm->_noDirectionSense = false;
-	return line.size();
-}
-
-/**
- * Draws the cursor and waits until the user presses a key
- */
-Common::KeyCode Window::doCursor(const Common::String &msg) {
-	EventsManager &events = *_vm->_events;
-	Interface &intf = *_vm->_interface;
-	Screen &screen = *_vm->_screen;
-	
-	bool oldUpDoorText = intf._upDoorText;
-	byte oldTillMove = intf._tillMove;
-	intf._upDoorText = false;
-	intf._tillMove = 0;
-
-	bool flag = !_vm->_startupWindowActive && !screen._windows[25]._enabled
-			&& _vm->_mode != MODE_FF && _vm->_mode != MODE_17;
-
-	Common::KeyCode ch = Common::KEYCODE_INVALID;
-	while (!_vm->shouldQuit()) {
-		events.updateGameCounter();
-
-		if (flag)
-			intf.draw3d(false);
-		writeString(msg);
-		update();
-
-		if (flag)
-			screen._windows[3].update();
-
-		events.wait(1, true);
-		if (events.isKeyPending()) {
-			Common::KeyState keyState;
-			events.getKey(keyState);
-			ch = keyState.keycode;
-			break;
-		}
-	}
-
-	writeString("");
-	update();
-
-	intf._tillMove = oldTillMove;
-	intf._upDoorText = oldUpDoorText;
-
-	return ch;
-}
-
 /*------------------------------------------------------------------------*/
 
 /**
diff --git a/engines/xeen/screen.h b/engines/xeen/screen.h
index 6e805c2..85affe3 100644
--- a/engines/xeen/screen.h
+++ b/engines/xeen/screen.h
@@ -67,8 +67,6 @@ private:
 	int _ycL, _ycH;
 
 	void open2();
-
-	Common::KeyCode doCursor(const Common::String &msg);
 public:
 	bool _enabled;
 public:
diff --git a/engines/xeen/scripts.cpp b/engines/xeen/scripts.cpp
index 0972165..e3cc682 100644
--- a/engines/xeen/scripts.cpp
+++ b/engines/xeen/scripts.cpp
@@ -21,7 +21,7 @@
  */
 
 #include "xeen/scripts.h"
-#include "xeen/dialogs_string_input.h"
+#include "xeen/dialogs_input.h"
 #include "xeen/dialogs_whowill.h"
 #include "xeen/dialogs_yesno.h"
 #include "xeen/party.h"
diff --git a/engines/xeen/town.cpp b/engines/xeen/town.cpp
index bb8590f..dceb79c 100644
--- a/engines/xeen/town.cpp
+++ b/engines/xeen/town.cpp
@@ -195,8 +195,8 @@ int Town::townAction(int actionId) {
 
 	sound.loadMusic(TOWN_ACTION_MUSIC[actionId], 223);
 
-	_townSprites.clear();
-	for (int idx = 0; idx < TOWN_ACTION_FILES[isDarkCc][actionId]; ++idx) {
+	_townSprites.resize(TOWN_ACTION_FILES[isDarkCc][actionId]);
+	for (uint idx = 0; idx < _townSprites.size(); ++idx) {
 		Common::String shapesName = Common::String::format("%s%d.twn",
 			TOWN_ACTION_SHAPES[actionId], idx + 1);
 		_townSprites[idx].load(shapesName);
@@ -281,20 +281,20 @@ int Town::townAction(int actionId) {
 	return result;
 }
 
-void Town::townWait() {
+int Town::townWait() {
 	EventsManager &events = *_vm->_events;
 	Interface &intf = *_vm->_interface;
 
-	while (!_vm->shouldQuit()) {
+	while (!_vm->shouldQuit() && !_buttonValue) {
 		events.updateGameCounter();
 		while (!_vm->shouldQuit() && !_buttonValue && events.timeElapsed() < 3) {
 			checkEvents(_vm);
 		}
-		if (_buttonValue)
-			return;
-
-		intf.drawTownAnim(!_vm->_screen->_windows[11]._enabled);
+		if (!_buttonValue)
+			intf.drawTownAnim(!_vm->_screen->_windows[11]._enabled);
 	}
+
+	return _buttonValue;
 }
 
 void Town::pyramidEvent() {
@@ -471,10 +471,96 @@ Common::String Town::createTownText(Character &ch) {
 	}
 }
 
-Character *Town::doTownOptions(Character *charP) {
-	Common::String result;
+Character *Town::doTownOptions(Character *c) {
+	switch (_townActionId) {
+	case 0:
+		if (_buttonValue == Common::KEYCODE_d)
+			_buttonValue = 0;
+		else if (_buttonValue == Common::KEYCODE_w)
+			_buttonValue = 1;
+		else
+			break;
+
+		depositWithdrawl(_buttonValue);
+		break;
+
+	default:
+		// TODO: remaining cases
+		error("TODO: doTownOptions");
+	}
+
+	return c;
+}
+
+void Town::depositWithdrawl(int choice) {
+	Party &party = *_vm->_party;
+	Screen &screen = *_vm->_screen;
+	SoundManager &sound = *_vm->_sound;
+	int gold, gems;
+
+	if (choice) {
+		gold = party._bankGold;
+		gems = party._bankGems;
+	} else {
+		gold = party._gold;
+		gems = party._gems;
+	}
+
+	for (uint idx = 0; idx < _buttons.size(); ++idx)
+		_buttons[idx]._sprites = &_icons1;
+	_buttons[0]._value = Common::KEYCODE_o;
+	_buttons[1]._value = Common::KEYCODE_e;
+	_buttons[2]._value = Common::KEYCODE_ESCAPE;
+
+	Common::String msg = Common::String::format(GOLD_GEMS,
+		DEPOSIT_WITHDRAWL[choice],
+		XeenEngine::printMil(gold).c_str(),
+		XeenEngine::printMil(gems).c_str());
+
+	screen._windows[35].open();
+	screen._windows[35].writeString(msg);
+	drawButtons(&screen._windows[35]);
+	screen._windows[35].update();
+
+	sound.playSample(nullptr, 0);
+	File f("coina.voc");
+	bool flag;
+
+	do {
+		bool flag;
+		switch (townWait()) {
+		case Common::KEYCODE_o:
+			continue;
+		case Common::KEYCODE_e:
+			flag = 1;
+			break;
+		default:
+			flag = 0;
+			break;
+		}
+		
+		if ((choice && !party._bankGems && flag) ||
+			(choice && !party._bankGold && !flag) ||
+			(choice && !party._gems && flag) ||
+			(choice && !party._gold && !flag)) {
+			notEnough(flag, choice, 1, WT_2);
+		} else {
+			screen._windows[35].writeString(AMOUNT);
+
+			// TODO
+		}
+		// TODO
+	} while (!_vm->shouldQuit() && _buttonValue != Common::KEYCODE_ESCAPE);
+
+}
+
+void Town::notEnough(int consumableId, int whereId, bool mode, ErrorWaitType wait) {
+	SoundManager &sound = *_vm->_sound;
 
-	error("TODO: doTownOptions");
+	Common::String msg = Common::String::format(
+		mode ? NO_X_IN_THE_Y : NOT_ENOUGH_X_IN_THE_Y,
+		CONSUMABLE_NAMES[consumableId], WHERE_NAMES[whereId]);
+	ErrorScroll::show(_vm, msg, wait);
 }
 
 
diff --git a/engines/xeen/town.h b/engines/xeen/town.h
index 07e9bad..068cc82 100644
--- a/engines/xeen/town.h
+++ b/engines/xeen/town.h
@@ -26,6 +26,7 @@
 #include "common/scummsys.h"
 #include "common/str-array.h"
 #include "xeen/dialogs.h"
+#include "xeen/dialogs_error.h"
 #include "xeen/party.h"
 
 namespace Xeen {
@@ -71,9 +72,13 @@ private:
 
 	Common::String createTownText(Character &ch);
 
-	void townWait();
+	int townWait();
 
-	Character *doTownOptions(Character *charP);
+	Character *doTownOptions(Character *c);
+
+	void depositWithdrawl(int choice);
+
+	void notEnough(int consumableId, int whereId, bool mode, ErrorWaitType wait);
 public:
 	Town(XeenEngine *vm);
 


Commit: 5030d0046f9f36965c5479d0fd0006461d32e5f4
    https://github.com/scummvm/scummvm/commit/5030d0046f9f36965c5479d0fd0006461d32e5f4
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-01-27T08:51:08-05:00

Commit Message:
XEEN: Implemented depositWithdrawl and subtract

Changed paths:
    engines/xeen/party.h
    engines/xeen/resources.cpp
    engines/xeen/resources.h
    engines/xeen/town.cpp
    engines/xeen/town.h



diff --git a/engines/xeen/party.h b/engines/xeen/party.h
index 0b7572c..883b378 100644
--- a/engines/xeen/party.h
+++ b/engines/xeen/party.h
@@ -218,7 +218,7 @@ public:
 	int _day;
 	int _year;
 	int _minutes;
-	int _food;
+	uint _food;
 	int _lightCount;
 	int _torchCount;
 	int _fireResistence;
@@ -228,10 +228,10 @@ public:
 	int _deathCount;
 	int _winCount;
 	int _lossCount;
-	int _gold;
-	int _gems;
-	int _bankGold;
-	int _bankGems;
+	uint _gold;
+	uint _gems;
+	uint _bankGold;
+	uint _bankGems;
 	int _totalTime;
 	bool _rested;
 	bool _gameFlags[512];
diff --git a/engines/xeen/resources.cpp b/engines/xeen/resources.cpp
index cab6e26..3be2617 100644
--- a/engines/xeen/resources.cpp
+++ b/engines/xeen/resources.cpp
@@ -657,6 +657,13 @@ const char *const GOLD_GEMS =
 	"\x0C""37o\x0C""dld\x09""040G\x0C\x03""7e"
 	"\x0C""dms\x09""067ESC\x01";
 
+const char *const GOLD_GEMS_2 =
+	"\x09""000\x0B""000\x03""c%s\x03l\n"
+	"\n"
+	"\x04""077Gold\x03r\x09""000%s\x03l\n"
+	"\x04""077Gems\x03r\x09""000%s\x03l\x09""000\x0B""051\x04""077\n"
+	"\x04""077";
+
 const char *const DEPOSIT_WITHDRAWL[2] = { "Deposit", "Withdrawl" };
 
 const char *const NOT_ENOUGH_X_IN_THE_Y =
diff --git a/engines/xeen/resources.h b/engines/xeen/resources.h
index 7461888..5dbc321 100644
--- a/engines/xeen/resources.h
+++ b/engines/xeen/resources.h
@@ -184,6 +184,8 @@ extern const char *const TRAINING_TEXT;
 
 extern const char *const GOLD_GEMS;
 
+extern const char *const GOLD_GEMS_2;
+
 extern const char *const DEPOSIT_WITHDRAWL[2];
 
 extern const char *const NOT_ENOUGH_X_IN_THE_Y;
diff --git a/engines/xeen/town.cpp b/engines/xeen/town.cpp
index dceb79c..9e1f047 100644
--- a/engines/xeen/town.cpp
+++ b/engines/xeen/town.cpp
@@ -21,6 +21,7 @@
  */
 
 #include "xeen/town.h"
+#include "xeen/dialogs_input.h"
 #include "xeen/resources.h"
 #include "xeen/xeen.h"
 
@@ -322,7 +323,6 @@ void Town::dwarfEvent() {
 }
 
 Common::String Town::createTownText(Character &ch) {
-	Interface &intf = *_vm->_interface;
 	Party &party = *_vm->_party;
 	Common::String msg;
 
@@ -507,7 +507,7 @@ void Town::depositWithdrawl(int choice) {
 	}
 
 	for (uint idx = 0; idx < _buttons.size(); ++idx)
-		_buttons[idx]._sprites = &_icons1;
+		_buttons[idx]._sprites = &_icons2;
 	_buttons[0]._value = Common::KEYCODE_o;
 	_buttons[1]._value = Common::KEYCODE_e;
 	_buttons[2]._value = Common::KEYCODE_ESCAPE;
@@ -523,45 +523,141 @@ void Town::depositWithdrawl(int choice) {
 	screen._windows[35].update();
 
 	sound.playSample(nullptr, 0);
-	File f("coina.voc");
-	bool flag;
+	File voc("coina.voc");
+	bool flag = false;
 
 	do {
-		bool flag;
 		switch (townWait()) {
 		case Common::KEYCODE_o:
-			continue;
+			flag = false;
+			break;
 		case Common::KEYCODE_e:
-			flag = 1;
+			flag = true;
 			break;
-		default:
-			flag = 0;
+		case Common::KEYCODE_ESCAPE:
 			break;
+		default:
+			continue;
 		}
 		
 		if ((choice && !party._bankGems && flag) ||
 			(choice && !party._bankGold && !flag) ||
-			(choice && !party._gems && flag) ||
-			(choice && !party._gold && !flag)) {
+			(!choice && !party._gems && flag) ||
+			(!choice && !party._gold && !flag)) {
 			notEnough(flag, choice, 1, WT_2);
 		} else {
 			screen._windows[35].writeString(AMOUNT);
+			int amount = NumericInput::show(_vm, 35, 10, 77);
+
+			if (amount) {
+				if (flag) {
+					if (subtract(true, amount, choice, WT_2)) {
+						if (choice) {
+							party._gems += amount;
+						} else {
+							party._bankGems += amount;
+						}
+					}
+				} else {
+					if (subtract(false, amount, choice, WT_2)) {
+						if (choice) {
+							party._gold += amount;
+						} else {
+							party._bankGold += amount;
+						}
+					}
+				}
+			}
 
-			// TODO
+			uint gold, gems;
+			if (choice) {
+				gold = party._bankGold;
+				gems = party._bankGems;
+			} else {
+				gold = party._gold;
+				gems = party._gems;
+			}
+
+			sound.playSample(&voc, 0);
+			msg = Common::String::format(GOLD_GEMS_2, DEPOSIT_WITHDRAWL[choice],
+				XeenEngine::printMil(gold), XeenEngine::printMil(gems));
+			screen._windows[35].writeString(msg);
+			screen._windows[35].update();
 		}
 		// TODO
 	} while (!_vm->shouldQuit() && _buttonValue != Common::KEYCODE_ESCAPE);
 
+	for (uint idx = 0; idx < _buttons.size(); ++idx)
+		_buttons[idx]._sprites = &_icons1;
+	_buttons[0]._value = Common::KEYCODE_d;
+	_buttons[1]._value = Common::KEYCODE_w;
+	_buttons[2]._value = Common::KEYCODE_ESCAPE;
 }
 
 void Town::notEnough(int consumableId, int whereId, bool mode, ErrorWaitType wait) {
-	SoundManager &sound = *_vm->_sound;
-
 	Common::String msg = Common::String::format(
 		mode ? NO_X_IN_THE_Y : NOT_ENOUGH_X_IN_THE_Y,
 		CONSUMABLE_NAMES[consumableId], WHERE_NAMES[whereId]);
 	ErrorScroll::show(_vm, msg, wait);
 }
 
+int Town::subtract(int mode, uint amount, int whereId, ErrorWaitType wait) {
+	Party &party = *_vm->_party;
+
+	switch (mode) {
+	case 0:
+		// Gold
+		if (whereId) {
+			if (amount <= party._bankGold) {
+				party._bankGold -= amount;
+			} else {
+				notEnough(0, whereId, false, wait);
+				return false;
+			}
+		} else {
+			if (amount <= party._gold) {
+				party._gold -= amount;
+			} else {
+				notEnough(0, whereId, false, wait);
+				return false;
+			}
+		}
+		break;
+
+	case 1:
+		// Gems
+		if (whereId) {
+			if (amount <= party._bankGems) {
+				party._bankGems -= amount;
+			} else {
+				notEnough(0, whereId, false, wait);
+				return false;
+			}
+		} else {
+			if (amount <= party._gems) {
+				party._gems -= amount;
+			} else {
+				notEnough(0, whereId, false, wait);
+				return false;
+			}
+		}
+		break;
+
+	case 2:
+		// Food
+		if (amount > party._food) {
+			party._food -= amount;
+		} else {
+			notEnough(5, 0, 0, wait);
+			return false;
+		}
+		break;
+
+	default:
+		break;
+	}
+
+	return true;
+}
 
 } // End of namespace Xeen
diff --git a/engines/xeen/town.h b/engines/xeen/town.h
index 068cc82..df754d5 100644
--- a/engines/xeen/town.h
+++ b/engines/xeen/town.h
@@ -79,6 +79,8 @@ private:
 	void depositWithdrawl(int choice);
 
 	void notEnough(int consumableId, int whereId, bool mode, ErrorWaitType wait);
+
+	int subtract(int mode, uint amount, int whereId, ErrorWaitType wait);
 public:
 	Town(XeenEngine *vm);
 


Commit: 689776d922ca719e5a6749c0e3ec0b6d1884852d
    https://github.com/scummvm/scummvm/commit/689776d922ca719e5a6749c0e3ec0b6d1884852d
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-01-27T22:04:23-05:00

Commit Message:
XEEN: Implemented doTownOptions

Changed paths:
    engines/xeen/dialogs_yesno.cpp
    engines/xeen/dialogs_yesno.h
    engines/xeen/interface_map.cpp
    engines/xeen/items.h
    engines/xeen/party.cpp
    engines/xeen/party.h
    engines/xeen/resources.cpp
    engines/xeen/resources.h
    engines/xeen/scripts.cpp
    engines/xeen/sound.h
    engines/xeen/town.cpp
    engines/xeen/town.h



diff --git a/engines/xeen/dialogs_yesno.cpp b/engines/xeen/dialogs_yesno.cpp
index 940f5b6..07de5a5 100644
--- a/engines/xeen/dialogs_yesno.cpp
+++ b/engines/xeen/dialogs_yesno.cpp
@@ -25,7 +25,7 @@
 
 namespace Xeen {
 
-bool YesNo::show(XeenEngine *vm, bool type, int v2) {
+bool YesNo::show(XeenEngine *vm, bool type, bool v2) {
 	YesNo *dlg = new YesNo(vm);
 	bool result = dlg->execute(type, v2);
 	delete dlg;
diff --git a/engines/xeen/dialogs_yesno.h b/engines/xeen/dialogs_yesno.h
index 82ac402..d083cd6 100644
--- a/engines/xeen/dialogs_yesno.h
+++ b/engines/xeen/dialogs_yesno.h
@@ -35,7 +35,7 @@ private:
 
 	bool execute(bool type, int v2);
 public:
-	static bool show(XeenEngine *vm, bool type, int v2);
+	static bool show(XeenEngine *vm, bool type, bool v2);
 };
 
 } // End of namespace Xeen
diff --git a/engines/xeen/interface_map.cpp b/engines/xeen/interface_map.cpp
index c9ea258..f90d3e3 100644
--- a/engines/xeen/interface_map.cpp
+++ b/engines/xeen/interface_map.cpp
@@ -4552,26 +4552,26 @@ void InterfaceMap::assembleBorder() {
 
 	// Draw UI element for blessed
 	_blessSprites.draw(screen, 16, Common::Point(33, 137));
-	if (_vm->_party->_blessedActive) {
+	if (_vm->_party->_blessed) {
 		_blessedUIFrame = (_blessedUIFrame + 1) % 4;
 		_blessSprites.draw(screen, _blessedUIFrame, Common::Point(33, 137));
 	}
 
 	// Draw UI element for power shield
-	if (_vm->_party->_powerShieldActive) {
+	if (_vm->_party->_powerShield) {
 		_powerShieldUIFrame = (_powerShieldUIFrame + 1) % 4;
 		_blessSprites.draw(screen, _powerShieldUIFrame + 4,
 			Common::Point(55, 137));
 	}
 
 	// Draw UI element for holy bonus
-	if (_vm->_party->_holyBonusActive) {
+	if (_vm->_party->_holyBonus) {
 		_holyBonusUIFrame = (_holyBonusUIFrame + 1) % 4;
 		_blessSprites.draw(screen, _holyBonusUIFrame + 8, Common::Point(160, 137));
 	}
 
 	// Draw UI element for heroism
-	if (_vm->_party->_heroismActive) {
+	if (_vm->_party->_heroism) {
 		_heroismUIFrame = (_heroismUIFrame + 1) % 4;
 		_blessSprites.draw(screen, _heroismUIFrame + 12, Common::Point(182, 137));
 	}
diff --git a/engines/xeen/items.h b/engines/xeen/items.h
index 95a5519..958a0b8 100644
--- a/engines/xeen/items.h
+++ b/engines/xeen/items.h
@@ -30,6 +30,8 @@ namespace Xeen {
 
 #define TOTAL_ITEMS 10
 
+enum BonusFlags { FLAG_CURSED = 0x40 };
+
 class XeenItem {
 public:
 	int _material;
diff --git a/engines/xeen/party.cpp b/engines/xeen/party.cpp
index 1baa254..66ba405 100644
--- a/engines/xeen/party.cpp
+++ b/engines/xeen/party.cpp
@@ -60,7 +60,7 @@ Character::Character() {
 	_lloydSide = 0;
 	Common::fill(&_conditions[0], &_conditions[16], 0);
 	_townUnknown = 0;
-	_unknown2 = 0;
+	_savedMazeId = 0;
 	_currentHp = 0;
 	_currentSp = 0;
 	_ybDay = 0;
@@ -140,7 +140,7 @@ void Character::synchronize(Common::Serializer &s) {
 		s.syncAsByte(_conditions[i]);
 
 	s.syncAsUint16LE(_townUnknown);
-	s.syncAsByte(_unknown2);
+	s.syncAsByte(_savedMazeId);
 	s.syncAsUint16LE(_currentHp);
 	s.syncAsUint16LE(_currentSp);
 	s.syncAsUint16LE(_ybDay);
@@ -381,7 +381,7 @@ int Character::getArmorClass(bool baseOnly) const {
 
 	int result = statBonus(getStat(SPEED)) + itemScan(9);
 	if (!baseOnly)
-		result += (party._blessedActive ? 1 : 0) + _ACTemp;
+		result += party._blessed + _ACTemp;
 
 	return MAX(result, 0);
 }
@@ -842,10 +842,10 @@ Party::Party(XeenEngine *vm) {
 	_wizardEyeActive = false;
 	_clairvoyanceActive = false;
 	_walkOnWaterActive = false;
-	_blessedActive = false;
-	_powerShieldActive = false;
-	_holyBonusActive = false;
-	_heroismActive = false;
+	_blessed = 0;
+	_powerShield = 0;
+	_holyBonus = 0;
+	_heroism = 0;
 	_difficulty = ADVENTURER;
 	_cloudsEnd = false;
 	_darkSideEnd = false;
@@ -912,10 +912,10 @@ void Party::synchronize(Common::Serializer &s) {
 	s.syncAsByte(_wizardEyeActive);
 	s.syncAsByte(_clairvoyanceActive);
 	s.syncAsByte(_walkOnWaterActive);
-	s.syncAsByte(_blessedActive);
-	s.syncAsByte(_powerShieldActive);
-	s.syncAsByte(_holyBonusActive);
-	s.syncAsByte(_heroismActive);
+	s.syncAsByte(_blessed);
+	s.syncAsByte(_powerShield);
+	s.syncAsByte(_holyBonus);
+	s.syncAsByte(_heroism);
 	s.syncAsByte(_difficulty);
 
 	for (int i = 0; i < ITEMS_COUNT; ++i)
@@ -1194,10 +1194,10 @@ void Party::resetTemps() {
 	_walkOnWaterActive = false;
 	_wizardEyeActive = false;
 	_clairvoyanceActive = false;
-	_heroismActive = false;
-	_holyBonusActive = false;
-	_powerShieldActive = false;
-	_blessedActive = false;
+	_heroism = 0;
+	_holyBonus = 0;
+	_powerShield = 0;
+	_blessed = 0;
 }
 
 void Party::handleLight() {
diff --git a/engines/xeen/party.h b/engines/xeen/party.h
index 883b378..10f4027 100644
--- a/engines/xeen/party.h
+++ b/engines/xeen/party.h
@@ -127,7 +127,7 @@ public:
 	AttributePair _magicResistence;
 	int _conditions[16];
 	int _townUnknown;
-	int _unknown2;
+	int _savedMazeId;
 	int _currentHp;
 	int _currentSp;
 	int _ybDay;
@@ -202,10 +202,10 @@ public:
 	bool _wizardEyeActive;
 	bool _clairvoyanceActive;
 	bool _walkOnWaterActive;
-	bool _blessedActive;
-	bool _powerShieldActive;
-	bool _holyBonusActive;
-	bool _heroismActive;
+	int _blessed;
+	int _powerShield;
+	int _holyBonus;
+	int _heroism;
 	Difficulty _difficulty;
 	XeenItem _blacksmithWeapons[ITEMS_COUNT];
 	XeenItem _blacksmithArmor[ITEMS_COUNT];
diff --git a/engines/xeen/resources.cpp b/engines/xeen/resources.cpp
index 3be2617..5eec5be 100644
--- a/engines/xeen/resources.cpp
+++ b/engines/xeen/resources.cpp
@@ -626,6 +626,34 @@ const char *const FOOD_AND_DRINK =
 	"\x09""017\x0C""37T\x0C""dip\n"
 	"\x09""017\x0C""37R\x0C""dumors";
 
+const char *const GOOD_STUFF = "\n"
+	"\n"
+	"Good Stuff\n"
+	"\n"
+	"Hit a key!";
+
+const char *const HAVE_A_DRINK = "\n\nHave a Drink\n\nHit a key!";
+
+const char *const YOURE_DRUNK = "\n\nYou're Drunk\n\nHit a key!";
+
+const int TAVERN_EXIT_LIST[2][6][5][2] = {
+	{
+		{ { 21, 17 }, { 0, 0 }, { 20, 3 }, { 0, 0 }, { 0, 0 } },
+		{ { 13, 4 }, { 0, 0 }, { 19, 9 }, { 0, 0 }, { 0, 0 } },
+		{ { 20, 10 }, { 12, 8 }, { 5, 26 }, { 3, 4 }, { 7, 5 } },
+		{ { 18, 4 }, { 0, 0 }, { 19, 16 }, { 0, 0 }, { 11, 12 } },
+		{ { 15, 21 }, { 0, 0 }, { 13, 21 }, { 0, 0 }, { 0, 0 } },
+		{ { 10, 8 }, { 0, 0 }, { 15, 12 }, { 0, 0 }, { 0, 0 } },
+	}, {
+		{ { 21, 17 }, { 0, 0 }, { 20, 3 }, { 0, 0 }, { 0, 0 } },
+		{ { 13, 4 }, { 0, 0 }, { 19, 9 }, { 0, 0 }, { 0, 0 } },
+		{ { 20, 10 }, { 12, 8 }, { 5, 26 }, { 3, 4 }, { 7, 5 } },
+		{ { 17, 24 }, { 14, 13 }, { 0, 0 }, { 0, 0 }, { 9, 4 } },
+		{ { 15, 21 }, { 0, 0 }, { 13, 21 }, { 0, 0 }, { 0, 0 } },
+		{ { 10, 8 }, { 0, 0 }, { 15, 12 }, { 0, 0 }, { 0, 0 } }
+	}
+};
+
 const char *const TEMPLE_TEXT =
 	"\x0D\x03""c\x0B""000\x09""000Temple Options for"
 	"\x09""039\x0B""027%s\x03l\x09""000\x0B""046"
@@ -683,4 +711,6 @@ const char *const WHERE_NAMES[2] = { "Party", "Bank" };
 
 const char *const AMOUNT = "\x03""c\x09""000\x0B""051Amount\x03l\n";
 
+const char *const FOOD_PACKS_FULL = "\v007Your food packs are already full!";
+
 } // End of namespace Xeen
diff --git a/engines/xeen/resources.h b/engines/xeen/resources.h
index 5dbc321..497b025 100644
--- a/engines/xeen/resources.h
+++ b/engines/xeen/resources.h
@@ -170,6 +170,14 @@ extern const char *const GUILD_TEXT;
 
 extern const char *const TAVERN_TEXT;
 
+extern const char *const GOOD_STUFF;
+
+extern const char *const HAVE_A_DRINK;
+
+extern const char *const YOURE_DRUNK;
+
+extern const int TAVERN_EXIT_LIST[2][6][5][2];
+
 extern const char *const FOOD_AND_DRINK;
 
 extern const char *const TEMPLE_TEXT;
@@ -200,6 +208,8 @@ extern const char *const WHERE_NAMES[2];
 
 extern const char *const AMOUNT;
 
+extern const char *const FOOD_PACKS_FULL;
+
 } // End of namespace Xeen
 
 #endif	/* XEEN_RESOURCES_H */
diff --git a/engines/xeen/scripts.cpp b/engines/xeen/scripts.cpp
index e3cc682..c84ec91 100644
--- a/engines/xeen/scripts.cpp
+++ b/engines/xeen/scripts.cpp
@@ -1077,7 +1077,7 @@ bool Scripts::ifProc(int action, uint32 mask, int mode, int charIndex) {
 		v = ps._luck._temporary;
 		break;
 	case 44:
-		v = YesNo::show(_vm, mask, 0);
+		v = YesNo::show(_vm, mask, false);
 		v = (!v && !mask) ? 2 : mask;
 		break;
 	case 45:
diff --git a/engines/xeen/sound.h b/engines/xeen/sound.h
index d38e16b..b6f1948 100644
--- a/engines/xeen/sound.h
+++ b/engines/xeen/sound.h
@@ -43,7 +43,7 @@ public:
 
 	void playSong(Common::SeekableReadStream &f) {}
 
-	void playSample(const Common::SeekableReadStream *stream, int v2) {}
+	void playSample(const Common::SeekableReadStream *stream, int v2 = 1) {}
 
 	void playFX(int id) {}
 };
diff --git a/engines/xeen/town.cpp b/engines/xeen/town.cpp
index 9e1f047..81cc88b 100644
--- a/engines/xeen/town.cpp
+++ b/engines/xeen/town.cpp
@@ -22,6 +22,7 @@
 
 #include "xeen/town.h"
 #include "xeen/dialogs_input.h"
+#include "xeen/dialogs_yesno.h"
 #include "xeen/resources.h"
 #include "xeen/xeen.h"
 
@@ -42,6 +43,11 @@ Town::Town(XeenEngine *vm) : _vm(vm) {
 	_v12 = _v13 = 0;
 	_v14 = 0;
 	_v20 = 0;
+	_v21 = 0;
+	_v22 = 0;
+	_v23 = 0;
+	_v24 = 0;
+	_dayOfWeek = 0;
 	_uncurseCost = 0;
 	_flag1 = false;
 	_nextExperienceLevel = 0;
@@ -474,19 +480,469 @@ Common::String Town::createTownText(Character &ch) {
 Character *Town::doTownOptions(Character *c) {
 	switch (_townActionId) {
 	case 0:
-		if (_buttonValue == Common::KEYCODE_d)
+		// Bank
+		c = doBankOptions(c);
+		break;
+	case 1:
+		// Blacksmith
+		c = doBlacksmithOptions(c);
+		break;
+	case 2:
+		// Guild
+		c = doGuildOptions(c);
+		break;
+	case 3:
+		// Tavern
+		c = doTavernOptions(c);
+		break;
+	case 4:
+		// Temple
+		c = doTempleOptions(c);
+	case 5:
+		// Training
+		c = doTrainingOptions(c);
+		break;
+	default:
+		break;
+	}
+
+	return c;
+}
+
+Character *Town::doBankOptions(Character *c) {
+	if (_buttonValue == Common::KEYCODE_d)
+		_buttonValue = 0;
+	else if (_buttonValue == Common::KEYCODE_w)
+		_buttonValue = 1;
+	else
+		return c;
+
+	depositWithdrawl(_buttonValue);
+	return c;
+}
+
+Character *Town::doBlacksmithOptions(Character *c) {
+	Interface &intf = *_vm->_interface;
+	Party &party = *_vm->_party;
+	
+	if (_buttonValue >= Common::KEYCODE_F1 && _buttonValue <= Common::KEYCODE_F6) {
+		// Switch character
+		_buttonValue -= Common::KEYCODE_F1;
+		if (_buttonValue < party._partyCount) {
+			c = &party._activeParty[_buttonValue];
+			intf.highlightChar(_buttonValue);
+		}
+	}
+	else if (_buttonValue == Common::KEYCODE_c) {
+		c = showItems(c, 1);
+		_buttonValue = 0;
+	}
+
+	return c;
+}
+
+Character *Town::doGuildOptions(Character *c) {
+	Interface &intf = *_vm->_interface;
+	Party &party = *_vm->_party;
+	SoundManager &sound = *_vm->_sound;
+	bool isDarkCc = _vm->_files->_isDarkCc;
+
+	if (_buttonValue >= Common::KEYCODE_F1 && _buttonValue <= Common::KEYCODE_F6) {
+		// Switch character
+		_buttonValue -= Common::KEYCODE_F1;
+		if (_buttonValue < party._partyCount) {
+			c = &party._activeParty[_buttonValue];
+			intf.highlightChar(_buttonValue);
+
+			if (!c->guildMember()) {
+				sound.playSample(nullptr, 0);
+				intf._overallFrame = 5;
+				File f(isDarkCc ? "skull1.voc" : "guild11.voc");
+				sound.playSample(&f, 1);
+			}
+		}
+	}
+	else if (_buttonValue == Common::KEYCODE_s) {
+		if (c->guildMember())
+			c = showAvailableSpells(c);
+		_buttonValue = 0;
+	} else if (_buttonValue == Common::KEYCODE_c) {
+		if (!c->noActions()) {
+			if (c->guildMember())
+				c = showAvailableSpells(c);
 			_buttonValue = 0;
-		else if (_buttonValue == Common::KEYCODE_w)
-			_buttonValue = 1;
+		}
+	}
+
+	return c;
+}
+
+Character *Town::doTavernOptions(Character *c) {
+	Interface &intf = *_vm->_interface;
+	Map &map = *_vm->_map;
+	Party &party = *_vm->_party;
+	SoundManager &sound = *_vm->_sound;
+	Screen &screen = *_vm->_screen;
+	bool isDarkCc = _vm->_files->_isDarkCc;
+	int idx = 0;
+
+	switch (_buttonValue) {
+	case Common::KEYCODE_F1:
+	case Common::KEYCODE_F2:
+	case Common::KEYCODE_F3:
+	case Common::KEYCODE_F4:
+	case Common::KEYCODE_F5:
+	case Common::KEYCODE_F6:
+		// Switch character
+		_buttonValue -= Common::KEYCODE_F1;
+		if (_buttonValue < party._partyCount) {
+			c = &party._activeParty[_buttonValue];
+			intf.highlightChar(_buttonValue);
+			_v21 = 0;
+		}
+		break;
+	case Common::KEYCODE_d:
+		// Drink
+		if (!c->noActions()) {
+			if (subtract(0, 1, 0, WT_2)) {
+				sound.playSample(nullptr, 0);
+				File f("gulp.voc");
+				sound.playSample(&f, 0);
+				_v21 = 1;
+
+				screen._windows[10].writeString(Common::String::format(TAVERN_TEXT,
+					c->_name.c_str(), GOOD_STUFF,
+					XeenEngine::printMil(party._gold)));
+				drawButtons(&screen._windows[0]);
+				screen._windows[10].update();
+
+				if (_vm->getRandomNumber(100) < 26) {
+					++c->_conditions[DRUNK];
+					intf.charIconsPrint(true);
+					sound.playFX(28);
+				}
+
+				townWait();
+			}
+		}
+		break;
+	case Common::KEYCODE_f: {
+		if (party._mazeId == (isDarkCc ? 29 : 28)) {
+			_v22 = party._partyCount * 15;
+			_v23 = 10;
+			idx = 0;
+		} else if (isDarkCc && party._mazeId == 31) {
+			_v22 = party._partyCount * 60;
+			_v23 = 100;
+			idx = 1;
+		} else if (!isDarkCc && party._mazeId == 30) {
+			_v22 = party._partyCount * 50;
+			_v23 = 50;
+			idx = 1;
+		} else if (isDarkCc) {
+			_v22 = party._partyCount * 120;
+			_v23 = 250;
+			idx = 2;
+		} else if (party._mazeId == 49) {
+			_v22 = party._partyCount * 120;
+			_v23 = 100;
+			idx = 2;
+		} else {
+			_v22 = party._partyCount * 15;
+			_v23 = 10;
+			idx = 0;
+		}
+
+		Common::String msg = _textStrings[(isDarkCc ? 60 : 75) + idx];
+		screen._windows[10].close();
+		screen._windows[12].open();
+		screen._windows[12].writeString(msg);
+
+		if (YesNo::show(_vm, false, true)) {
+			if (party._food >= _v22) {
+				ErrorScroll::show(_vm, FOOD_PACKS_FULL, WT_2);
+			} else if (subtract(0, _v23, 0, WT_2)) {
+				party._food = _v22;
+				sound.playSample(nullptr, 0);
+				File f(isDarkCc ? "thanks2.voc" : "thankyou.voc");
+				sound.playSample(&f, 1);
+			}
+		}
+
+		screen._windows[12].close();
+		screen._windows[10].open();
+		_buttonValue = 0;
+		break;
+	}
+
+	case Common::KEYCODE_r: {
+		if (party._mazeId == (isDarkCc ? 29 : 28)) {
+			idx = 0;
+		} else if (party._mazeId == (isDarkCc ? 31 : 30)) {
+			idx = 10;
+		} else if (isDarkCc || party._mazeId == 49) {
+			idx = 20;
+		}
+
+		Common::String msg = Common::String::format("\x03""c\x0B""012%s",
+			_textStrings[(party._day % 10) + idx]);
+		Window &w = screen._windows[12];
+		w.open();
+		w.writeString(msg);
+		w.update();
+
+		townWait();
+		w.close();
+		break;
+	}
+
+	case Common::KEYCODE_s: {
+		// Save game
+		// TODO: This needs to be fit in better with ScummVM framework
+		int idx = isDarkCc ? (party._mazeId - 29) >> 1 : party._mazeId - 28;
+		assert(idx >= 0);
+		party._mazePosition.x = TAVERN_EXIT_LIST[isDarkCc ? 1 : 0][_townActionId][idx][0];
+		party._mazePosition.y = TAVERN_EXIT_LIST[isDarkCc ? 1 : 0][_townActionId][idx][1];
+
+		if (!isDarkCc || party._mazeId == 29)
+			party._mazeDirection = DIR_WEST;
+		else if (party._mazeId == 31)
+			party._mazeDirection = DIR_EAST;
 		else
-			break;
+			party._mazeDirection = DIR_SOUTH;
+
+		party._priorMazeId = party._mazeId;
+		for (int idx = 0; idx < party._partyCount; ++idx) {
+			party._activeParty[idx]._savedMazeId = party._mazeId;
+			party._activeParty[idx]._xeenSide = map._loadDarkSide;
+		}
+
+		party.addTime(1440);
+		party._mazeId = 0;
+		_vm->quitGame();
+		break;
+	}
+
+	case Common::KEYCODE_t:
+		if (!c->noActions()) {
+			if (!_v21) {
+				screen._windows[10].writeString(Common::String::format(TAVERN_TEXT,
+					c->_name.c_str(), HAVE_A_DRINK,
+					XeenEngine::printMil(party._gold)));
+				drawButtons(&screen);
+				screen._windows[10].update();
+				townWait();
+			} else {
+				_v21 = 0;
+				if (c->_conditions[DRUNK]) {
+					screen._windows[10].writeString(Common::String::format(TAVERN_TEXT,
+						c->_name.c_str(), YOURE_DRUNK,
+						XeenEngine::printMil(party._gold)));
+					drawButtons(&screen);
+					screen._windows[10].update();
+					townWait();
+				} else if (subtract(0, 1, 0, WT_2)) {
+					sound.playSample(nullptr, 0);
+					File f(isDarkCc ? "thanks2.voc" : "thankyou.voc");
+					sound.playSample(&f, 1);
+
+					if (party._mazeId == (isDarkCc ? 29 : 28)) {
+						_v24 = 30;
+					} else if (isDarkCc && party._mazeId == 31) {
+						_v24 = 40;
+					} else if (!isDarkCc && party._mazeId == 45) {
+						_v24 = 45;
+					} else if (!isDarkCc && party._mazeId == 49) {
+						_v24 = 60;
+					} else if (isDarkCc) {
+						_v24 = 50;
+					}
+
+					Common::String msg = _textStrings[map.mazeData()._tavernTips + _v24];
+					map.mazeData()._tavernTips = (map.mazeData()._tavernTips + 1) /
+						(isDarkCc ? 10 : 15);
 
-		depositWithdrawl(_buttonValue);
+					Window &w = screen._windows[12];
+					w.open();
+					w.writeString(Common::String::format("\x03""c\x0B""012%s", msg.c_str()));
+					w.update();
+					townWait();
+					w.close();
+				}
+			}
+		}
 		break;
 
 	default:
-		// TODO: remaining cases
-		error("TODO: doTownOptions");
+		break;
+	}
+
+	return c;
+}
+
+Character *Town::doTempleOptions(Character *c) {
+	Interface &intf = *_vm->_interface;
+	Party &party = *_vm->_party;
+	SoundManager &sound = *_vm->_sound;
+	
+	switch (_buttonValue) {
+	case Common::KEYCODE_F1:
+	case Common::KEYCODE_F2:
+	case Common::KEYCODE_F3:
+	case Common::KEYCODE_F4:
+	case Common::KEYCODE_F5:
+	case Common::KEYCODE_F6:
+		// Switch character
+		_buttonValue -= Common::KEYCODE_F1;
+		if (_buttonValue < party._partyCount) {
+			c = &party._activeParty[_buttonValue];
+			intf.highlightChar(_buttonValue);
+			_dayOfWeek = 0;
+		}
+		break;
+
+	case Common::KEYCODE_d:
+		if (_donation && subtract(0, _donation, 0, WT_2)) {
+			sound.playSample(nullptr, 0);
+			File f("coina.voc");
+			sound.playSample(&f, 1);
+			_dayOfWeek = (_dayOfWeek + 1) / 10;
+
+			if (_dayOfWeek == (party._day / 10)) {
+				party._clairvoyanceActive = true;
+				party._lightCount = 1;
+				
+				int amt = _dayOfWeek ? _dayOfWeek : 10;
+				party._heroism = amt;
+				party._holyBonus = amt;
+				party._powerShield = amt;
+				party._blessed = amt;
+
+				intf.charIconsPrint(true);
+				sound.playSample(nullptr, 0);
+				File f("ahh.voc");
+				sound.playSample(&f, 1);
+				_flag1 = true;
+				_donation = 0;
+			}
+		}
+		break;
+
+	case Common::KEYCODE_h:
+		if (_healCost && subtract(0, _healCost, 0, WT_2)) {
+			c->_magicResistence._temporary = 0;
+			c->_energyResistence._temporary = 0;
+			c->_poisonResistence._temporary = 0;
+			c->_electricityResistence._temporary = 0;
+			c->_coldResistence._temporary = 0;
+			c->_fireResistence._temporary = 0;
+			c->_ACTemp = 0;
+			c->_level._temporary = 0;
+			c->_luck._temporary = 0;
+			c->_accuracy._temporary = 0;
+			c->_speed._temporary = 0;
+			c->_endurance._temporary = 0;
+			c->_personality._temporary = 0;
+			c->_intellect._temporary = 0;
+			c->_might._temporary = 0;
+			c->_currentHp = c->getMaxHP();
+			Common::fill(&c->_conditions[HEART_BROKEN], &c->_conditions[NO_CONDITION], 0);
+
+			_v1 = 1440;
+			intf.charIconsPrint(true);
+			sound.playSample(nullptr, 0);
+			File f("ahh.voc");
+			sound.playSample(&f, 1);
+		}
+		break;
+
+	case Common::KEYCODE_u:
+		if (_uncurseCost && subtract(0, _uncurseCost, 0, WT_2)) {
+			for (int idx = 0; idx < 9; ++idx) {
+				c->_weapons[idx]._bonusFlags &= ~FLAG_CURSED;
+				c->_armor[idx]._bonusFlags &= ~FLAG_CURSED;
+				c->_accessories[idx]._bonusFlags &= ~FLAG_CURSED;
+				c->_misc[idx]._bonusFlags &= ~FLAG_CURSED;
+			}
+
+			_v1 = 1440;
+			intf.charIconsPrint(true);
+			sound.playSample(nullptr, 0);
+			File f("ahh.voc");
+			sound.playSample(&f, 1);
+		}
+		break;
+
+	default:
+		break;
+	}
+
+	return c;
+}
+
+Character *Town::doTrainingOptions(Character *c) {
+	Interface &intf = *_vm->_interface;
+	Party &party = *_vm->_party;
+	SoundManager &sound = *_vm->_sound;
+	bool isDarkCc = _vm->_files->_isDarkCc;
+
+	switch (_buttonValue) {
+	case Common::KEYCODE_F1:
+	case Common::KEYCODE_F2:
+	case Common::KEYCODE_F3:
+	case Common::KEYCODE_F4:
+	case Common::KEYCODE_F5:
+	case Common::KEYCODE_F6:
+		// Switch character
+		_buttonValue -= Common::KEYCODE_F1;
+		if (_buttonValue < party._partyCount) {
+			_v2 = _buttonValue;
+			c = &party._activeParty[_buttonValue];
+			intf.highlightChar(_buttonValue);
+		}
+		break;
+
+	case Common::KEYCODE_t:
+		if (_nextExperienceLevel) {
+			sound.playSample(nullptr, 0);
+			_townCurrent = 0;
+
+			Common::String name;
+			if (c->_level._permanent >= _v20) {
+				name = isDarkCc ? "gtlost.voc" : "trainin1.voc";
+			} else {
+				name = isDarkCc ? "gtlost.voc" : "trainin0.voc";
+			}
+
+			File f(name);
+			sound.playSample(&f);
+
+		} else if (!c->noActions()) {
+			if (subtract(0, (c->_level._permanent * c->_level._permanent) * 10, 0, WT_2)) {
+				_townCurrent = 0;
+				sound.playSample(nullptr, 0);
+				File f(isDarkCc ? "prtygd.voc" : "trainin2.voc");
+				sound.playSample(&f, 1);
+
+				c->_experience -=  c->currentExperienceLevel() - 
+					(c->getCurrentExperience() - c->_experience);
+				c->_level._permanent++;
+
+				if (!_arr1[_v2]) {
+					party.addTime(1440);
+					_arr1[_v2] = 1;
+				}
+
+				party.resetTemps();
+				c->_currentHp = c->getMaxHP();
+				c->_currentSp = c->getMaxSP();
+				intf.charIconsPrint(true);
+			}
+		}
+		break;
+
+	default:
+		break;
 	}
 
 	return c;
@@ -660,4 +1116,12 @@ int Town::subtract(int mode, uint amount, int whereId, ErrorWaitType wait) {
 	return true;
 }
 
+Character *Town::showItems(Character *c, int v2) {
+	error("TODO: showItems");
+}
+
+Character *Town::showAvailableSpells(Character *c) {
+	error("TODO: showAvailableSpells");
+}
+
 } // End of namespace Xeen
diff --git a/engines/xeen/town.h b/engines/xeen/town.h
index df754d5..950d702 100644
--- a/engines/xeen/town.h
+++ b/engines/xeen/town.h
@@ -49,6 +49,11 @@ private:
 	int _v10, _v11, _v12;
 	int _v13, _v14;
 	int _v20;
+	int _v21;
+	uint _v22;
+	int _v23;
+	int _v24;
+	int _dayOfWeek;
 	int _uncurseCost;
 	Common::Point _townPos;
 	int _arr1[6];
@@ -76,11 +81,27 @@ private:
 
 	Character *doTownOptions(Character *c);
 
+	Character *doBankOptions(Character *c);
+
+	Character *doBlacksmithOptions(Character *c);
+
+	Character *doGuildOptions(Character *c);
+
+	Character *doTavernOptions(Character *c);
+
+	Character *doTempleOptions(Character *c);
+
+	Character *doTrainingOptions(Character *c);
+
 	void depositWithdrawl(int choice);
 
 	void notEnough(int consumableId, int whereId, bool mode, ErrorWaitType wait);
 
 	int subtract(int mode, uint amount, int whereId, ErrorWaitType wait);
+
+	Character *showItems(Character *c, int v2);
+
+	Character *showAvailableSpells(Character *c);
 public:
 	Town(XeenEngine *vm);
 


Commit: a755ce6e9215006bbafbcb28f46c30a03b464a4d
    https://github.com/scummvm/scummvm/commit/a755ce6e9215006bbafbcb28f46c30a03b464a4d
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-01-27T22:57:46-05:00

Commit Message:
XEEN: Implement hilight/unhilightChar, bufixes for Tavern display

Changed paths:
    engines/xeen/interface.cpp
    engines/xeen/interface.h
    engines/xeen/town.cpp
    engines/xeen/town.h



diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp
index 0126cd6..ece8ff3 100644
--- a/engines/xeen/interface.cpp
+++ b/engines/xeen/interface.cpp
@@ -781,11 +781,31 @@ void Interface::doFalling() {
 }
 
 void Interface::highlightChar(int charId) {
-	error("TODO: highlightChar");
+	Screen &screen = *_vm->_screen;
+
+	if (charId != _hiliteChar && _hiliteChar != HILIGHT_CHAR_DISABLED) {
+		// Handle deselecting any previusly selected char
+		if (_hiliteChar != -1) {
+			_globalSprites.draw(screen, 9 + _hiliteChar,
+				Common::Point(CHAR_FACES_X[_hiliteChar] - 1, 149));
+		}
+
+		// Highlight new character
+		_globalSprites.draw(screen, 8, Common::Point(CHAR_FACES_X[charId] - 1, 149));
+		_hiliteChar = charId;
+		screen._windows[33].update();
+	}
 }
 
 void Interface::unhighlightChar() {
-	error("TODO: unhighlight");
+	Screen &screen = *_vm->_screen;
+
+	if (_hiliteChar != -1) {
+		_globalSprites.draw(screen, _hiliteChar + 9,
+			Common::Point(CHAR_FACES_X[_hiliteChar] - 1, 149));
+		_hiliteChar = -1;
+		screen._windows[33].update();
+	}
 }
 
 bool Interface::checkMoveDirection(int key) {
diff --git a/engines/xeen/interface.h b/engines/xeen/interface.h
index ab30654..1630e80 100644
--- a/engines/xeen/interface.h
+++ b/engines/xeen/interface.h
@@ -34,6 +34,7 @@ namespace Xeen {
 class XeenEngine;
 
 #define MINIMAP_SIZE 7
+#define HILIGHT_CHAR_DISABLED -2
 
 class Interface: public ButtonContainer, public InterfaceMap {
 private:
diff --git a/engines/xeen/town.cpp b/engines/xeen/town.cpp
index 81cc88b..af93d00 100644
--- a/engines/xeen/town.cpp
+++ b/engines/xeen/town.cpp
@@ -292,9 +292,11 @@ int Town::townWait() {
 	EventsManager &events = *_vm->_events;
 	Interface &intf = *_vm->_interface;
 
+	_buttonValue = 0;
 	while (!_vm->shouldQuit() && !_buttonValue) {
 		events.updateGameCounter();
 		while (!_vm->shouldQuit() && !_buttonValue && events.timeElapsed() < 3) {
+			events.pollEventsAndWait();
 			checkEvents(_vm);
 		}
 		if (!_buttonValue)
@@ -343,7 +345,7 @@ Common::String Town::createTownText(Character &ch) {
 	case 1:
 		// Blacksmith
 		return Common::String::format(BLACKSMITH_TEXT,
-			XeenEngine::printMil(party._gold));
+			XeenEngine::printMil(party._gold).c_str());
 
 	case 2:
 		// Guild
@@ -352,7 +354,7 @@ Common::String Town::createTownText(Character &ch) {
 
 	case 3:
 		// Tavern
-		return Common::String::format(TAVERN_TEXT, ch._name,
+		return Common::String::format(TAVERN_TEXT, ch._name.c_str(),
 			FOOD_AND_DRINK, XeenEngine::printMil(party._gold).c_str());
 
 	case 4:
@@ -564,12 +566,12 @@ Character *Town::doGuildOptions(Character *c) {
 	}
 	else if (_buttonValue == Common::KEYCODE_s) {
 		if (c->guildMember())
-			c = showAvailableSpells(c);
+			c = showAvailableSpells(c, 0x80);
 		_buttonValue = 0;
 	} else if (_buttonValue == Common::KEYCODE_c) {
 		if (!c->noActions()) {
 			if (c->guildMember())
-				c = showAvailableSpells(c);
+				c = showAvailableSpells(c, 0);
 			_buttonValue = 0;
 		}
 	}
@@ -612,7 +614,7 @@ Character *Town::doTavernOptions(Character *c) {
 
 				screen._windows[10].writeString(Common::String::format(TAVERN_TEXT,
 					c->_name.c_str(), GOOD_STUFF,
-					XeenEngine::printMil(party._gold)));
+					XeenEngine::printMil(party._gold).c_str()));
 				drawButtons(&screen._windows[0]);
 				screen._windows[10].update();
 
@@ -728,7 +730,7 @@ Character *Town::doTavernOptions(Character *c) {
 			if (!_v21) {
 				screen._windows[10].writeString(Common::String::format(TAVERN_TEXT,
 					c->_name.c_str(), HAVE_A_DRINK,
-					XeenEngine::printMil(party._gold)));
+					XeenEngine::printMil(party._gold).c_str()));
 				drawButtons(&screen);
 				screen._windows[10].update();
 				townWait();
@@ -737,7 +739,7 @@ Character *Town::doTavernOptions(Character *c) {
 				if (c->_conditions[DRUNK]) {
 					screen._windows[10].writeString(Common::String::format(TAVERN_TEXT,
 						c->_name.c_str(), YOURE_DRUNK,
-						XeenEngine::printMil(party._gold)));
+						XeenEngine::printMil(party._gold).c_str()));
 					drawButtons(&screen);
 					screen._windows[10].update();
 					townWait();
@@ -1036,7 +1038,7 @@ void Town::depositWithdrawl(int choice) {
 
 			sound.playSample(&voc, 0);
 			msg = Common::String::format(GOLD_GEMS_2, DEPOSIT_WITHDRAWL[choice],
-				XeenEngine::printMil(gold), XeenEngine::printMil(gems));
+				XeenEngine::printMil(gold).c_str(), XeenEngine::printMil(gems).c_str());
 			screen._windows[35].writeString(msg);
 			screen._windows[35].update();
 		}
@@ -1120,7 +1122,7 @@ Character *Town::showItems(Character *c, int v2) {
 	error("TODO: showItems");
 }
 
-Character *Town::showAvailableSpells(Character *c) {
+Character *Town::showAvailableSpells(Character *c, int v2) {
 	error("TODO: showAvailableSpells");
 }
 
diff --git a/engines/xeen/town.h b/engines/xeen/town.h
index 950d702..88031ca 100644
--- a/engines/xeen/town.h
+++ b/engines/xeen/town.h
@@ -101,7 +101,7 @@ private:
 
 	Character *showItems(Character *c, int v2);
 
-	Character *showAvailableSpells(Character *c);
+	Character *showAvailableSpells(Character *c, int v2);
 public:
 	Town(XeenEngine *vm);
 


Commit: 8a324eb755cfa07cccfe2c1513522801863643c8
    https://github.com/scummvm/scummvm/commit/8a324eb755cfa07cccfe2c1513522801863643c8
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-01-28T08:46:34-05:00

Commit Message:
XEEN: Implemented drawTownAnim

Changed paths:
    engines/xeen/dialogs_whowill.cpp
    engines/xeen/dialogs_yesno.cpp
    engines/xeen/interface_map.cpp
    engines/xeen/interface_map.h
    engines/xeen/sound.h
    engines/xeen/town.cpp
    engines/xeen/town.h



diff --git a/engines/xeen/dialogs_whowill.cpp b/engines/xeen/dialogs_whowill.cpp
index 042214a..fb845a6 100644
--- a/engines/xeen/dialogs_whowill.cpp
+++ b/engines/xeen/dialogs_whowill.cpp
@@ -41,6 +41,7 @@ int WhoWill::execute(int message, int action, bool type) {
 	Party &party = *_vm->_party;
 	Screen &screen = *_vm->_screen;
 	Scripts &scripts = *_vm->_scripts;
+	Town &town = *_vm->_town;
 	int numFrames;
 
 	if (party._partyCount <= 1)
@@ -65,7 +66,7 @@ int WhoWill::execute(int message, int action, bool type) {
 		events.updateGameCounter();
 
 		if (screen._windows[11]._enabled) {
-			intf.drawTownAnim(0);
+			town.drawTownAnim(0);
 			screen._windows[36].frame();
 			numFrames = 3;
 		} else {
diff --git a/engines/xeen/dialogs_yesno.cpp b/engines/xeen/dialogs_yesno.cpp
index 07de5a5..1c0c3a7 100644
--- a/engines/xeen/dialogs_yesno.cpp
+++ b/engines/xeen/dialogs_yesno.cpp
@@ -39,6 +39,7 @@ bool YesNo::execute(bool type, int v2) {
 	Interface &intf = *_vm->_interface;
 	Map &map = *_vm->_map;
 	Party &party = *_vm->_party;
+	Town &town = *_vm->_town;
 	SpriteResource confirmSprites;
 	int numFrames;
 	bool result = false;
@@ -67,7 +68,7 @@ bool YesNo::execute(bool type, int v2) {
 			intf.draw3d(true);
 			numFrames = 1;
 		} else {
-			intf.drawTownAnim(v2);
+			town.drawTownAnim(v2);
 			numFrames = 3;
 		}
 
diff --git a/engines/xeen/interface_map.cpp b/engines/xeen/interface_map.cpp
index f90d3e3..77a5f92 100644
--- a/engines/xeen/interface_map.cpp
+++ b/engines/xeen/interface_map.cpp
@@ -4964,8 +4964,4 @@ void InterfaceMap::drawMiniMap() {
 	party._wizardEyeActive = eyeActive;
 }
 
-void InterfaceMap::drawTownAnim(bool v) {
-	warning("TODO");
-}
-
 } // End of namespace Xeen
diff --git a/engines/xeen/interface_map.h b/engines/xeen/interface_map.h
index 153abba..fb448e1 100644
--- a/engines/xeen/interface_map.h
+++ b/engines/xeen/interface_map.h
@@ -165,8 +165,6 @@ public:
 
 	void drawOutdoors();
 
-	void drawTownAnim(bool v);
-
 	void assembleBorder();
 };
 
diff --git a/engines/xeen/sound.h b/engines/xeen/sound.h
index b6f1948..7e7df9c 100644
--- a/engines/xeen/sound.h
+++ b/engines/xeen/sound.h
@@ -45,6 +45,8 @@ public:
 
 	void playSample(const Common::SeekableReadStream *stream, int v2 = 1) {}
 
+	bool playSample(int v1, int v2) { return false; }
+
 	void playFX(int id) {}
 };
 
diff --git a/engines/xeen/town.cpp b/engines/xeen/town.cpp
index af93d00..328301a 100644
--- a/engines/xeen/town.cpp
+++ b/engines/xeen/town.cpp
@@ -51,6 +51,7 @@ Town::Town(XeenEngine *vm) : _vm(vm) {
 	_uncurseCost = 0;
 	_flag1 = false;
 	_nextExperienceLevel = 0;
+	_drawCtr1 = _drawCtr2 = 0;
 }
 
 void Town::loadStrings(const Common::String &name) {
@@ -231,7 +232,7 @@ int Town::townAction(int actionId) {
 
 	screen._windows[0].update();
 	intf.highlightChar(0);
-	intf.drawTownAnim(1);
+	drawTownAnim(1);
 
 	if (actionId == 0)
 		intf._overallFrame = 2;
@@ -290,7 +291,6 @@ int Town::townAction(int actionId) {
 
 int Town::townWait() {
 	EventsManager &events = *_vm->_events;
-	Interface &intf = *_vm->_interface;
 
 	_buttonValue = 0;
 	while (!_vm->shouldQuit() && !_buttonValue) {
@@ -300,7 +300,7 @@ int Town::townWait() {
 			checkEvents(_vm);
 		}
 		if (!_buttonValue)
-			intf.drawTownAnim(!_vm->_screen->_windows[11]._enabled);
+			drawTownAnim(!_vm->_screen->_windows[11]._enabled);
 	}
 
 	return _buttonValue;
@@ -1118,6 +1118,136 @@ int Town::subtract(int mode, uint amount, int whereId, ErrorWaitType wait) {
 	return true;
 }
 
+void Town::drawTownAnim(bool flag) {
+	Interface &intf = *_vm->_interface;
+	Screen &screen = *_vm->_screen;
+	SoundManager &sound = *_vm->_sound;
+	bool isDarkCc = _vm->_files->_isDarkCc;
+
+	if (_townActionId == 1) {
+		if (sound.playSample(1, 0)) {
+			if (isDarkCc) {
+				_townSprites[_townCurrent / 8].draw(screen, _townCurrent % 8, _townPos);
+				_townSprites[2].draw(screen, _vm->getRandomNumber(11) == 1 ? 9 : 10,
+					Common::Point(34, 33));
+				_townSprites[2].draw(screen, _vm->getRandomNumber(5) + 3,
+					Common::Point(34, 54));
+			}
+		} else {
+			_townSprites[_townCurrent / 8].draw(screen, _townCurrent % 8, _townPos);
+			if (isDarkCc) {
+				_townSprites[2].draw(screen, _vm->getRandomNumber(11) == 1 ? 9 : 10,
+					Common::Point(34, 33));
+			}
+		}
+	} else {
+		if (!isDarkCc || _townActionId != 5) {
+			if (!_townSprites[_townCurrent / 8].empty())
+				_townSprites[_townCurrent / 8].draw(screen, _townCurrent % 8, _townPos);
+		}
+	}
+
+	switch (_townActionId) {
+	case 0:
+		if (sound.playSample(1, 0) || (isDarkCc && intf._overallFrame)) {
+			if (isDarkCc) {
+				if (sound.playSample(1, 0) || intf._overallFrame == 1) {
+					_townSprites[4].draw(screen, _vm->getRandomNumber(13, 18),
+						Common::Point(8, 30));
+				} else if (intf._overallFrame > 1) {
+					_townSprites[4].draw(screen, 13 - intf._overallFrame++,
+						Common::Point(8, 30));
+					if (intf._overallFrame > 14)
+						intf._overallFrame = 0;
+				}
+			} else {
+				_townSprites[2].draw(screen, _vm->getRandomNumber(7, 11), Common::Point(8, 8));
+			}
+		}
+		break;
+
+	case 2:
+		if (sound.playSample(1, 0)) {
+			if (isDarkCc) {
+				if (intf._overallFrame) {
+					intf._overallFrame ^= 1;
+					_townSprites[6].draw(screen, intf._overallFrame, Common::Point(8, 106));
+				} else {
+					_townSprites[6].draw(screen, _vm->getRandomNumber(3), Common::Point(16, 48));
+				}
+			}
+		}
+		break;
+
+	case 3:
+		if (sound.playSample(1, 0) && isDarkCc) {
+			_townSprites[4].draw(screen, _vm->getRandomNumber(7), Common::Point(153, 49));
+		}
+		break;
+	case 4:
+		if (sound.playSample(1, 0)) {
+			_townSprites[3].draw(screen, _vm->getRandomNumber(2, 4), Common::Point(8, 8));
+
+		}
+		break;
+
+	case 5:
+		if (sound.playSample(1, 0)) {
+			if (isDarkCc) {
+				_townSprites[_townCurrent / 8].draw(screen, _townCurrent % 8, _townPos);
+			}
+		} else {
+			if (isDarkCc) {
+				_townSprites[0].draw(screen, ++intf._overallFrame % 8, Common::Point(8, 8));
+				_townSprites[5].draw(screen, _vm->getRandomNumber(5), Common::Point(61, 74));
+			} else {
+				_townSprites[1].draw(screen, _vm->getRandomNumber(8, 12), Common::Point(8, 8));
+			}
+		}
+	}
+
+	if (flag) {
+		intf._face1UIFrame = 0;
+		intf._face2UIFrame = 0;
+		intf._dangerSenseUIFrame = 0;
+		intf._spotDoorsUIFrame = 0;
+		intf._batUIFrame = 0;
+
+		intf.assembleBorder();
+	}
+
+	if (screen._windows[11]._enabled) {
+		_drawCtr1 = (_drawCtr1 + 1) % 2;
+		if (!_drawCtr1 || !_drawCtr2) {
+			_townCurrent = 0;
+			_drawCtr2 = 0;
+		} else {
+			_townCurrent = _vm->getRandomNumber(3);
+		}
+	} else {
+		_townCurrent = (_townCurrent + 1) % _townMaxId;
+	}
+
+	if (isDarkCc) {
+		if (_townActionId == 1 && (_townCurrent == 4 || _townCurrent == 13))
+			sound.playFX(45);
+
+		if (_townActionId == 5 && _townCurrent == 23) {
+			File f("spit1.voc");
+			sound.playSample(&f, 0);
+		}
+	} else {
+		if (_townMaxId == 32 || _townCurrent == 0)
+			_townCurrent = 17;
+		if (_townMaxId == 26 || _townCurrent == 0)
+			_townCurrent = 20;
+		if (_townActionId == 1 && (_townCurrent == 3 || _townCurrent == 9))
+			sound.playFX(45);
+	}
+
+	screen._windows[3].update();
+}
+
 Character *Town::showItems(Character *c, int v2) {
 	error("TODO: showItems");
 }
diff --git a/engines/xeen/town.h b/engines/xeen/town.h
index 88031ca..e28d03c 100644
--- a/engines/xeen/town.h
+++ b/engines/xeen/town.h
@@ -60,6 +60,7 @@ private:
 	int _currentCharLevel;
 	bool _flag1;
 	uint _nextExperienceLevel;
+	int _drawCtr1, _drawCtr2;
 
 	void loadStrings(const Common::String &name);
 
@@ -106,6 +107,8 @@ public:
 	Town(XeenEngine *vm);
 
 	int townAction(int actionId);
+
+	void drawTownAnim(bool flag);
 };
 
 } // End of namespace Xeen


Commit: 5228879a1dfa2684ee71fe0577eb98dbbc92d55a
    https://github.com/scummvm/scummvm/commit/5228879a1dfa2684ee71fe0577eb98dbbc92d55a
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-01-28T19:22:54-05:00

Commit Message:
XEEN: Fix for entering/exiting tavern display

Changed paths:
    engines/xeen/scripts.cpp
    engines/xeen/town.cpp
    engines/xeen/town.h



diff --git a/engines/xeen/scripts.cpp b/engines/xeen/scripts.cpp
index c84ec91..11f8804 100644
--- a/engines/xeen/scripts.cpp
+++ b/engines/xeen/scripts.cpp
@@ -158,6 +158,7 @@ bool Scripts::checkEvents() {
 						(_currentPos.x | _currentPos.y) && event._line == _lineNum) {
 					if (event._direction == party._mazeDirection || event._direction == DIR_ALL) {
 						_vm->_mode = MODE_9;
+						_scriptExecuted = true;
 						doOpcode(event);
 						break;
 					} else {
@@ -517,7 +518,8 @@ void Scripts::cmdSpawn(Common::Array<byte> &params) {
 void Scripts::cmdDoTownEvent(Common::Array<byte> &params) {
 	_scriptResult = _vm->_town->townAction(params[0]);
 	_vm->_party->_stepped = true;
-	
+	_refreshIcons = true;
+
 	cmdExit(params);
 }
 
diff --git a/engines/xeen/town.cpp b/engines/xeen/town.cpp
index 328301a..a1b0971 100644
--- a/engines/xeen/town.cpp
+++ b/engines/xeen/town.cpp
@@ -32,7 +32,7 @@ Town::Town(XeenEngine *vm) : _vm(vm) {
 	Common::fill(&_arr1[0], &_arr1[6], 0);
 	_townMaxId = 0;
 	_townActionId = 0;
-	_townCurrent = 0;
+	_drawFrameIndex = 0;
 	_currentCharLevel = 0;
 	_v1 = 0;
 	_v2 = 0;
@@ -77,7 +77,7 @@ int Town::townAction(int actionId) {
 
 	_townMaxId = TOWN_MAXES[_vm->_files->_isDarkCc][actionId];
 	_townActionId = actionId;
-	_townCurrent = 0;
+	_drawFrameIndex = 0;
 	_v1 = 0;
 	_townPos = Common::Point(8, 8);
 	intf._overallFrame = 0;
@@ -217,7 +217,7 @@ int Town::townAction(int actionId) {
 	intf._spotDoorsUIFrame = 0;
 	intf._batUIFrame = 0;
 
-	_townSprites[_townCurrent / 8].draw(screen, _townCurrent % 8, _townPos);
+	_townSprites[_drawFrameIndex / 8].draw(screen, _drawFrameIndex % 8, _townPos);
 	if (actionId == 0 && isDarkCc) {
 		_townSprites[4].draw(screen, _vm->getRandomNumber(13, 18),
 			Common::Point(8, 30));
@@ -907,7 +907,7 @@ Character *Town::doTrainingOptions(Character *c) {
 	case Common::KEYCODE_t:
 		if (_nextExperienceLevel) {
 			sound.playSample(nullptr, 0);
-			_townCurrent = 0;
+			_drawFrameIndex = 0;
 
 			Common::String name;
 			if (c->_level._permanent >= _v20) {
@@ -921,7 +921,7 @@ Character *Town::doTrainingOptions(Character *c) {
 
 		} else if (!c->noActions()) {
 			if (subtract(0, (c->_level._permanent * c->_level._permanent) * 10, 0, WT_2)) {
-				_townCurrent = 0;
+				_drawFrameIndex = 0;
 				sound.playSample(nullptr, 0);
 				File f(isDarkCc ? "prtygd.voc" : "trainin2.voc");
 				sound.playSample(&f, 1);
@@ -1127,14 +1127,14 @@ void Town::drawTownAnim(bool flag) {
 	if (_townActionId == 1) {
 		if (sound.playSample(1, 0)) {
 			if (isDarkCc) {
-				_townSprites[_townCurrent / 8].draw(screen, _townCurrent % 8, _townPos);
+				_townSprites[_drawFrameIndex / 8].draw(screen, _drawFrameIndex % 8, _townPos);
 				_townSprites[2].draw(screen, _vm->getRandomNumber(11) == 1 ? 9 : 10,
 					Common::Point(34, 33));
 				_townSprites[2].draw(screen, _vm->getRandomNumber(5) + 3,
 					Common::Point(34, 54));
 			}
 		} else {
-			_townSprites[_townCurrent / 8].draw(screen, _townCurrent % 8, _townPos);
+			_townSprites[_drawFrameIndex / 8].draw(screen, _drawFrameIndex % 8, _townPos);
 			if (isDarkCc) {
 				_townSprites[2].draw(screen, _vm->getRandomNumber(11) == 1 ? 9 : 10,
 					Common::Point(34, 33));
@@ -1142,8 +1142,8 @@ void Town::drawTownAnim(bool flag) {
 		}
 	} else {
 		if (!isDarkCc || _townActionId != 5) {
-			if (!_townSprites[_townCurrent / 8].empty())
-				_townSprites[_townCurrent / 8].draw(screen, _townCurrent % 8, _townPos);
+			if (!_townSprites[_drawFrameIndex / 8].empty())
+				_townSprites[_drawFrameIndex / 8].draw(screen, _drawFrameIndex % 8, _townPos);
 		}
 	}
 
@@ -1194,7 +1194,7 @@ void Town::drawTownAnim(bool flag) {
 	case 5:
 		if (sound.playSample(1, 0)) {
 			if (isDarkCc) {
-				_townSprites[_townCurrent / 8].draw(screen, _townCurrent % 8, _townPos);
+				_townSprites[_drawFrameIndex / 8].draw(screen, _drawFrameIndex % 8, _townPos);
 			}
 		} else {
 			if (isDarkCc) {
@@ -1219,29 +1219,29 @@ void Town::drawTownAnim(bool flag) {
 	if (screen._windows[11]._enabled) {
 		_drawCtr1 = (_drawCtr1 + 1) % 2;
 		if (!_drawCtr1 || !_drawCtr2) {
-			_townCurrent = 0;
+			_drawFrameIndex = 0;
 			_drawCtr2 = 0;
 		} else {
-			_townCurrent = _vm->getRandomNumber(3);
+			_drawFrameIndex = _vm->getRandomNumber(3);
 		}
 	} else {
-		_townCurrent = (_townCurrent + 1) % _townMaxId;
+		_drawFrameIndex = (_drawFrameIndex + 1) % _townMaxId;
 	}
 
 	if (isDarkCc) {
-		if (_townActionId == 1 && (_townCurrent == 4 || _townCurrent == 13))
+		if (_townActionId == 1 && (_drawFrameIndex == 4 || _drawFrameIndex == 13))
 			sound.playFX(45);
 
-		if (_townActionId == 5 && _townCurrent == 23) {
+		if (_townActionId == 5 && _drawFrameIndex == 23) {
 			File f("spit1.voc");
 			sound.playSample(&f, 0);
 		}
 	} else {
-		if (_townMaxId == 32 || _townCurrent == 0)
-			_townCurrent = 17;
-		if (_townMaxId == 26 || _townCurrent == 0)
-			_townCurrent = 20;
-		if (_townActionId == 1 && (_townCurrent == 3 || _townCurrent == 9))
+		if (_townMaxId == 32 && _drawFrameIndex == 0)
+			_drawFrameIndex = 17;
+		if (_townMaxId == 26 && _drawFrameIndex == 0)
+			_drawFrameIndex = 20;
+		if (_townActionId == 1 && (_drawFrameIndex == 3 || _drawFrameIndex == 9))
 			sound.playFX(45);
 	}
 
diff --git a/engines/xeen/town.h b/engines/xeen/town.h
index e28d03c..af3f4c3 100644
--- a/engines/xeen/town.h
+++ b/engines/xeen/town.h
@@ -41,7 +41,6 @@ private:
 	Common::Array<SpriteResource> _townSprites;
 	int _townMaxId;
 	int _townActionId;
-	int _townCurrent;
 	int _v1, _v2;
 	int _donation;
 	int _healCost;
@@ -60,6 +59,7 @@ private:
 	int _currentCharLevel;
 	bool _flag1;
 	uint _nextExperienceLevel;
+	int _drawFrameIndex;
 	int _drawCtr1, _drawCtr2;
 
 	void loadStrings(const Common::String &name);


Commit: 16b8382d6e72c72d567b44bca8cf0d48a4280366
    https://github.com/scummvm/scummvm/commit/16b8382d6e72c72d567b44bca8cf0d48a4280366
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-01-28T20:09:15-05:00

Commit Message:
XEEN: Fix display of buy message for buying tavern food

Changed paths:
    engines/xeen/screen.cpp
    engines/xeen/town.cpp



diff --git a/engines/xeen/screen.cpp b/engines/xeen/screen.cpp
index 87062dc..e979143 100644
--- a/engines/xeen/screen.cpp
+++ b/engines/xeen/screen.cpp
@@ -63,6 +63,15 @@ void Window::open2() {
 	addDirtyRect(_bounds);
 	frame();
 	fill();
+
+	Screen &screen = *_vm->_screen;
+	screen._writePos.x = _bounds.right - 8;
+	screen.writeSymbol(19);
+
+	screen._writePos.x = _innerBounds.left;
+	screen._writePos.y = _innerBounds.top;
+	screen._fontJustify = JUSTIFY_NONE;
+	screen._fontReduced = false;
 }
 
 void Window::frame() {
diff --git a/engines/xeen/town.cpp b/engines/xeen/town.cpp
index a1b0971..b28300f 100644
--- a/engines/xeen/town.cpp
+++ b/engines/xeen/town.cpp
@@ -659,6 +659,7 @@ Character *Town::doTavernOptions(Character *c) {
 		screen._windows[10].close();
 		screen._windows[12].open();
 		screen._windows[12].writeString(msg);
+		screen._windows[12].update();
 
 		if (YesNo::show(_vm, false, true)) {
 			if (party._food >= _v22) {


Commit: 1f28332b2053f2dbbe138937f9b0e342774a4cc9
    https://github.com/scummvm/scummvm/commit/1f28332b2053f2dbbe138937f9b0e342774a4cc9
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-01-28T20:59:01-05:00

Commit Message:
XEEN: Add saving/restoring of background when opening/closing windows

Changed paths:
    engines/xeen/screen.cpp
    engines/xeen/screen.h



diff --git a/engines/xeen/screen.cpp b/engines/xeen/screen.cpp
index e979143..9c9783b 100644
--- a/engines/xeen/screen.cpp
+++ b/engines/xeen/screen.cpp
@@ -60,11 +60,17 @@ void Window::open() {
 }
 
 void Window::open2() {
+	Screen &screen = *_vm->_screen;
+
+	// Save a copy of the area under the window
+	_savedArea.create(_bounds.width(), _bounds.height());
+	_savedArea.copyRectToSurface(screen, 0, 0, _bounds);
+
+	// Mark the area as dirty and fill it with a default background
 	addDirtyRect(_bounds);
 	frame();
 	fill();
 
-	Screen &screen = *_vm->_screen;
 	screen._writePos.x = _bounds.right - 8;
 	screen.writeSymbol(19);
 
@@ -130,11 +136,17 @@ void Window::frame() {
 }
 
 void Window::close() {
+	Screen &screen = *_vm->_screen;
+
 	if (_enabled) {
-		// Update any remaining pending changes to the screen and free
-		// the window's internal surface storage
+		// Update the window
 		update();
 
+		// Restore the saved original content
+		screen.copyRectToSurface(_savedArea, _bounds.left, _bounds.top,
+			Common::Rect(0, 0, _bounds.width(), _bounds.height()));
+		addDirtyRect(_bounds);
+
 		// Remove the window from the stack and flag it as now disabled
 		for (uint i = 0; i < _vm->_screen->_windowStack.size(); ++i) {
 			if (_vm->_screen->_windowStack[i] == this)
diff --git a/engines/xeen/screen.h b/engines/xeen/screen.h
index 85affe3..e3ced06 100644
--- a/engines/xeen/screen.h
+++ b/engines/xeen/screen.h
@@ -61,6 +61,7 @@ private:
 	XeenEngine *_vm;
 	Common::Rect _bounds;
 	Common::Rect _innerBounds;
+	XSurface _savedArea;
 	int _a;
 	int _border;
 	int _xLo, _xHi;


Commit: 60c462bfdcb9cb342ccb3367b64c599144f70e57
    https://github.com/scummvm/scummvm/commit/60c462bfdcb9cb342ccb3367b64c599144f70e57
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-01-28T20:59:36-05:00

Commit Message:
XEEN: Fixes for tavern options

Changed paths:
    engines/xeen/dialogs_yesno.cpp
    engines/xeen/dialogs_yesno.h
    engines/xeen/interface.h
    engines/xeen/scripts.cpp
    engines/xeen/town.cpp
    engines/xeen/town.h



diff --git a/engines/xeen/dialogs_yesno.cpp b/engines/xeen/dialogs_yesno.cpp
index 1c0c3a7..8ea27eb 100644
--- a/engines/xeen/dialogs_yesno.cpp
+++ b/engines/xeen/dialogs_yesno.cpp
@@ -33,7 +33,7 @@ bool YesNo::show(XeenEngine *vm, bool type, bool v2) {
 	return result;
 }
 
-bool YesNo::execute(bool type, int v2) {
+bool YesNo::execute(bool type, bool townFlag) {
 	Screen &screen = *_vm->_screen;
 	EventsManager &events = *_vm->_events;
 	Interface &intf = *_vm->_interface;
@@ -64,12 +64,12 @@ bool YesNo::execute(bool type, int v2) {
 	while (!_vm->shouldQuit()) {
 		events.updateGameCounter();
 		
-		if (intf._townSprites[0].empty()) {
+		if (town.isActive()) {
+			town.drawTownAnim(townFlag);
+			numFrames = 3;
+		} else {
 			intf.draw3d(true);
 			numFrames = 1;
-		} else {
-			town.drawTownAnim(v2);
-			numFrames = 3;
 		}
 
 		events.wait(3, true);
diff --git a/engines/xeen/dialogs_yesno.h b/engines/xeen/dialogs_yesno.h
index d083cd6..96c3592 100644
--- a/engines/xeen/dialogs_yesno.h
+++ b/engines/xeen/dialogs_yesno.h
@@ -33,9 +33,9 @@ private:
 
 	YesNo(XeenEngine *vm) : ButtonContainer(), _vm(vm) {}
 
-	bool execute(bool type, int v2);
+	bool execute(bool type, bool townFlag);
 public:
-	static bool show(XeenEngine *vm, bool type, bool v2);
+	static bool show(XeenEngine *vm, bool type, bool townFlag = false);
 };
 
 } // End of namespace Xeen
diff --git a/engines/xeen/interface.h b/engines/xeen/interface.h
index 1630e80..73cd509 100644
--- a/engines/xeen/interface.h
+++ b/engines/xeen/interface.h
@@ -76,7 +76,6 @@ private:
 
 	bool checkMoveDirection(int key);
 public:
-	SpriteResource _townSprites[8];
 	int _intrIndex1;
 	Common::String _interfaceText;
 public:
diff --git a/engines/xeen/scripts.cpp b/engines/xeen/scripts.cpp
index 11f8804..3ba6329 100644
--- a/engines/xeen/scripts.cpp
+++ b/engines/xeen/scripts.cpp
@@ -1079,7 +1079,7 @@ bool Scripts::ifProc(int action, uint32 mask, int mode, int charIndex) {
 		v = ps._luck._temporary;
 		break;
 	case 44:
-		v = YesNo::show(_vm, mask, false);
+		v = YesNo::show(_vm, mask);
 		v = (!v && !mask) ? 2 : mask;
 		break;
 	case 45:
diff --git a/engines/xeen/town.cpp b/engines/xeen/town.cpp
index b28300f..303ef50 100644
--- a/engines/xeen/town.cpp
+++ b/engines/xeen/town.cpp
@@ -1249,6 +1249,13 @@ void Town::drawTownAnim(bool flag) {
 	screen._windows[3].update();
 }
 
+/**
+ * Returns true if a town location (bank, blacksmith, etc.) is currently active
+ */
+bool Town::isActive() const {
+	return _townSprites.size() > 0 && !_townSprites[0].empty();
+}
+
 Character *Town::showItems(Character *c, int v2) {
 	error("TODO: showItems");
 }
diff --git a/engines/xeen/town.h b/engines/xeen/town.h
index af3f4c3..f6c67ab 100644
--- a/engines/xeen/town.h
+++ b/engines/xeen/town.h
@@ -109,6 +109,8 @@ public:
 	int townAction(int actionId);
 
 	void drawTownAnim(bool flag);
+
+	bool isActive() const;
 };
 
 } // End of namespace Xeen


Commit: e34429207c9d632a1f72680a08409992e81d95a5
    https://github.com/scummvm/scummvm/commit/e34429207c9d632a1f72680a08409992e81d95a5
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-01-28T21:11:46-05:00

Commit Message:
XEEN: Add missing c_str to a Common::String::format call

Changed paths:
    engines/xeen/town.cpp



diff --git a/engines/xeen/town.cpp b/engines/xeen/town.cpp
index 303ef50..f90ffbd 100644
--- a/engines/xeen/town.cpp
+++ b/engines/xeen/town.cpp
@@ -688,7 +688,7 @@ Character *Town::doTavernOptions(Character *c) {
 		}
 
 		Common::String msg = Common::String::format("\x03""c\x0B""012%s",
-			_textStrings[(party._day % 10) + idx]);
+			_textStrings[(party._day % 10) + idx].c_str());
 		Window &w = screen._windows[12];
 		w.open();
 		w.writeString(msg);


Commit: be327cb7672652a44294a13b9fa4215ae6358b6a
    https://github.com/scummvm/scummvm/commit/be327cb7672652a44294a13b9fa4215ae6358b6a
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-01-29T08:42:31-05:00

Commit Message:
XEEN: Implemented setSpellText for spells dialog

Changed paths:
    engines/xeen/module.mk
    engines/xeen/party.cpp
    engines/xeen/party.h
    engines/xeen/resources.cpp
    engines/xeen/resources.h
    engines/xeen/spells.cpp
    engines/xeen/spells.h
    engines/xeen/town.cpp
    engines/xeen/town.h



diff --git a/engines/xeen/module.mk b/engines/xeen/module.mk
index c361c47..9d252b1 100644
--- a/engines/xeen/module.mk
+++ b/engines/xeen/module.mk
@@ -11,6 +11,7 @@ MODULE_OBJS := \
 	dialogs_error.o \
 	dialogs_options.o \
 	dialogs_input.o \
+	dialogs_spells.o \
 	dialogs_whowill.o \
 	dialogs_yesno.o \
 	events.o \
diff --git a/engines/xeen/party.cpp b/engines/xeen/party.cpp
index 66ba405..2138ca6 100644
--- a/engines/xeen/party.cpp
+++ b/engines/xeen/party.cpp
@@ -27,6 +27,7 @@
 #include "xeen/files.h"
 #include "xeen/resources.h"
 #include "xeen/saves.h"
+#include "xeen/spells.h"
 #include "xeen/xeen.h"
 
 namespace Xeen {
@@ -52,7 +53,7 @@ Character::Character() {
 	_tempAge = 0;
 	Common::fill(&_skills[0], &_skills[18], 0);
 	Common::fill(&_awards[0], &_awards[128], false);
-	Common::fill(&_spells[9], &_spells[312], false);
+	Common::fill(&_spells[0], &_spells[39], 0);
 	_lloydMap = 0;
 	_hasSpells = false;
 	_currentSpell = 0;
@@ -110,8 +111,8 @@ void Character::synchronize(Common::Serializer &s) {
 	}
 
 	// Synchronize spell list
-	SavesManager::syncBitFlags(s, &_spells[0], &_spells[312]);
-	
+	for (int i = 0; i < MAX_SPELLS_PER_CLASS - 1; ++i)
+		s.syncAsByte(_spells[i]);	
 	s.syncAsByte(_lloydMap);
 	s.syncAsByte(_lloydPosition.x);
 	s.syncAsByte(_lloydPosition.y);
diff --git a/engines/xeen/party.h b/engines/xeen/party.h
index 10f4027..035e76c 100644
--- a/engines/xeen/party.h
+++ b/engines/xeen/party.h
@@ -108,7 +108,7 @@ public:
 	int _tempAge;
 	int _skills[18];
 	bool _awards[128];
-	bool _spells[312];
+	int _spells[39];
 	int _lloydMap;
 	Common::Point _lloydPosition;
 	bool _hasSpells;
diff --git a/engines/xeen/resources.cpp b/engines/xeen/resources.cpp
index 5eec5be..57e16d7 100644
--- a/engines/xeen/resources.cpp
+++ b/engines/xeen/resources.cpp
@@ -713,4 +713,74 @@ const char *const AMOUNT = "\x03""c\x09""000\x0B""051Amount\x03l\n";
 
 const char *const FOOD_PACKS_FULL = "\v007Your food packs are already full!";
 
+const char *const BUY_SPELLS =
+	"\x03""c\x0B""027\x09""039%s\x03l\x0B""046\n"
+	"\x09""012\x0C""37B\x0C""duy Spells\n"
+	"\x09""012\x0C""37S\x0C""dpell Info";
+
+const char *const GUILD_OPTIONS = 
+	"\x0D\x0C""00\x03""c\x0B""000\x09""000Guild Options for%s"
+	"\x03l\x09""000\x0B""090Gold"
+	"\x03r\x09""000%s\x02\x03""c\x0B""122\x09""040ESC\x01";
+
+const int SPELL_COSTS[77] = {
+	8, 1, 5, -2, 5, -2, 20, 10, 12, 8, 3,
+	- 3, 75, 40, 12, 6, 200, 10, 100, 30, -1, 30,
+	15, 25, 10, -2, 1, 2, 7, 20, -2, -2, 100,
+	15, 5, 100, 35, 75, 5, 20, 4, 5, 1, -2,
+	6, 2, 75, 40, 60, 6, 4, 25, -2, -2, 60,
+	- 1, 50, 15, 125, 2, -1, 3, -1, 200, 35, 150,
+	15, 5, 4, 10, 8, 30, 4, 5, 7, 5, 0
+};
+
+const int DARK_SPELL_RANGES[12][2] = {
+	{ 0, 20 }, { 16, 35 }, { 27, 37 }, { 29, 39 }, 
+	{ 0, 17 }, { 14, 34 }, { 26, 37 }, { 29, 39 }, 
+	{ 0, 20 }, { 16, 35 }, { 27, 37 }, { 29, 39 }
+};
+
+const int CLOUDS_SPELL_OFFSETS[5][20] = {
+	{
+		1, 10, 20, 26, 27, 38, 40, 42, 45, 50,
+		55, 59, 60, 61, 62, 68, 72, 75, 77, 77
+	}, {
+		3, 4, 5, 14, 15, 25, 30, 31, 34, 41,
+		49, 51, 53, 67, 73, 75, -1, -1, -1, -1
+	}, {
+		4, 8, 9, 12, 13, 22, 23, 24, 28, 34,
+		41, 44, 52, 70, 73, 74, -1, -1, -1, -1
+	}, {
+		6, 7, 9, 11, 12, 13, 17, 21, 22, 24,
+		29, 36, 56, 58, 64, 71, -1, -1, -1, -1
+	}, {
+		6, 7, 9, 11, 12, 13, 18, 21, 29, 32,
+		36, 37, 46, 51, 56, 58, 69, -1, -1, -1
+	}
+};
+
+const int DARK_SPELL_OFFSETS[3][39] = {
+	{
+		42, 1, 26, 59, 27, 10, 50, 68, 55, 62, 67, 73, 2,
+		5, 3, 31, 30, 52, 49, 28, 74, 0, 9, 7, 14, 8,
+		33, 6, 23, 71, 64, 56, 48, 46, 12, 32, 58, 65, 16
+	}, {
+		42, 1, 45, 61, 72, 40, 20, 60, 38, 41, 75, 34, 4,
+		43, 25, 53, 44, 15, 70, 17, 24, 69, 22, 66, 57, 11,
+		29, 39, 51, 21, 19, 36, 47, 13, 54, 37, 18, 35, 63
+	}, {
+		0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
+		13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,
+		26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38
+	}
+};
+
+const int SPELL_GEM_COST[77] = {
+	0, 0, 2, 1, 2, 4, 5, 0, 0, 0, 0, 10, 10, 10, 0, 0, 20, 4, 10, 20, 1, 10,
+	5, 5, 4, 2, 0, 0, 0, 10, 3, 1, 20, 4, 0, 20, 10, 10, 1, 10, 0, 0, 0, 2,
+	2, 0, 10, 10, 10, 0, 0, 10, 3, 2, 10, 1, 10, 10, 20, 0, 0, 1, 1, 20, 5, 20,
+	5, 0, 0, 0, 0, 5, 1, 2, 0, 2, 0
+};
+
+extern const char *NOT_A_SPELL_CASTER = "Not a spell caster...";
+
 } // End of namespace Xeen
diff --git a/engines/xeen/resources.h b/engines/xeen/resources.h
index 497b025..60f4848 100644
--- a/engines/xeen/resources.h
+++ b/engines/xeen/resources.h
@@ -210,6 +210,24 @@ extern const char *const AMOUNT;
 
 extern const char *const FOOD_PACKS_FULL;
 
+extern const char *const BUY_SPELLS;
+
+extern const char *const GUILD_OPTIONS;
+
+extern const int SPELL_COSTS[77];
+
+extern const int CLOUDS_SPELL_OFFSETS[5][20];
+
+extern const int DARK_SPELL_OFFSETS[3][39];
+
+extern const int DARK_SPELL_RANGES[12][2];
+
+extern const int SPELL_LEVEL_OFFSETS[3][39];
+
+extern const int SPELL_GEM_COST[77];
+
+extern const char *NOT_A_SPELL_CASTER;
+
 } // End of namespace Xeen
 
 #endif	/* XEEN_RESOURCES_H */
diff --git a/engines/xeen/spells.cpp b/engines/xeen/spells.cpp
index 29c22b1..922f6fc 100644
--- a/engines/xeen/spells.cpp
+++ b/engines/xeen/spells.cpp
@@ -22,6 +22,7 @@
 
 #include "xeen/spells.h"
 #include "xeen/files.h"
+#include "xeen/resources.h"
 #include "xeen/xeen.h"
 
 namespace Xeen {
@@ -42,4 +43,15 @@ void Spells::load() {
 	f2.close();
 }
 
+int Spells::calcSpellCost(int spellId, int expenseFactor) const {
+	int amount = SPELL_COSTS[spellId];
+	return (amount >= 0) ? (amount * 100) << expenseFactor :
+		(amount * -500) << expenseFactor;
+}
+
+int Spells::calcSpellPoints(int spellId, int expenseFactor) const {
+	int amount = SPELL_COSTS[spellId];
+	return (amount >= 0) ? amount : amount * -1 * expenseFactor;
+}
+
 } // End of namespace Xeen
diff --git a/engines/xeen/spells.h b/engines/xeen/spells.h
index 48c0f9a..97e3c80 100644
--- a/engines/xeen/spells.h
+++ b/engines/xeen/spells.h
@@ -30,6 +30,8 @@ namespace Xeen {
 
 class XeenEngine;
 
+#define MAX_SPELLS_PER_CLASS 40
+
 class Spells {
 private:
 	XeenEngine *_vm;
@@ -40,6 +42,11 @@ public:
 	Common::StringArray _maeNames;
 public:
 	Spells(XeenEngine *vm);
+
+	int calcSpellCost(int spellId, int expenseFactor) const;
+
+	int calcSpellPoints(int spellId, int expenseFactor) const;
+
 };
 
 } // End of namespace Xeen
diff --git a/engines/xeen/town.cpp b/engines/xeen/town.cpp
index f90ffbd..d773f6d 100644
--- a/engines/xeen/town.cpp
+++ b/engines/xeen/town.cpp
@@ -23,6 +23,7 @@
 #include "xeen/town.h"
 #include "xeen/dialogs_input.h"
 #include "xeen/dialogs_yesno.h"
+#include "xeen/dialogs_spells.h"
 #include "xeen/resources.h"
 #include "xeen/xeen.h"
 
@@ -563,15 +564,14 @@ Character *Town::doGuildOptions(Character *c) {
 				sound.playSample(&f, 1);
 			}
 		}
-	}
-	else if (_buttonValue == Common::KEYCODE_s) {
+	} else if (_buttonValue == Common::KEYCODE_s) {
 		if (c->guildMember())
-			c = showAvailableSpells(c, 0x80);
+			c = SpellsScroll::show(_vm, c, 0x80);
 		_buttonValue = 0;
 	} else if (_buttonValue == Common::KEYCODE_c) {
 		if (!c->noActions()) {
 			if (c->guildMember())
-				c = showAvailableSpells(c, 0);
+				c = SpellsScroll::show(_vm, c, 0);
 			_buttonValue = 0;
 		}
 	}
@@ -1260,8 +1260,4 @@ Character *Town::showItems(Character *c, int v2) {
 	error("TODO: showItems");
 }
 
-Character *Town::showAvailableSpells(Character *c, int v2) {
-	error("TODO: showAvailableSpells");
-}
-
 } // End of namespace Xeen
diff --git a/engines/xeen/town.h b/engines/xeen/town.h
index f6c67ab..27b1fe2 100644
--- a/engines/xeen/town.h
+++ b/engines/xeen/town.h
@@ -101,8 +101,6 @@ private:
 	int subtract(int mode, uint amount, int whereId, ErrorWaitType wait);
 
 	Character *showItems(Character *c, int v2);
-
-	Character *showAvailableSpells(Character *c, int v2);
 public:
 	Town(XeenEngine *vm);
 


Commit: 29753a29a4b82d8cac78223232dc84c003d8f210
    https://github.com/scummvm/scummvm/commit/29753a29a4b82d8cac78223232dc84c003d8f210
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-01-30T19:18:43-05:00

Commit Message:
XEEN: Implemented SpellsDialog and ConfirmDialog classes

Changed paths:
  A engines/xeen/dialogs_confirm.cpp
  A engines/xeen/dialogs_confirm.h
  A engines/xeen/dialogs_spells.cpp
  A engines/xeen/dialogs_spells.h
    engines/xeen/dialogs_yesno.cpp
    engines/xeen/module.mk
    engines/xeen/party.cpp
    engines/xeen/party.h
    engines/xeen/resources.cpp
    engines/xeen/resources.h
    engines/xeen/spells.cpp
    engines/xeen/spells.h
    engines/xeen/town.cpp
    engines/xeen/town.h



diff --git a/engines/xeen/dialogs_confirm.cpp b/engines/xeen/dialogs_confirm.cpp
new file mode 100644
index 0000000..13a41e7
--- /dev/null
+++ b/engines/xeen/dialogs_confirm.cpp
@@ -0,0 +1,85 @@
+/* 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 "xeen/dialogs_confirm.h"
+#include "xeen/xeen.h"
+
+namespace Xeen {
+
+bool ConfirmDialog::show(XeenEngine *vm, const Common::String &msg, int v2) {
+	ConfirmDialog *dlg = new ConfirmDialog(vm);
+	bool result = dlg->execute(msg, v2);
+	delete dlg;
+
+	return result;
+}
+
+bool ConfirmDialog::execute(const Common::String &msg, int v2) {
+	Screen &screen = *_vm->_screen;
+	EventsManager &events = *_vm->_events;
+	SpriteResource confirmSprites;
+	confirmSprites.load("confirm.icn");
+
+	addButton(Common::Rect(129, 112, 153, 132), Common::KEYCODE_y, &confirmSprites);
+	addButton(Common::Rect(185, 112, 209, 132), Common::KEYCODE_n, &confirmSprites);
+
+	Window &w = screen._windows[v2 ? 21 : 22];
+	w.open();
+
+	if (v2) {
+		confirmSprites.draw(screen._windows[21], 0, Common::Point(129, 112));
+		confirmSprites.draw(screen._windows[21], 2, Common::Point(185, 112));
+
+		_buttons[0]._bounds.moveTo(129, 112);
+		_buttons[1]._bounds.moveTo(185, 112);
+	} else if (v2 & 0x80) {
+		clearButtons();
+	} else {
+		confirmSprites.draw(screen._windows[22], 0, Common::Point(120, 133));
+		confirmSprites.draw(screen._windows[22], 2, Common::Point(176, 133));
+
+		_buttons[0]._bounds.moveTo(120, 133);
+		_buttons[1]._bounds.moveTo(176, 133);
+	}
+
+	w.writeString(msg);
+	w.update();
+
+	bool result = false;
+	while (!_vm->shouldQuit()) {
+		while (!events.isKeyMousePressed())
+			events.pollEventsAndWait();
+
+		if ((v2 & 0x80) || _buttonValue == Common::KEYCODE_ESCAPE ||
+			_buttonValue == Common::KEYCODE_y)
+			break;
+		else if (_buttonValue == Common::KEYCODE_y) {
+			result = true;
+			break;
+		}
+	}
+
+	w.close();
+	return result;
+}
+
+} // End of namespace Xeen
diff --git a/engines/xeen/dialogs_confirm.h b/engines/xeen/dialogs_confirm.h
new file mode 100644
index 0000000..825be5e
--- /dev/null
+++ b/engines/xeen/dialogs_confirm.h
@@ -0,0 +1,43 @@
+/* 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_CONFIRM_H
+#define XEEN_DIALOGS_CONFIRM_H
+
+#include "xeen/dialogs.h"
+
+namespace Xeen {
+
+class ConfirmDialog : public ButtonContainer {
+private:
+	XeenEngine *_vm;
+
+	ConfirmDialog(XeenEngine *vm) : ButtonContainer(), _vm(vm) {}
+
+	bool execute(const Common::String &msg, int v2);
+public:
+	static bool show(XeenEngine *vm, const Common::String &msg, int v2);
+};
+
+} // End of namespace Xeen
+
+#endif /* XEEN_DIALOGS_CONFIRM_H */
diff --git a/engines/xeen/dialogs_spells.cpp b/engines/xeen/dialogs_spells.cpp
new file mode 100644
index 0000000..7ae5e7a
--- /dev/null
+++ b/engines/xeen/dialogs_spells.cpp
@@ -0,0 +1,416 @@
+/* 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 "xeen/dialogs_spells.h"
+#include "xeen/dialogs_confirm.h"
+#include "xeen/resources.h"
+#include "xeen/spells.h"
+#include "xeen/sprites.h"
+#include "xeen/xeen.h"
+
+namespace Xeen {
+
+Character *SpellsScroll::show(XeenEngine *vm, Character *c, int v2) {
+	SpellsScroll *dlg = new SpellsScroll(vm);
+	Character *result = dlg->execute(c, v2);
+	delete dlg;
+
+	return result;
+}
+
+Character *SpellsScroll::execute(Character *c, int v2) {
+	EventsManager &events = *_vm->_events;
+	Interface &intf = *_vm->_interface;
+	Party &party = *_vm->_party;
+	Screen &screen = *_vm->_screen;
+	SoundManager &sound = *_vm->_sound;
+	Spells &spells = *_vm->_spells;
+	bool isDarkCc = _vm->_files->_isDarkCc;
+	loadButtons();
+
+	int v2Copy = v2;
+	v2 &= 0x7f;
+	int selection = -1;
+	int topIndex = 0;
+	int newSelection;
+	screen._windows[25].open();
+
+	while (!_vm->shouldQuit()) {
+		if (!v2) {
+			if (!c->guildMember()) {
+				sound.playSample(nullptr, 0);
+				intf._overallFrame = 5;
+				File f(isDarkCc ? "skull1.voc" : "guild11.voc");
+				sound.playSample(&f, 1);
+				break;
+			}
+
+			Common::String title = Common::String::format(BUY_SPELLS, c->_name.c_str());
+			Common::String msg = Common::String::format(GUILD_OPTIONS,
+				title.c_str(), XeenEngine::printMil(party._gold));
+			screen._windows[10].writeString(msg);
+
+			warning("TODO: Sprite draw using previously used button sprites");
+		}
+
+		_spells.clear();
+		const char *errorMsg = setSpellText(c, v2Copy);
+		screen._windows[25].writeString(Common::String::format(SPELLS_FOR,
+			errorMsg == nullptr ? SPELL_LINES_0_TO_9 : nullptr));
+
+		screen._windows[37].writeString(Common::String::format(SPELLS_DIALOG_SPELLS,
+			(topIndex + 0) < _spells.size() ? _spells[topIndex + 0]._name.c_str() : nullptr,
+			(topIndex + 1) < _spells.size() ? _spells[topIndex + 1]._name.c_str() : nullptr,
+			(topIndex + 2) < _spells.size() ? _spells[topIndex + 2]._name.c_str() : nullptr,
+			(topIndex + 3) < _spells.size() ? _spells[topIndex + 3]._name.c_str() : nullptr,
+			(topIndex + 4) < _spells.size() ? _spells[topIndex + 4]._name.c_str() : nullptr,
+			(topIndex + 5) < _spells.size() ? _spells[topIndex + 5]._name.c_str() : nullptr,
+			(topIndex + 6) < _spells.size() ? _spells[topIndex + 6]._name.c_str() : nullptr,
+			(topIndex + 7) < _spells.size() ? _spells[topIndex + 7]._name.c_str() : nullptr,
+			(topIndex + 8) < _spells.size() ? _spells[topIndex + 8]._name.c_str() : nullptr,
+			(topIndex + 9) < _spells.size() ? _spells[topIndex + 9]._name.c_str() : nullptr,
+			v2 ? SPELL_PTS : GOLD,
+			v2 ? c->_currentSp : party._gold
+		));
+
+		_iconSprites.draw(screen, 4, Common::Point(39, 26));
+		_iconSprites.draw(screen, 0, Common::Point(187, 26));
+		_iconSprites.draw(screen, 2, Common::Point(187, 111));
+		if (v2)
+			_iconSprites.draw(screen._windows[25], 5, Common::Point(132, 123));
+
+		screen._windows[25].update();
+
+		while (!_vm->shouldQuit() && !events.isKeyMousePressed())
+			events.pollEventsAndWait();
+		if (_vm->shouldQuit())
+			break;
+		checkEvents(_vm);
+
+		switch (_buttonValue) {
+		case Common::KEYCODE_F1:
+		case Common::KEYCODE_F6:
+			if (_vm->_mode != MODE_2) {
+				_buttonValue -= Common::KEYCODE_F1;
+				if (_buttonValue < party._partyCount) {
+					c = &party._activeParty[_buttonValue];
+					spells._lastCaster = _buttonValue;
+					intf.highlightChar(_buttonValue);
+
+					if (_vm->_mode == MODE_17) {
+						screen._windows[10].writeString(Common::String::format(GUILD_OPTIONS,
+							XeenEngine::printMil(party._gold).c_str(), GUILD_TEXT, c->_name.c_str()));
+					} else {
+						int category;
+						switch (c->_class) {
+						case CLASS_ARCHER:
+						case CLASS_SORCERER:
+							category = 1;
+							break;
+						case CLASS_DRUID:
+						case CLASS_RANGER:
+							category = 2;
+							break;
+						default:
+							category = 0;
+							break;
+						}
+
+						int spellIndex = (c->_currentSp == -1) ? 39 : c->_currentSpell;
+						int spellId = SPELLS_ALLOWED[category][spellIndex];
+						screen._windows[10].writeString(Common::String::format(SPELL_DETAILS,
+							spells._spellNames[spellId].c_str(),
+							spells.calcSpellPoints(spellId, c->getCurrentLevel()),
+							SPELL_GEM_COST[spellId], c->_currentSp));
+					}
+
+					drawButtons(&screen);
+					screen._windows[10].update();
+				}
+			}
+			break;
+
+		case Common::KEYCODE_RETURN:
+		case Common::KEYCODE_KP_ENTER:
+		case Common::KEYCODE_s:
+			if (selection != -1)
+				_buttonValue = Common::KEYCODE_ESCAPE;
+			break;
+
+		case Common::KEYCODE_ESCAPE:
+			selection = -1;
+			_buttonValue = Common::KEYCODE_ESCAPE;
+			break;
+
+		case Common::KEYCODE_0:
+		case Common::KEYCODE_1:
+		case Common::KEYCODE_2:
+		case Common::KEYCODE_3:
+		case Common::KEYCODE_4:
+		case Common::KEYCODE_5:
+		case Common::KEYCODE_6:
+		case Common::KEYCODE_7:
+		case Common::KEYCODE_8:
+		case Common::KEYCODE_9:
+			newSelection = topIndex + (_buttonValue == Common::KEYCODE_0) ? 9 :
+				(_buttonValue - Common::KEYCODE_1);
+
+			if (newSelection < (int)_spells.size()) {
+				int expenseFactor = 0;
+				int category = 0;
+
+				switch (c->_class) {
+				case CLASS_PALADIN:
+					expenseFactor = 1;
+					category = 0;
+					break;
+				case CLASS_ARCHER:
+					expenseFactor = 1;
+					category = 1;
+					break;
+				case CLASS_CLERIC:
+					category = 0;
+					break;
+				case CLASS_SORCERER:
+					category = 1;
+					break;
+				case CLASS_DRUID:
+					category = 2;
+					break;
+				case CLASS_RANGER:
+					expenseFactor = 1;
+					category = 2;
+					break;
+				default:
+					break;
+				}
+
+				int spellId = _spells[newSelection]._spellId;
+				int spellIndex = _spells[newSelection]._spellIndex;
+				int spellCost = spells.calcSpellCost(spellId, expenseFactor);
+				if (v2) {
+					// TODO: Confirm this refactoring against against original
+					selection = _buttonValue;
+				} else {
+					Common::String spellName = _spells[_buttonValue]._name;
+					Common::String msg = (v2Copy & 0x80) ?
+						Common::String::format(SPELLS_PRESS_A_KEY, msg.c_str()) :
+						Common::String::format(SPELLS_PURCHASE, msg.c_str(), spellCost);
+
+					if (ConfirmDialog::show(_vm, msg, v2Copy + 1)) {
+						if (party.subtract(0, spellCost, 0, WT_FREEZE_WAIT)) {
+							++c->_spells[spellIndex];
+							sound.playSample(nullptr, 0);
+							intf._overallFrame = 0;
+							File f(isDarkCc ? "guild12.voc" : "parrot2.voc");
+							sound.playSample(&f, 1);
+						} else {
+							sound.playFX(21);
+						}
+					}
+				}
+			}
+			break;
+
+		case Common::KEYCODE_PAGEUP:
+		case Common::KEYCODE_KP9:
+			topIndex = MAX(topIndex - 10, 0);
+			break;
+
+		case Common::KEYCODE_PAGEDOWN:
+		case Common::KEYCODE_KP3:
+			topIndex = MIN(topIndex + 10, (((int)_spells.size() - 1) / 10) * 10);
+			break;
+
+		case Common::KEYCODE_UP:
+		case Common::KEYCODE_KP8:
+			if (topIndex > 0)
+				--topIndex;
+			break;
+
+		case Common::KEYCODE_DOWN:
+		case Common::KEYCODE_KP2:
+			if (topIndex < ((int)_spells.size() - 10))
+				++topIndex;
+			break;
+		}
+	}
+
+	screen._windows[25].close();
+	if (v2 && selection != -1)
+		c->_currentSpell = _spells[selection]._spellIndex;
+
+	return c;
+}
+
+void SpellsScroll::loadButtons() {
+	_iconSprites.load("main.icn");
+	_scrollSprites.load("scroll.icn");
+	addButton(Common::Rect(187, 26, 198, 36), Common::KEYCODE_UP, &_scrollSprites, true);
+	addButton(Common::Rect(187, 111, 198, 121), Common::KEYCODE_DOWN, &_scrollSprites, true);
+	addButton(Common::Rect(40, 28, 187, 36), Common::KEYCODE_1, &_scrollSprites, false);
+	addButton(Common::Rect(40, 37, 187, 45), Common::KEYCODE_2, &_scrollSprites, false);
+	addButton(Common::Rect(40, 46, 187, 54), Common::KEYCODE_3, &_scrollSprites, false);
+	addButton(Common::Rect(40, 55, 187, 63), Common::KEYCODE_4, &_scrollSprites, false);
+	addButton(Common::Rect(40, 64, 187, 72), Common::KEYCODE_5, &_scrollSprites, false);
+	addButton(Common::Rect(40, 73, 187, 81), Common::KEYCODE_6, &_scrollSprites, false);
+	addButton(Common::Rect(40, 82, 187, 90), Common::KEYCODE_7, &_scrollSprites, false);
+	addButton(Common::Rect(40, 91, 187, 99), Common::KEYCODE_8, &_scrollSprites, false);
+	addButton(Common::Rect(40, 100, 187, 108), Common::KEYCODE_9, &_scrollSprites, false);
+	addButton(Common::Rect(40, 109, 187, 117), Common::KEYCODE_0, &_scrollSprites, false);
+	addButton(Common::Rect(174, 123, 198, 133), Common::KEYCODE_ESCAPE, &_scrollSprites, false);
+	addButton(Common::Rect(187, 35, 198, 73), Common::KEYCODE_PAGEUP, &_scrollSprites, false);
+	addButton(Common::Rect(187, 74, 198, 112), Common::KEYCODE_PAGEDOWN, &_scrollSprites, false);
+	addButton(Common::Rect(132, 123, 168, 133), Common::KEYCODE_s, &_scrollSprites, false);
+}
+
+const char *SpellsScroll::setSpellText(Character *c, int v2) {
+	Party &party = *_vm->_party;
+	Spells &spells = *_vm->_spells;
+	bool isDarkCc = _vm->_files->_isDarkCc;
+	int expenseFactor = 0;
+	int currLevel = c->getCurrentLevel();
+	int category;
+
+	if ((v2 & 0x7f) == 0) {
+		switch (c->_class) {
+		case CLASS_PALADIN:
+			expenseFactor = 1;
+			category = 0;
+			break;
+		case CLASS_ARCHER:
+			expenseFactor = 1;
+			category = 1;
+			break;
+		case CLASS_CLERIC:
+			category = 0;
+			break;
+		case CLASS_SORCERER:
+			category = 1;
+			break;
+		case CLASS_DRUID:
+			category = 2;
+			break;
+		case CLASS_RANGER:
+			expenseFactor = 1;
+			category = 2;
+			break;
+		default:
+			category = -1;
+			break;
+		}
+
+		if (category != -1) {
+			if (party._mazeId == 49 || party._mazeId == 37) {
+				for (int spellId = 0; spellId < 76; ++spellId) {
+					int idx = 0;
+					while (idx < MAX_SPELLS_PER_CLASS && SPELLS_ALLOWED[category][idx] == spellId)
+						++idx;
+
+					// Handling if the spell is appropriate for the character's class
+					if (idx < MAX_SPELLS_PER_CLASS) {
+						if (!c->_spells[idx] || (v2 & 0x80)) {
+							int cost = spells.calcSpellCost(SPELLS_ALLOWED[category][idx], expenseFactor);
+							_spells.push_back(SpellEntry(Common::String::format("\x3l%s\x3r\x9""000%u",
+								spells._spellNames[SPELLS_ALLOWED[category][idx]], cost), 
+								idx, spellId));
+						}
+					}
+				}
+			} else if (isDarkCc) {
+				int groupIndex = (party._mazeId - 29) / 2;
+				for (int spellId = DARK_SPELL_RANGES[category][0];
+						spellId < DARK_SPELL_RANGES[category][1]; ++spellId) {
+					int idx = 0;
+					while (idx < 40 && SPELLS_ALLOWED[category][idx] ==
+						DARK_SPELL_OFFSETS[category][spellId]);
+
+					if (idx < 40) {
+						if (!c->_spells[idx] || (v2 & 0x80)) {
+							int cost = spells.calcSpellCost(SPELLS_ALLOWED[category][idx], expenseFactor);
+							_spells.push_back(SpellEntry(Common::String::format("\x3l%s\x3r\x9""000%u",
+								spells._spellNames[SPELLS_ALLOWED[category][idx]], cost), 
+								idx, spellId));
+						}
+					}
+				}
+			} else {
+				for (int spellId = 0; spellId < 20; ++spellId) {
+					int idx = 0;
+					while (CLOUDS_SPELL_OFFSETS[party._mazeId - 29][spellId] !=
+						SPELLS_ALLOWED[category][idx] && idx < 40) ;
+
+					if (idx < 40) {
+						if (!c->_spells[idx] || (v2 & 0x80)) {
+							int cost = spells.calcSpellCost(SPELLS_ALLOWED[category][idx], expenseFactor);
+							_spells.push_back(SpellEntry(Common::String::format("\x3l%s\x3r\x9""000%u",
+								spells._spellNames[SPELLS_ALLOWED[category][idx]], cost), 
+								idx, spellId));
+						}
+					}
+				}
+			}
+		}
+
+		if (c->getMaxSP() == 0)
+			return NOT_A_SPELL_CASTER;
+
+	} else if ((v2 & 0x7f) == 1) {
+		switch (c->_class) {
+		case 0:
+		case 12:
+			category = 0;
+			break;
+		case 1:
+		case 3:
+			category = 1;
+			break;
+		case 7:
+		case 8:
+			category = 2;
+			break;
+		default:
+			category = 0;
+			break;
+		}
+
+		if (c->getMaxSP() == 0) {
+			return NOT_A_SPELL_CASTER;
+		} else {
+			for (int spellIndex = 0; spellIndex < (MAX_SPELLS_PER_CLASS - 1); ++spellIndex) {
+				if (c->_spells[spellIndex]) {
+					int spellId = SPELLS_ALLOWED[category][spellIndex];
+					int gemCost = SPELL_GEM_COST[spellId];
+					int spCost = spells.calcSpellPoints(spellId, currLevel);
+
+					Common::String msg = Common::String::format("\x3l%s\x3r\x9""000%u/%u",
+						spells._spellNames[spellId].c_str(), spCost, gemCost);
+					_spells.push_back(SpellEntry(msg, spellIndex, spellId));
+				}
+			}
+		}
+	}
+
+	return nullptr;
+}
+
+} // End of namespace Xeen
diff --git a/engines/xeen/dialogs_spells.h b/engines/xeen/dialogs_spells.h
new file mode 100644
index 0000000..69e339f
--- /dev/null
+++ b/engines/xeen/dialogs_spells.h
@@ -0,0 +1,61 @@
+/* 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_SPELLS_H
+#define XEEN_DIALOGS_SPELLS_H
+
+#include "common/array.h"
+#include "xeen/dialogs.h"
+#include "xeen/party.h"
+
+namespace Xeen {
+
+struct SpellEntry {
+	Common::String _name;
+	int _spellIndex;
+	int _spellId;
+
+	SpellEntry(const Common::String &name, int spellIndex, int spellId) :
+		_name(name), _spellIndex(spellIndex), _spellId(spellId) {}
+};
+
+class SpellsScroll : public ButtonContainer {
+private:
+	XeenEngine *_vm;
+	SpriteResource _iconSprites;
+	SpriteResource _scrollSprites;
+	Common::Array<SpellEntry> _spells;
+
+	SpellsScroll(XeenEngine *vm) : ButtonContainer(), _vm(vm) {}
+
+	Character *execute(Character *c, int v2);
+
+	void loadButtons();
+
+	const char *setSpellText(Character *c, int v2);
+public:
+	static Character *show(XeenEngine *vm, Character *c, int v2);
+};
+
+} // End of namespace Xeen
+
+#endif /* XEEN_DIALOGS_SPELLS_H */
diff --git a/engines/xeen/dialogs_yesno.cpp b/engines/xeen/dialogs_yesno.cpp
index 8ea27eb..17ca9a0 100644
--- a/engines/xeen/dialogs_yesno.cpp
+++ b/engines/xeen/dialogs_yesno.cpp
@@ -25,9 +25,9 @@
 
 namespace Xeen {
 
-bool YesNo::show(XeenEngine *vm, bool type, bool v2) {
+bool YesNo::show(XeenEngine *vm, bool type, bool townFlag) {
 	YesNo *dlg = new YesNo(vm);
-	bool result = dlg->execute(type, v2);
+	bool result = dlg->execute(type, townFlag);
 	delete dlg;
 
 	return result;
diff --git a/engines/xeen/module.mk b/engines/xeen/module.mk
index 9d252b1..be95123 100644
--- a/engines/xeen/module.mk
+++ b/engines/xeen/module.mk
@@ -8,6 +8,7 @@ MODULE_OBJS := \
 	debugger.o \
 	detection.o \
 	dialogs.o \
+	dialogs_confirm.o \
 	dialogs_error.o \
 	dialogs_options.o \
 	dialogs_input.o \
diff --git a/engines/xeen/party.cpp b/engines/xeen/party.cpp
index 2138ca6..66078b6 100644
--- a/engines/xeen/party.cpp
+++ b/engines/xeen/party.cpp
@@ -1218,4 +1218,70 @@ void Party::handleLight() {
 		(map.mazeData()._mazeFlags2 & FLAG_IS_DARK) == 0 ? 4 : 0;
 }
 
+int Party::subtract(int mode, uint amount, int whereId, ErrorWaitType wait) {
+	switch (mode) {
+	case 0:
+		// Gold
+		if (whereId) {
+			if (amount <= _bankGold) {
+				_bankGold -= amount;
+			} else {
+				notEnough(0, whereId, false, wait);
+				return false;
+			}
+		}
+		else {
+			if (amount <= _gold) {
+				_gold -= amount;
+			} else {
+				notEnough(0, whereId, false, wait);
+				return false;
+			}
+		}
+		break;
+
+	case 1:
+		// Gems
+		if (whereId) {
+			if (amount <= _bankGems) {
+				_bankGems -= amount;
+			} else {
+				notEnough(0, whereId, false, wait);
+				return false;
+			}
+		}
+		else {
+			if (amount <= _gems) {
+				_gems -= amount;
+			} else {
+				notEnough(0, whereId, false, wait);
+				return false;
+			}
+		}
+		break;
+
+	case 2:
+		// Food
+		if (amount > _food) {
+			_food -= amount;
+		} else {
+			notEnough(5, 0, 0, wait);
+			return false;
+		}
+		break;
+
+	default:
+		break;
+	}
+
+	return true;
+}
+
+void Party::notEnough(int consumableId, int whereId, bool mode, ErrorWaitType wait) {
+	Common::String msg = Common::String::format(
+		mode ? NO_X_IN_THE_Y : NOT_ENOUGH_X_IN_THE_Y,
+		CONSUMABLE_NAMES[consumableId], WHERE_NAMES[whereId]);
+	ErrorScroll::show(_vm, msg, wait);
+}
+
 } // End of namespace Xeen
diff --git a/engines/xeen/party.h b/engines/xeen/party.h
index 035e76c..e00b424 100644
--- a/engines/xeen/party.h
+++ b/engines/xeen/party.h
@@ -28,6 +28,7 @@
 #include "common/rect.h"
 #include "common/serializer.h"
 #include "xeen/combat.h"
+#include "xeen/dialogs_error.h"
 #include "xeen/items.h"
 
 namespace Xeen {
@@ -274,6 +275,10 @@ public:
 	void resetTemps();
 
 	void handleLight();
+
+	int subtract(int mode, uint amount, int whereId, ErrorWaitType wait);
+
+	void notEnough(int consumableId, int whereId, bool mode, ErrorWaitType wait);
 };
 
 } // End of namespace Xeen
diff --git a/engines/xeen/resources.cpp b/engines/xeen/resources.cpp
index 57e16d7..ed304dc 100644
--- a/engines/xeen/resources.cpp
+++ b/engines/xeen/resources.cpp
@@ -492,7 +492,7 @@ const int MONSTER_EFFECT_FLAGS[15][8] = {
 	{ 0x108, 0x108, 0x108, 0x108, 0x108, 0x108, 0x108, 0x108 }
 };
 
-const uint SPELLS_ALLOWED[3][40] = {
+const int SPELLS_ALLOWED[3][40] = {
 	{
 		0, 1, 2, 3, 5, 6, 7, 8, 9, 10,
 		12, 14, 16, 23, 26, 27, 28, 30, 31, 32,
@@ -781,6 +781,49 @@ const int SPELL_GEM_COST[77] = {
 	5, 0, 0, 0, 0, 5, 1, 2, 0, 2, 0
 };
 
-extern const char *NOT_A_SPELL_CASTER = "Not a spell caster...";
+const char *const NOT_A_SPELL_CASTER = "Not a spell caster...";
+
+const char *const SPELLS_FOR = "\xD\xC""d%s\x2\x3""c\x9""000\xB""002Spells for %s";
+
+const char *const SPELL_LINES_0_TO_9 =
+	"\x2\x3l\xB""015\x9""0011\n2\n3\n4\n5\n6\n7\n8\n9\n0";
+
+const char *const SPELLS_DIALOG_SPELLS = "\x3l\xB""015"
+	"\x9""010\xC""%2u%s\xC""d\x3l\n"
+	"\x9""010\xC""%2u%s\xC""d\x3l\n"
+	"\x9""010\xC""%2u%s\xC""d\x3l\n"
+	"\x9""010\xC""%2u%s\xC""d\x3l\n"
+	"\x9""010\xC""%2u%s\xC""d\x3l\n"
+	"\x9""010\xC""%2u%s\xC""d\x3l\n"
+	"\x9""010\xC""%2u%s\xC""d\x3l\n"
+	"\x9""010\xC""%2u%s\xC""d\x3l\n"
+	"\x9""010\xC""%2u%s\xC""d\x3l\n"
+	"\x9""010\xC""%2u%s\xC""d\x3l"
+	"\x9""004\xB""110%s - %lu\x1";
+
+const char *const SPELL_PTS = "Spell Pts";
+
+const char *const GOLD = "Gold";
+
+const char *const SPELLS_PRESS_A_KEY =
+	"\x3""c\xC""09%s\xC""d\x3l\n"
+	"\n"
+	"%s\x3""c\x9""000\xB""100Press a Key!";
+
+const char *const SPELLS_PURCHASE =
+	"\x3l\xB""000\x9""000\xC""d%s  Do you wish to purchase "
+	"\xC""09%s\xC""d for %u?"; 
+
+const char *const SPELL_DETAILS =
+"\xD\x2\x3""c\xB""122\x9""013\xC""37C\xC""dast"
+"\x9""040\xC""37N\xC""dew\x9""067ESC\x1""000\xB""000\x3""cCast Spell\n"
+"\n"
+"%s\x3l\n"
+"\n"
+"Spell Ready:\x3""c\n"
+"\n"
+"\xC""09%s\xC""d\x2\x3l\n"
+"\xB""082Cost\x3r\x9""000%u/%u\x3l\n"
+"Cur SP\x3r\x9""000%u\x1";
 
 } // End of namespace Xeen
diff --git a/engines/xeen/resources.h b/engines/xeen/resources.h
index 60f4848..37afb2c 100644
--- a/engines/xeen/resources.h
+++ b/engines/xeen/resources.h
@@ -124,7 +124,7 @@ extern const int COMBAT_FLOAT_Y[8];
 
 extern const int MONSTER_EFFECT_FLAGS[15][8];
 
-extern const uint SPELLS_ALLOWED[3][40];
+extern const int SPELLS_ALLOWED[3][40];
 
 extern const int BASE_HP_BY_CLASS[10];
 
@@ -226,7 +226,23 @@ extern const int SPELL_LEVEL_OFFSETS[3][39];
 
 extern const int SPELL_GEM_COST[77];
 
-extern const char *NOT_A_SPELL_CASTER;
+extern const char *const NOT_A_SPELL_CASTER;
+
+extern const char *const SPELLS_FOR;
+
+extern const char *const SPELL_LINES_0_TO_9;
+
+extern const char *const SPELLS_DIALOG_SPELLS;
+
+extern const char *const SPELL_PTS;
+
+extern const char *const GOLD;
+
+extern const char *const SPELLS_PRESS_A_KEY;
+
+extern const char *const SPELLS_PURCHASE;
+
+extern const char *const SPELL_DETAILS;
 
 } // End of namespace Xeen
 
diff --git a/engines/xeen/spells.cpp b/engines/xeen/spells.cpp
index 922f6fc..588fa1b 100644
--- a/engines/xeen/spells.cpp
+++ b/engines/xeen/spells.cpp
@@ -28,6 +28,8 @@
 namespace Xeen {
 
 Spells::Spells(XeenEngine *vm) : _vm(vm) {
+	_lastCaster = 0;
+
 	load();
 }
 
diff --git a/engines/xeen/spells.h b/engines/xeen/spells.h
index 97e3c80..96f4916 100644
--- a/engines/xeen/spells.h
+++ b/engines/xeen/spells.h
@@ -40,6 +40,7 @@ private:
 public:
 	Common::StringArray _spellNames;
 	Common::StringArray _maeNames;
+	int _lastCaster;
 public:
 	Spells(XeenEngine *vm);
 
diff --git a/engines/xeen/town.cpp b/engines/xeen/town.cpp
index d773f6d..2f31113 100644
--- a/engines/xeen/town.cpp
+++ b/engines/xeen/town.cpp
@@ -606,7 +606,7 @@ Character *Town::doTavernOptions(Character *c) {
 	case Common::KEYCODE_d:
 		// Drink
 		if (!c->noActions()) {
-			if (subtract(0, 1, 0, WT_2)) {
+			if (party.subtract(0, 1, 0, WT_2)) {
 				sound.playSample(nullptr, 0);
 				File f("gulp.voc");
 				sound.playSample(&f, 0);
@@ -664,7 +664,7 @@ Character *Town::doTavernOptions(Character *c) {
 		if (YesNo::show(_vm, false, true)) {
 			if (party._food >= _v22) {
 				ErrorScroll::show(_vm, FOOD_PACKS_FULL, WT_2);
-			} else if (subtract(0, _v23, 0, WT_2)) {
+			} else if (party.subtract(0, _v23, 0, WT_2)) {
 				party._food = _v22;
 				sound.playSample(nullptr, 0);
 				File f(isDarkCc ? "thanks2.voc" : "thankyou.voc");
@@ -744,7 +744,7 @@ Character *Town::doTavernOptions(Character *c) {
 					drawButtons(&screen);
 					screen._windows[10].update();
 					townWait();
-				} else if (subtract(0, 1, 0, WT_2)) {
+				} else if (party.subtract(0, 1, 0, WT_2)) {
 					sound.playSample(nullptr, 0);
 					File f(isDarkCc ? "thanks2.voc" : "thankyou.voc");
 					sound.playSample(&f, 1);
@@ -805,7 +805,7 @@ Character *Town::doTempleOptions(Character *c) {
 		break;
 
 	case Common::KEYCODE_d:
-		if (_donation && subtract(0, _donation, 0, WT_2)) {
+		if (_donation && party.subtract(0, _donation, 0, WT_2)) {
 			sound.playSample(nullptr, 0);
 			File f("coina.voc");
 			sound.playSample(&f, 1);
@@ -832,7 +832,7 @@ Character *Town::doTempleOptions(Character *c) {
 		break;
 
 	case Common::KEYCODE_h:
-		if (_healCost && subtract(0, _healCost, 0, WT_2)) {
+		if (_healCost && party.subtract(0, _healCost, 0, WT_2)) {
 			c->_magicResistence._temporary = 0;
 			c->_energyResistence._temporary = 0;
 			c->_poisonResistence._temporary = 0;
@@ -860,7 +860,7 @@ Character *Town::doTempleOptions(Character *c) {
 		break;
 
 	case Common::KEYCODE_u:
-		if (_uncurseCost && subtract(0, _uncurseCost, 0, WT_2)) {
+		if (_uncurseCost && party.subtract(0, _uncurseCost, 0, WT_2)) {
 			for (int idx = 0; idx < 9; ++idx) {
 				c->_weapons[idx]._bonusFlags &= ~FLAG_CURSED;
 				c->_armor[idx]._bonusFlags &= ~FLAG_CURSED;
@@ -921,7 +921,7 @@ Character *Town::doTrainingOptions(Character *c) {
 			sound.playSample(&f);
 
 		} else if (!c->noActions()) {
-			if (subtract(0, (c->_level._permanent * c->_level._permanent) * 10, 0, WT_2)) {
+			if (party.subtract(0, (c->_level._permanent * c->_level._permanent) * 10, 0, WT_2)) {
 				_drawFrameIndex = 0;
 				sound.playSample(nullptr, 0);
 				File f(isDarkCc ? "prtygd.voc" : "trainin2.voc");
@@ -1003,14 +1003,14 @@ void Town::depositWithdrawl(int choice) {
 			(choice && !party._bankGold && !flag) ||
 			(!choice && !party._gems && flag) ||
 			(!choice && !party._gold && !flag)) {
-			notEnough(flag, choice, 1, WT_2);
+			party.notEnough(flag, choice, 1, WT_2);
 		} else {
 			screen._windows[35].writeString(AMOUNT);
 			int amount = NumericInput::show(_vm, 35, 10, 77);
 
 			if (amount) {
 				if (flag) {
-					if (subtract(true, amount, choice, WT_2)) {
+					if (party.subtract(true, amount, choice, WT_2)) {
 						if (choice) {
 							party._gems += amount;
 						} else {
@@ -1018,7 +1018,7 @@ void Town::depositWithdrawl(int choice) {
 						}
 					}
 				} else {
-					if (subtract(false, amount, choice, WT_2)) {
+					if (party.subtract(false, amount, choice, WT_2)) {
 						if (choice) {
 							party._gold += amount;
 						} else {
@@ -1053,72 +1053,6 @@ void Town::depositWithdrawl(int choice) {
 	_buttons[2]._value = Common::KEYCODE_ESCAPE;
 }
 
-void Town::notEnough(int consumableId, int whereId, bool mode, ErrorWaitType wait) {
-	Common::String msg = Common::String::format(
-		mode ? NO_X_IN_THE_Y : NOT_ENOUGH_X_IN_THE_Y,
-		CONSUMABLE_NAMES[consumableId], WHERE_NAMES[whereId]);
-	ErrorScroll::show(_vm, msg, wait);
-}
-
-int Town::subtract(int mode, uint amount, int whereId, ErrorWaitType wait) {
-	Party &party = *_vm->_party;
-
-	switch (mode) {
-	case 0:
-		// Gold
-		if (whereId) {
-			if (amount <= party._bankGold) {
-				party._bankGold -= amount;
-			} else {
-				notEnough(0, whereId, false, wait);
-				return false;
-			}
-		} else {
-			if (amount <= party._gold) {
-				party._gold -= amount;
-			} else {
-				notEnough(0, whereId, false, wait);
-				return false;
-			}
-		}
-		break;
-
-	case 1:
-		// Gems
-		if (whereId) {
-			if (amount <= party._bankGems) {
-				party._bankGems -= amount;
-			} else {
-				notEnough(0, whereId, false, wait);
-				return false;
-			}
-		} else {
-			if (amount <= party._gems) {
-				party._gems -= amount;
-			} else {
-				notEnough(0, whereId, false, wait);
-				return false;
-			}
-		}
-		break;
-
-	case 2:
-		// Food
-		if (amount > party._food) {
-			party._food -= amount;
-		} else {
-			notEnough(5, 0, 0, wait);
-			return false;
-		}
-		break;
-
-	default:
-		break;
-	}
-
-	return true;
-}
-
 void Town::drawTownAnim(bool flag) {
 	Interface &intf = *_vm->_interface;
 	Screen &screen = *_vm->_screen;
diff --git a/engines/xeen/town.h b/engines/xeen/town.h
index 27b1fe2..8237f81 100644
--- a/engines/xeen/town.h
+++ b/engines/xeen/town.h
@@ -96,10 +96,6 @@ private:
 
 	void depositWithdrawl(int choice);
 
-	void notEnough(int consumableId, int whereId, bool mode, ErrorWaitType wait);
-
-	int subtract(int mode, uint amount, int whereId, ErrorWaitType wait);
-
 	Character *showItems(Character *c, int v2);
 public:
 	Town(XeenEngine *vm);


Commit: 4b364c50d6069e0f94254b78d8ef5839d0e63f04
    https://github.com/scummvm/scummvm/commit/4b364c50d6069e0f94254b78d8ef5839d0e63f04
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-01-30T19:59:38-05:00

Commit Message:
XEEN: Fix glitch in indoor walls drawing

Changed paths:
    engines/xeen/interface_map.cpp



diff --git a/engines/xeen/interface_map.cpp b/engines/xeen/interface_map.cpp
index 77a5f92..dcae6cc 100644
--- a/engines/xeen/interface_map.cpp
+++ b/engines/xeen/interface_map.cpp
@@ -27,6 +27,8 @@
 
 namespace Xeen {
 
+static bool debugFlag = false;
+
 OutdoorDrawList::OutdoorDrawList() : _sky1(_data[0]), _sky2(_data[1]), 
 	_groundSprite(_data[2]), _combatImgs1(&_data[124]), _combatImgs2(&_data[95]),
 	_combatImgs3(&_data[76]), _combatImgs4(&_data[53]), _groundTiles(&_data[3]) {
@@ -189,7 +191,7 @@ IndoorDrawList::IndoorDrawList() :
 	_objects6(_data[99]), _objects7(_data[55]), _objects8(_data[56]),
 	_objects9(_data[58]), _objects10(_data[57]), _objects11(_data[59]),
 	_combatImgs1(&_data[162]), _combatImgs2(&_data[135]),
-	_combatImgs3(&_data[111]), _combatImgs4(&_data[80]) {
+	_combatImgs3(&_data[111]), _combatImgs4(&_data[79]) {
 	// Setup draw structure positions
 	_data[0] = DrawStruct(0, 8, 8);
 	_data[1] = DrawStruct(1, 8, 25);
@@ -3699,7 +3701,7 @@ void InterfaceMap::drawIndoors() {
 
 	if (!_wo[26] && !_wo[29] && !_wo[21] && !_wo[13] && !_wo[18] && !_wo[31]) {
 		if (_wo[33])
-			_indoorList._fwl_3F1R._frame = 15;
+			_indoorList._swl_3F1R._frame = 15;
 		else if (_wo[77])
 			_indoorList._swl_3F1R._frame = 39;
 	}


Commit: 2472cc0917e3e1a56f61e270e55c76af1152cb05
    https://github.com/scummvm/scummvm/commit/2472cc0917e3e1a56f61e270e55c76af1152cb05
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-01-31T07:22:25-05:00

Commit Message:
XEEN: Initial implementation of map dialog

Changed paths:
  A engines/xeen/dialogs_automap.cpp
  A engines/xeen/dialogs_automap.h
    engines/xeen/interface.cpp
    engines/xeen/interface_map.cpp
    engines/xeen/map.h
    engines/xeen/module.mk
    engines/xeen/resources.cpp
    engines/xeen/resources.h



diff --git a/engines/xeen/dialogs_automap.cpp b/engines/xeen/dialogs_automap.cpp
new file mode 100644
index 0000000..08cf593
--- /dev/null
+++ b/engines/xeen/dialogs_automap.cpp
@@ -0,0 +1,413 @@
+/* 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 "xeen/dialogs_automap.h"
+#include "xeen/resources.h"
+#include "xeen/xeen.h"
+
+namespace Xeen {
+
+
+void AutoMapDialog::show(XeenEngine *vm) {
+	AutoMapDialog *dlg = new AutoMapDialog(vm);
+	dlg->execute();
+	delete dlg;
+}
+
+void AutoMapDialog::execute() {
+	Screen &screen = *_vm->_screen;
+	EventsManager &events = *_vm->_events;
+	Interface &intf = *_vm->_interface;
+	Map &map = *_vm->_map;
+	Party &party = *_vm->_party;
+	int frame2 = intf._overallFrame * 2;
+	int varSI = 1;
+	bool frameEndFlag;
+
+	int yDiffStart = 8;
+	int xDiffStart = 248;
+	Common::Point pt = party._mazePosition;
+	Common::Point arrowPt;
+	SpriteResource globalSprites;
+	globalSprites.load("global.icn");
+
+	if (pt.x < 8 && map.mazeData()._surroundingMazes._west == 0) {
+		arrowPt.x = pt.x * 10 + 4;
+	} else if (pt.x > 23) {
+		arrowPt.x = pt.x * 10 + 100;
+		pt.x = 23;
+	} else if (pt.x > 8 && map.mazeData()._surroundingMazes._east == 0) {
+		arrowPt.x = pt.x * 10 + 4;
+		pt.x = 7;
+	} else {
+		arrowPt.x = 74;
+	}
+
+	if (pt.y < 8 && map.mazeData()._surroundingMazes._south == 0) {
+		arrowPt.y = ((15 - pt.y) << 3) + 13;
+		pt.y = 8;
+	} else if (pt.y > 24) {
+		arrowPt.y = ((15 - (pt.y - 24)) << 3) + 13;
+		pt.y = 24;
+	} else if (pt.y >= 8 && map.mazeData()._surroundingMazes._north == 0) {
+		arrowPt.y = ((15 - pt.y) << 3) + 13;
+		pt.y = 8;
+	} else {
+		arrowPt.y = 69;
+	}
+
+	screen._windows[5].open();
+	MazeData &mazeData = map.mazeDataCurrent();
+	bool drawFlag = true;
+	int v;
+	
+	events.updateGameCounter();
+	do {
+		if (drawFlag)
+			intf.draw3d(false);
+		screen._windows[5].writeString("\n");
+
+		if (map._isOutdoors) {
+			// Draw outdoors map
+			for (int yCtr = 0, yDiff = yDiffStart - 1, yp = 38; yCtr < 16; 
+					++yCtr, --yDiff, yp += 8) {
+				for (int xp = 80, xDiff = xDiffStart + 1; xp < 240; xp += 10, ++xDiff) {
+					v = map.mazeLookup(Common::Point(xDiff, yDiff), 0);
+
+					if (map._currentSteppedOn) {
+						map._tileSprites.draw(screen, map.mazeDataCurrent()._surfaceTypes[v],
+							Common::Point(xp, yp));
+					}
+				}
+			}
+
+			for (int yCtr = 0, yDiff = yDiffStart - 1, yp = 38; yCtr < 16;
+				++yCtr, --yDiff, yp += 8) {
+				for (int xp = 80, xDiff = xDiffStart + 1; xp < 240; xp += 10, ++xDiff) {
+					v = map.mazeLookup(Common::Point(xDiff, yDiff), 4);
+					int wallType = map.mazeDataCurrent()._wallTypes[v];
+
+					if (wallType && map._currentSteppedOn)
+						map._tileSprites.draw(screen, wallType, Common::Point(xp, yp));
+				}
+			}
+
+			for (int yCtr = 0, yDiff = yDiffStart - 1, yp = 38; yCtr < 16;
+				++yCtr, --yDiff, yp += 8) {
+				for (int xCtr = 0, xp = 80, xDiff = xDiffStart + 1; xp < 240; 
+						++xCtr, ++xDiff, xp += 10) {
+					if (xCtr == (arrowPt.x / 10) && yCtr == (14 - (arrowPt.y)) && frameEndFlag)
+						map._tileSprites.draw(screen, party._mazeDirection + 1,
+							Common::Point(arrowPt.x + 81, arrowPt.y + 29));
+					
+					v = map.mazeLookup(Common::Point(xDiff, yDiff), 12);					
+					int frame;
+					switch (v) {
+					case SURFTYPE_WATER:
+						frame = 18;
+						break;
+					case SURFTYPE_DIRT:
+						frame = 34;
+						break;
+					case SURFTYPE_GRASS:
+						frame = 22;
+						break;
+					case SURFTYPE_SNOW:
+					case SURFTYPE_SEWER:
+						frame = 16;
+						break;
+					case SURFTYPE_SWAMP:
+					case SURFTYPE_ROAD:
+						frame = 2;
+					case SURFTYPE_LAVA:
+						frame = 30;
+						break;
+					case SURFTYPE_DESERT:
+						frame = 32;
+						break;
+					case SURFTYPE_DWATER:
+						frame = 20;
+						break;
+					case SURFTYPE_TFLR:
+						frame = 28;
+						break;
+					case SURFTYPE_SKY:
+						frame = 14;
+						break;
+					case SURFTYPE_CROAD:
+						frame = frame2 + 4;
+						break;
+					case SURFTYPE_CLOUD:
+						frame = 24;
+						break;
+					case SURFTYPE_SCORCH:
+						frame = 26;
+						break;
+					default:
+						frame = -1;
+						break;
+					}
+					
+					if (frame != -1 && map._currentSteppedOn)
+						map._tileSprites.draw(screen, frame, Common::Point(xp, yp));
+
+					v = map.mazeLookup(Common::Point(xDiff, yDiff), 0);
+					switch (v) {
+					case SURFTYPE_WATER:
+						frame = 19;
+						break;
+					case SURFTYPE_DIRT:
+						frame = 35;
+						break;
+					case SURFTYPE_GRASS:
+						frame = 23;
+						break;
+					case SURFTYPE_SNOW:
+					case SURFTYPE_SEWER:
+						frame = 17;
+						break;
+					case SURFTYPE_SWAMP:
+					case SURFTYPE_ROAD:
+						frame = 3;
+						break;
+					case SURFTYPE_LAVA:
+						frame = 31;
+						break;
+					case SURFTYPE_DESERT:
+						frame = 33;
+						break;
+					case SURFTYPE_DWATER:
+						frame = 21;
+						break;
+					case SURFTYPE_TFLR:
+						frame = 29;
+						break;
+					case SURFTYPE_SKY:
+						frame = 15;
+						break;
+					case SURFTYPE_CROAD:
+						frame = frame2 + 5;
+						break;
+					case SURFTYPE_CLOUD:
+						frame = 25;
+						break;
+					case SURFTYPE_SCORCH:
+						frame = 27;
+						break;
+					default:
+						frame = -1;
+						break;
+					}
+					
+					if (frame != -1 && map._currentSteppedOn)
+						map._tileSprites.draw(screen, frame, Common::Point(xp, yp));
+				}
+			}
+
+			for (int yCtr = 0, yDiff = yDiffStart - 1, yp = 38; yCtr < 16;
+				++yCtr, --yDiff, yp += 8) {
+				for (int xp = 80, xDiff = xDiffStart + 1; xp < 240; xp += 10, ++xDiff) {
+					v = map.mazeLookup(Common::Point(xDiff, yDiff), 0, 0xffff);
+
+					if (v != INVALID_CELL && map._currentSteppedOn)
+						map._tileSprites.draw(screen, 1, Common::Point(xp, yp));
+				}
+			}
+		} else {
+			// Draw indoors map
+			frame2 = (frame2 + 2) % 8;
+
+			for (int yCtr = 0, yDiff = yDiffStart - 1, yp = 38; yCtr < 16;
+				++yCtr, --yDiff, yp += 8) {
+				for (int xp = 80, xDiff = xDiffStart + 1; xp < 240; xp += 10, ++xDiff) {
+					v = map.mazeLookup(Common::Point(xDiff, yDiff), 0, 0xffff);
+
+					if (v != INVALID_CELL && map._currentSteppedOn)
+						map._tileSprites.draw(screen, 0, Common::Point(xp, yp));
+				}
+			}
+
+			for (int yDiff = yDiffStart - 1, yp = 38; yp < 171; --yDiff, yp += 8) {
+				v = map.mazeLookup(Common::Point(pt.x - 8, yDiff), 0, 0xffff);
+
+				if (v != INVALID_CELL && map._currentSurfaceId != 0 && map._currentSteppedOn)
+					map._tileSprites.draw(screen, 36 + map.mazeData()._surfaceTypes[v],
+						Common::Point(75, yp));
+			}
+
+			v = map.mazeLookup(Common::Point(pt.x - 8, pt.y + 8), 0, 0xffff);
+			if (v != INVALID_CELL && map._currentSurfaceId != 0 && map._currentSteppedOn)
+				map._tileSprites.draw(screen, 36 + map.mazeData()._surfaceTypes[v],
+				Common::Point(75, 35));
+
+			for (int xp = 85, xDiff = xDiffStart + 1; xp < 245; xp += 10, ++xDiff) {
+				v = map.mazeLookup(Common::Point(xDiff, pt.y + 8), 0, 0xffff);
+
+				if (v != INVALID_CELL && map._currentSurfaceId != 0 && map._currentSteppedOn)
+					map._tileSprites.draw(screen, 36 + map.mazeData()._surfaceTypes[v],
+					Common::Point(xp, 35));
+			}
+
+			for (int xp = 80, yp = 158, xDiff = pt.x - 7, yDiff = pt.y - 8; xp < 250; 
+					xp += 10, yp += 8, ++xDiff, ++yDiff) {
+				v = map.mazeLookup(Common::Point(pt.x - 8, yDiff), 12);
+
+				int frame;
+				switch (v) {
+				case SURFTYPE_WATER:
+					frame = 18;
+					break;
+				case SURFTYPE_GRASS:
+					frame = 24;
+					break;
+				case SURFTYPE_SNOW:
+				case SURFTYPE_SEWER:
+					frame = 16;
+					break;
+				case SURFTYPE_SWAMP:
+				case SURFTYPE_ROAD:
+					frame = 2;
+					break;
+				case SURFTYPE_LAVA:
+					frame = 30;
+					break;
+				case SURFTYPE_DESERT:
+					frame = 32;
+					break;
+				case SURFTYPE_DWATER:
+					frame = 20;
+					break;
+				case SURFTYPE_TFLR:
+					frame = 28;
+					break;
+				case SURFTYPE_SKY:
+					frame = 14;
+					break;
+				case SURFTYPE_CROAD:
+					frame = frame2 + 4;
+					break;
+				case SURFTYPE_CLOUD:
+					frame = 24;
+					break;
+				case SURFTYPE_SCORCH:
+					frame = 26;
+					break;
+				default:
+					frame = -1;
+					break;
+				}
+
+				if (frame != -1 && map._currentSteppedOn)
+					map._tileSprites.draw(screen, frame, Common::Point(70, yp));
+
+				v = map.mazeLookup(Common::Point(xDiff, pt.y + 8), 0);
+
+				switch (v) {
+				case SURFTYPE_WATER:
+					frame = 19;
+					break;
+				case SURFTYPE_DIRT:
+					frame = 35;
+					break;
+				case SURFTYPE_GRASS:
+					frame = 23;
+					break;
+				case SURFTYPE_SNOW:
+				case SURFTYPE_SEWER:
+					frame = 17;
+					break;
+				case SURFTYPE_SWAMP:
+				case SURFTYPE_ROAD:
+					frame = 3;
+					break;
+				case SURFTYPE_LAVA:
+					frame = 31;
+					break;
+				case SURFTYPE_DESERT:
+					frame = 33;
+					break;
+				case SURFTYPE_DWATER:
+					frame = 21;
+					break;
+				case SURFTYPE_TFLR:
+					frame = 29;
+					break;
+				case SURFTYPE_SKY:
+					frame = 15;
+					break;
+				case SURFTYPE_CROAD:
+					frame = frame2 + 5;
+					break;
+				case SURFTYPE_CLOUD:
+					frame = 25;
+					break;
+				case SURFTYPE_SCORCH:
+					frame = 27;
+					break;
+				default:
+					frame = -1;
+					break;
+				}
+
+				if (frame != -1 && map._currentSteppedOn)
+					map._tileSprites.draw(screen, frame, Common::Point(xp, 30));
+			}
+
+			for (int yCtr = 0, yDiff = yDiffStart - 1, yp = 38; yCtr < 16;
+				++yCtr, --yDiff, yp += 8) {
+				for (int xp = 80, xDiff = xDiffStart + 1; xp < 240; xp += 10, ++xDiff) {
+					v = map.mazeLookup(Common::Point(xDiff, yDiff), 0, 0xffff);
+
+					if (v != INVALID_CELL && map._currentSteppedOn)
+						map._tileSprites.draw(screen, 0, Common::Point(xp, yp));
+				}
+			}
+		}
+
+		screen._windows[5].frame();
+		if (!map._isOutdoors) {
+			map._tileSprites.draw(screen, 52, Common::Point(76, 30));
+		} else if (frameEndFlag) {
+			globalSprites.draw(screen, party._mazeDirection + 1,
+				Common::Point(arrowPt.x + 76, arrowPt.y + 25));
+		}
+
+		if (events.timeElapsed() > 5) {
+			// Set the flag to make the basic arrow blinking effect
+			frameEndFlag = true;
+			events.updateGameCounter();
+		}
+
+		screen._windows[5].writeString(Common::String::format(MAP_TEXT,
+			map._mazeName.c_str(), party._mazePosition.x,
+			party._mazePosition.y, DIRECTION_TEXT[party._mazeDirection]));
+		screen._windows[5].update();
+		screen._windows[3].update();
+
+		events.pollEvents();
+	} while (!_vm->shouldQuit() && !events.isKeyMousePressed());
+
+	events.clearEvents();
+	screen._windows[5].close();
+}
+
+} // End of namespace Xeen
diff --git a/engines/xeen/dialogs_automap.h b/engines/xeen/dialogs_automap.h
new file mode 100644
index 0000000..f20f9b0
--- /dev/null
+++ b/engines/xeen/dialogs_automap.h
@@ -0,0 +1,45 @@
+/* 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_AUTOMAP_H
+#define XEEN_DIALOGS_AUTOMAP_H
+
+#include "xeen/dialogs.h"
+
+namespace Xeen {
+
+class XeenEngine;
+
+class AutoMapDialog: public ButtonContainer {
+private:
+	XeenEngine *_vm;
+
+	AutoMapDialog(XeenEngine *vm) : ButtonContainer(), _vm(vm) {}
+
+	void execute();
+public:
+	static void show(XeenEngine *vm);
+};
+
+} // End of namespace Xeen
+
+#endif /* XEEN_DIALOGS_AUTOMAP_H */
diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp
index ece8ff3..d3fe234 100644
--- a/engines/xeen/interface.cpp
+++ b/engines/xeen/interface.cpp
@@ -22,6 +22,7 @@
 
 #include "xeen/interface.h"
 #include "xeen/dialogs_error.h"
+#include "xeen/dialogs_automap.h"
 #include "xeen/resources.h"
 #include "xeen/xeen.h"
 
@@ -672,6 +673,12 @@ void Interface::perform() {
 		// Toggle minimap
 		party._automapOn = !party._automapOn;
 		break;
+
+	case Common::KEYCODE_m:
+		// Show map dialog
+		AutoMapDialog::show(_vm);
+		break;
+
 	default:
 		break;
 	}
diff --git a/engines/xeen/interface_map.cpp b/engines/xeen/interface_map.cpp
index dcae6cc..46f5272 100644
--- a/engines/xeen/interface_map.cpp
+++ b/engines/xeen/interface_map.cpp
@@ -4580,7 +4580,7 @@ void InterfaceMap::assembleBorder() {
 
 	// Draw direction character if direction sense is active
 	if (_vm->_party->checkSkill(DIRECTION_SENSE) && !_vm->_noDirectionSense) {
-		const char *dirText = DIRECTION_TEXT[_vm->_party->_mazeDirection];
+		const char *dirText = DIRECTION_TEXT_UPPER[_vm->_party->_mazeDirection];
 		Common::String msg = Common::String::format(
 			"\002""08\003""c\013""139\011""116%c\014""d\001", *dirText);
 		screen._windows[0].writeString(msg);
diff --git a/engines/xeen/map.h b/engines/xeen/map.h
index 7d268ef..abc3641 100644
--- a/engines/xeen/map.h
+++ b/engines/xeen/map.h
@@ -347,7 +347,6 @@ class Map {
 private:
 	XeenEngine *_vm;
 	MazeData _mazeData[9];
-	Common::String _mazeName;
 	SpriteResource _wallPicSprites;
 	int _sideTownPortal;
 	int _sidePictures;
@@ -357,6 +356,7 @@ private:
 
 	void loadEvents(int mapId);
 public:
+	Common::String _mazeName;
 	bool _isOutdoors;
 	MonsterObjectData _mobData;
 	MonsterData _monsterData;
diff --git a/engines/xeen/module.mk b/engines/xeen/module.mk
index be95123..50a8947 100644
--- a/engines/xeen/module.mk
+++ b/engines/xeen/module.mk
@@ -8,6 +8,8 @@ MODULE_OBJS := \
 	debugger.o \
 	detection.o \
 	dialogs.o \
+	automap.o \
+	dialogs_automap.o \
 	dialogs_confirm.o \
 	dialogs_error.o \
 	dialogs_options.o \
diff --git a/engines/xeen/resources.cpp b/engines/xeen/resources.cpp
index ed304dc..05eff2d 100644
--- a/engines/xeen/resources.cpp
+++ b/engines/xeen/resources.cpp
@@ -271,7 +271,9 @@ const byte TEXT_COLORS[40][4] = {
 	{ 0x00, 0xDB, 0xDB, 0xDB },
 };
 
-const char *const DIRECTION_TEXT[4] = { "NORTH", "EAST", "SOUTH", "WEST" };
+const char *const DIRECTION_TEXT_UPPER[4] = { "NORTH", "EAST", "SOUTH", "WEST" };
+
+const char *const DIRECTION_TEXT[4] = { "North", "East", "South", "West" };
 
 const char *const RACE_NAMES[5] = { "Human", "Elf", "Dwarf", "Gnome", "H-Orc" };
 
@@ -815,15 +817,19 @@ const char *const SPELLS_PURCHASE =
 	"\xC""09%s\xC""d for %u?"; 
 
 const char *const SPELL_DETAILS =
-"\xD\x2\x3""c\xB""122\x9""013\xC""37C\xC""dast"
-"\x9""040\xC""37N\xC""dew\x9""067ESC\x1""000\xB""000\x3""cCast Spell\n"
-"\n"
-"%s\x3l\n"
-"\n"
-"Spell Ready:\x3""c\n"
-"\n"
-"\xC""09%s\xC""d\x2\x3l\n"
-"\xB""082Cost\x3r\x9""000%u/%u\x3l\n"
-"Cur SP\x3r\x9""000%u\x1";
+	"\xD\x2\x3""c\xB""122\x9""013\xC""37C\xC""dast"
+	"\x9""040\xC""37N\xC""dew\x9""067ESC\x1""000\xB""000\x3""cCast Spell\n"
+	"\n"
+	"%s\x3l\n"
+	"\n"
+	"Spell Ready:\x3""c\n"
+	"\n"
+	"\xC""09%s\xC""d\x2\x3l\n"
+	"\xB""082Cost\x3r\x9""000%u/%u\x3l\n"
+	"Cur SP\x3r\x9""000%u\x1";
+
+const char *const MAP_TEXT =
+	"\x3""c\xB""000\x9""000%s\x3l\xB""139"
+	"\x9""000X = %d\x3r\x9""000Y = %d\x3""c\x9""000%s";
 
 } // End of namespace Xeen
diff --git a/engines/xeen/resources.h b/engines/xeen/resources.h
index 37afb2c..70fdcf6 100644
--- a/engines/xeen/resources.h
+++ b/engines/xeen/resources.h
@@ -56,6 +56,8 @@ extern const byte SYMBOLS[20][64];
 
 extern const byte TEXT_COLORS[40][4];
 
+extern const char *const DIRECTION_TEXT_UPPER[4];
+
 extern const char *const DIRECTION_TEXT[4];
 
 extern const char *const RACE_NAMES[5];
@@ -244,6 +246,8 @@ extern const char *const SPELLS_PURCHASE;
 
 extern const char *const SPELL_DETAILS;
 
+extern const char *const MAP_TEXT;
+
 } // End of namespace Xeen
 
 #endif	/* XEEN_RESOURCES_H */


Commit: b22418de083e8eee1eb88e83a3b3acec6956d74b
    https://github.com/scummvm/scummvm/commit/b22418de083e8eee1eb88e83a3b3acec6956d74b
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-01-31T12:17:15-05:00

Commit Message:
XEEN: Bugfixes for the automap dialog

Changed paths:
    engines/xeen/dialogs_automap.cpp



diff --git a/engines/xeen/dialogs_automap.cpp b/engines/xeen/dialogs_automap.cpp
index 08cf593..da75f5e 100644
--- a/engines/xeen/dialogs_automap.cpp
+++ b/engines/xeen/dialogs_automap.cpp
@@ -41,10 +41,8 @@ void AutoMapDialog::execute() {
 	Party &party = *_vm->_party;
 	int frame2 = intf._overallFrame * 2;
 	int varSI = 1;
-	bool frameEndFlag;
+	bool frameEndFlag = false;
 
-	int yDiffStart = 8;
-	int xDiffStart = 248;
 	Common::Point pt = party._mazePosition;
 	Common::Point arrowPt;
 	SpriteResource globalSprites;
@@ -82,15 +80,14 @@ void AutoMapDialog::execute() {
 	
 	events.updateGameCounter();
 	do {
-		if (drawFlag)
-			intf.draw3d(false);
+//		if (drawFlag)
+//			intf.draw3d(false);
 		screen._windows[5].writeString("\n");
 
 		if (map._isOutdoors) {
 			// Draw outdoors map
-			for (int yCtr = 0, yDiff = yDiffStart - 1, yp = 38; yCtr < 16; 
-					++yCtr, --yDiff, yp += 8) {
-				for (int xp = 80, xDiff = xDiffStart + 1; xp < 240; xp += 10, ++xDiff) {
+			for (int yp = 38, yDiff = pt.y + 7; pt.y < 166; --yDiff, yp += 8) {
+				for (int xp = 80, xDiff = pt.x - 7; xp < 240; xp += 10, ++xDiff) {
 					v = map.mazeLookup(Common::Point(xDiff, yDiff), 0);
 
 					if (map._currentSteppedOn) {
@@ -100,9 +97,8 @@ void AutoMapDialog::execute() {
 				}
 			}
 
-			for (int yCtr = 0, yDiff = yDiffStart - 1, yp = 38; yCtr < 16;
-				++yCtr, --yDiff, yp += 8) {
-				for (int xp = 80, xDiff = xDiffStart + 1; xp < 240; xp += 10, ++xDiff) {
+			for (int yp = 38, yDiff = pt.y + 7; yp < 166; --yDiff, yp += 8) {
+				for (int xp = 80, xDiff = pt.x - 7; xp < 240; xp += 10, ++xDiff) {
 					v = map.mazeLookup(Common::Point(xDiff, yDiff), 4);
 					int wallType = map.mazeDataCurrent()._wallTypes[v];
 
@@ -111,124 +107,12 @@ void AutoMapDialog::execute() {
 				}
 			}
 
-			for (int yCtr = 0, yDiff = yDiffStart - 1, yp = 38; yCtr < 16;
-				++yCtr, --yDiff, yp += 8) {
-				for (int xCtr = 0, xp = 80, xDiff = xDiffStart + 1; xp < 240; 
-						++xCtr, ++xDiff, xp += 10) {
-					if (xCtr == (arrowPt.x / 10) && yCtr == (14 - (arrowPt.y)) && frameEndFlag)
-						map._tileSprites.draw(screen, party._mazeDirection + 1,
-							Common::Point(arrowPt.x + 81, arrowPt.y + 29));
-					
-					v = map.mazeLookup(Common::Point(xDiff, yDiff), 12);					
-					int frame;
-					switch (v) {
-					case SURFTYPE_WATER:
-						frame = 18;
-						break;
-					case SURFTYPE_DIRT:
-						frame = 34;
-						break;
-					case SURFTYPE_GRASS:
-						frame = 22;
-						break;
-					case SURFTYPE_SNOW:
-					case SURFTYPE_SEWER:
-						frame = 16;
-						break;
-					case SURFTYPE_SWAMP:
-					case SURFTYPE_ROAD:
-						frame = 2;
-					case SURFTYPE_LAVA:
-						frame = 30;
-						break;
-					case SURFTYPE_DESERT:
-						frame = 32;
-						break;
-					case SURFTYPE_DWATER:
-						frame = 20;
-						break;
-					case SURFTYPE_TFLR:
-						frame = 28;
-						break;
-					case SURFTYPE_SKY:
-						frame = 14;
-						break;
-					case SURFTYPE_CROAD:
-						frame = frame2 + 4;
-						break;
-					case SURFTYPE_CLOUD:
-						frame = 24;
-						break;
-					case SURFTYPE_SCORCH:
-						frame = 26;
-						break;
-					default:
-						frame = -1;
-						break;
-					}
-					
-					if (frame != -1 && map._currentSteppedOn)
-						map._tileSprites.draw(screen, frame, Common::Point(xp, yp));
-
-					v = map.mazeLookup(Common::Point(xDiff, yDiff), 0);
-					switch (v) {
-					case SURFTYPE_WATER:
-						frame = 19;
-						break;
-					case SURFTYPE_DIRT:
-						frame = 35;
-						break;
-					case SURFTYPE_GRASS:
-						frame = 23;
-						break;
-					case SURFTYPE_SNOW:
-					case SURFTYPE_SEWER:
-						frame = 17;
-						break;
-					case SURFTYPE_SWAMP:
-					case SURFTYPE_ROAD:
-						frame = 3;
-						break;
-					case SURFTYPE_LAVA:
-						frame = 31;
-						break;
-					case SURFTYPE_DESERT:
-						frame = 33;
-						break;
-					case SURFTYPE_DWATER:
-						frame = 21;
-						break;
-					case SURFTYPE_TFLR:
-						frame = 29;
-						break;
-					case SURFTYPE_SKY:
-						frame = 15;
-						break;
-					case SURFTYPE_CROAD:
-						frame = frame2 + 5;
-						break;
-					case SURFTYPE_CLOUD:
-						frame = 25;
-						break;
-					case SURFTYPE_SCORCH:
-						frame = 27;
-						break;
-					default:
-						frame = -1;
-						break;
-					}
-					
-					if (frame != -1 && map._currentSteppedOn)
-						map._tileSprites.draw(screen, frame, Common::Point(xp, yp));
-				}
-			}
+		
+			for (int yp = 38, yDiff = pt.y + 7; yp < 166; yp += 8, --yDiff) {
+				for (int xp = 80, xDiff = -7; xp < 240; xp += 10, ++xDiff) {
+					v = map.mazeLookup(Common::Point(xDiff, yDiff), 8);
 
-			for (int yCtr = 0, yDiff = yDiffStart - 1, yp = 38; yCtr < 16;
-				++yCtr, --yDiff, yp += 8) {
-				for (int xp = 80, xDiff = xDiffStart + 1; xp < 240; xp += 10, ++xDiff) {
-					v = map.mazeLookup(Common::Point(xDiff, yDiff), 0, 0xffff);
-
-					if (v != INVALID_CELL && map._currentSteppedOn)
+					if (v && map._currentSteppedOn)
 						map._tileSprites.draw(screen, 1, Common::Point(xp, yp));
 				}
 			}
@@ -236,79 +120,94 @@ void AutoMapDialog::execute() {
 			// Draw indoors map
 			frame2 = (frame2 + 2) % 8;
 
-			for (int yCtr = 0, yDiff = yDiffStart - 1, yp = 38; yCtr < 16;
-				++yCtr, --yDiff, yp += 8) {
-				for (int xp = 80, xDiff = xDiffStart + 1; xp < 240; xp += 10, ++xDiff) {
+			// Draw ground tiles
+			for (int yp = 38, yDiff = pt.y + 7; yp < 166; yp += 8, --yDiff) {
+				for (int xp = 80, xDiff = pt.x - 7; xp < 240; xp += 10, ++xDiff) {
 					v = map.mazeLookup(Common::Point(xDiff, yDiff), 0, 0xffff);
 
 					if (v != INVALID_CELL && map._currentSteppedOn)
 						map._tileSprites.draw(screen, 0, Common::Point(xp, yp));
 				}
 			}
-
-			for (int yDiff = yDiffStart - 1, yp = 38; yp < 171; --yDiff, yp += 8) {
+			
+			// Draw thinner ground tiles on the left edge of the map
+			for (int yp = 43, yDiff = pt.y + 7; yp < 171; yp += 8, --yDiff) {
 				v = map.mazeLookup(Common::Point(pt.x - 8, yDiff), 0, 0xffff);
 
 				if (v != INVALID_CELL && map._currentSurfaceId != 0 && map._currentSteppedOn)
-					map._tileSprites.draw(screen, 36 + map.mazeData()._surfaceTypes[v],
-						Common::Point(75, yp));
+					map._tileSprites.draw(screen, 36 + map.mazeData()._surfaceTypes[
+						map._currentSurfaceId], Common::Point(75, yp));
 			}
-
+			
+			// Draw thin tile portion on top-left corner of map
 			v = map.mazeLookup(Common::Point(pt.x - 8, pt.y + 8), 0, 0xffff);
 			if (v != INVALID_CELL && map._currentSurfaceId != 0 && map._currentSteppedOn)
-				map._tileSprites.draw(screen, 36 + map.mazeData()._surfaceTypes[v],
-				Common::Point(75, 35));
-
-			for (int xp = 85, xDiff = xDiffStart + 1; xp < 245; xp += 10, ++xDiff) {
+				map._tileSprites.draw(screen, 36 + map.mazeData()._surfaceTypes[
+					map._currentSurfaceId], Common::Point(75, 35));
+			
+			// Draw any thin tiles at the very top of the map
+			for (int xp = 85, xDiff = pt.x - 7; xp < 245; xp += 10, ++xDiff) {
 				v = map.mazeLookup(Common::Point(xDiff, pt.y + 8), 0, 0xffff);
 
 				if (v != INVALID_CELL && map._currentSurfaceId != 0 && map._currentSteppedOn)
-					map._tileSprites.draw(screen, 36 + map.mazeData()._surfaceTypes[v],
-					Common::Point(xp, 35));
+					map._tileSprites.draw(screen, 36 + map.mazeData()._surfaceTypes[
+						map._currentSurfaceId], Common::Point(xp, 35));
+			}
+
+			// Draw the default ground tiles
+			for (int yp = 43, yDiff = pt.y + 7; yp < 171; yp += 8, --yDiff) {
+				for (int xp = 85, xDiff = pt.x - 7; xp < 245; xp += 10, ++xDiff) {
+					v = map.mazeLookup(Common::Point(xDiff, yDiff), 0, 0xffff);
+
+					if (v != INVALID_CELL && map._currentSteppedOn)
+						map._tileSprites.draw(screen, 0, Common::Point(xp, yp));
+				}
 			}
 
+			// Draw walls on left and top edges of map
 			for (int xp = 80, yp = 158, xDiff = pt.x - 7, yDiff = pt.y - 8; xp < 250; 
-					xp += 10, yp += 8, ++xDiff, ++yDiff) {
+					xp += 10, yp -= 8, ++xDiff, ++yDiff) {
+				// Draw walls on left edge of map
 				v = map.mazeLookup(Common::Point(pt.x - 8, yDiff), 12);
 
 				int frame;
 				switch (v) {
-				case SURFTYPE_WATER:
+				case SURFTYPE_DIRT:
 					frame = 18;
 					break;
-				case SURFTYPE_GRASS:
-					frame = 24;
-					break;
 				case SURFTYPE_SNOW:
-				case SURFTYPE_SEWER:
-					frame = 16;
+					frame = 22;
 					break;
 				case SURFTYPE_SWAMP:
-				case SURFTYPE_ROAD:
-					frame = 2;
+				case SURFTYPE_CLOUD:
+					frame = 16;
 					break;
 				case SURFTYPE_LAVA:
-					frame = 30;
+				case SURFTYPE_DWATER:
+					frame = 2;
 					break;
 				case SURFTYPE_DESERT:
+					frame = 30;
+					break;
+				case SURFTYPE_ROAD:
 					frame = 32;
 					break;
-				case SURFTYPE_DWATER:
+				case SURFTYPE_TFLR:
 					frame = 20;
 					break;
-				case SURFTYPE_TFLR:
+				case SURFTYPE_SKY:
 					frame = 28;
 					break;
-				case SURFTYPE_SKY:
+				case SURFTYPE_CROAD:
 					frame = 14;
 					break;
-				case SURFTYPE_CROAD:
+				case SURFTYPE_SEWER:
 					frame = frame2 + 4;
 					break;
-				case SURFTYPE_CLOUD:
+				case SURFTYPE_SCORCH:
 					frame = 24;
 					break;
-				case SURFTYPE_SCORCH:
+				case SURFTYPE_SPACE:
 					frame = 26;
 					break;
 				default:
@@ -319,48 +218,49 @@ void AutoMapDialog::execute() {
 				if (frame != -1 && map._currentSteppedOn)
 					map._tileSprites.draw(screen, frame, Common::Point(70, yp));
 
+				// Draw walls on top edge of map
 				v = map.mazeLookup(Common::Point(xDiff, pt.y + 8), 0);
 
 				switch (v) {
-				case SURFTYPE_WATER:
+				case SURFTYPE_DIRT:
 					frame = 19;
 					break;
-				case SURFTYPE_DIRT:
+				case SURFTYPE_GRASS:
 					frame = 35;
 					break;
-				case SURFTYPE_GRASS:
+				case SURFTYPE_SNOW:
 					frame = 23;
 					break;
-				case SURFTYPE_SNOW:
-				case SURFTYPE_SEWER:
+				case SURFTYPE_SWAMP:
+				case SURFTYPE_CLOUD:
 					frame = 17;
 					break;
-				case SURFTYPE_SWAMP:
-				case SURFTYPE_ROAD:
+				case SURFTYPE_LAVA:
+				case SURFTYPE_DWATER:
 					frame = 3;
 					break;
-				case SURFTYPE_LAVA:
+				case SURFTYPE_DESERT:
 					frame = 31;
 					break;
-				case SURFTYPE_DESERT:
+				case SURFTYPE_ROAD:
 					frame = 33;
 					break;
-				case SURFTYPE_DWATER:
+				case SURFTYPE_TFLR:
 					frame = 21;
 					break;
-				case SURFTYPE_TFLR:
+				case SURFTYPE_SKY:
 					frame = 29;
 					break;
-				case SURFTYPE_SKY:
+				case SURFTYPE_CROAD:
 					frame = 15;
 					break;
-				case SURFTYPE_CROAD:
+				case SURFTYPE_SEWER:
 					frame = frame2 + 5;
 					break;
-				case SURFTYPE_CLOUD:
+				case SURFTYPE_SCORCH:
 					frame = 25;
 					break;
-				case SURFTYPE_SCORCH:
+				case SURFTYPE_SPACE:
 					frame = 27;
 					break;
 				default:
@@ -372,12 +272,125 @@ void AutoMapDialog::execute() {
 					map._tileSprites.draw(screen, frame, Common::Point(xp, 30));
 			}
 
-			for (int yCtr = 0, yDiff = yDiffStart - 1, yp = 38; yCtr < 16;
-				++yCtr, --yDiff, yp += 8) {
-				for (int xp = 80, xDiff = xDiffStart + 1; xp < 240; xp += 10, ++xDiff) {
+			for (int yCtr = 0, yp = 38, yDiff = pt.y + 7; yCtr < 16; ++yCtr, yp += 8, --yDiff) {
+				for (int xCtr = 0, xp = 80, xDiff = pt.x - 7; xCtr < 16; ++xCtr, xp += 10, ++xDiff) {
+					// Draw the arrow if at the correct position
+					if ((arrowPt.x / 10) == xCtr && (14 - (arrowPt.y / 10)) == yCtr && frameEndFlag) {
+						globalSprites.draw(screen, party._mazeDirection + 1,
+							Common::Point(arrowPt.x, arrowPt.y + 29));
+					}
+
+					v = map.mazeLookup(Common::Point(xDiff, yDiff), 12);
+					int frame;
+					switch (v) {
+					case SURFTYPE_DIRT:
+						frame = 18;
+						break;
+					case SURFTYPE_GRASS:
+						frame = 34;
+						break;
+					case SURFTYPE_SNOW:
+						frame = 22;
+						break;
+					case SURFTYPE_SWAMP:
+					case SURFTYPE_CLOUD:
+						frame = 16;
+						break;
+					case SURFTYPE_LAVA:
+					case SURFTYPE_DWATER:
+						frame = 2;
+						break;
+					case SURFTYPE_DESERT:
+						frame = 30;
+						break;
+					case SURFTYPE_ROAD:
+						frame = 32;
+						break;
+					case SURFTYPE_TFLR:
+						frame = 20;
+						break;
+					case SURFTYPE_SKY:
+						frame = 28;
+						break;
+					case SURFTYPE_CROAD:
+						frame = 14;
+						break;
+					case SURFTYPE_SEWER:
+						frame = frame2 + 4;
+						break;
+					case SURFTYPE_SCORCH:
+						frame = 24;
+						break;
+					case SURFTYPE_SPACE:
+						frame = 26;
+						break;
+					default:
+						frame = -1;
+						break;
+					}
+
+					if (frame != -1 && map._currentSteppedOn)
+						map._tileSprites.draw(screen, frame, Common::Point(xp, yp));
+
+					v = map.mazeLookup(Common::Point(xDiff, yDiff), 0);
+					switch (v) {
+					case SURFTYPE_DIRT:
+						frame = 19;
+						break;
+					case SURFTYPE_GRASS:
+						frame = 35;
+						break;
+					case SURFTYPE_SNOW:
+						frame = 23;
+						break;
+					case SURFTYPE_SWAMP:
+					case SURFTYPE_CLOUD:
+						frame = 17;
+						break;
+					case SURFTYPE_LAVA:
+					case SURFTYPE_DWATER:
+						frame = 3;
+						break;
+					case SURFTYPE_DESERT:
+						frame = 31;
+						break;
+					case SURFTYPE_ROAD:
+						frame = 33;
+						break;
+					case SURFTYPE_TFLR:
+						frame = 21;
+						break;
+					case SURFTYPE_SKY:
+						frame = 29;
+						break;
+					case SURFTYPE_CROAD:
+						frame = 15;
+						break;
+					case SURFTYPE_SEWER:
+						frame = frame2 + 5;
+						break;
+					case SURFTYPE_SCORCH:
+						frame = 25;
+						break;
+					case SURFTYPE_SPACE:
+						frame = 27;
+						break;
+					default:
+						frame = -1;
+						break;
+					}
+
+					if (frame != -1 && map._currentSteppedOn)
+						map._tileSprites.draw(screen, frame, Common::Point(xp, yp));
+				}
+			}
+
+			// Draw overlay on cells that haven't been stepped on yet
+			for (int yDiff = pt.y + 7, yp = 38; yp < 166; --yDiff, yp += 8) {
+				for (int xp = 80, xDiff = pt.x - 7; xp < 240; xp += 10, ++xDiff) {
 					v = map.mazeLookup(Common::Point(xDiff, yDiff), 0, 0xffff);
 
-					if (v != INVALID_CELL && map._currentSteppedOn)
+					if (v != INVALID_CELL && !map._currentSteppedOn)
 						map._tileSprites.draw(screen, 0, Common::Point(xp, yp));
 				}
 			}
@@ -393,7 +406,7 @@ void AutoMapDialog::execute() {
 
 		if (events.timeElapsed() > 5) {
 			// Set the flag to make the basic arrow blinking effect
-			frameEndFlag = true;
+			frameEndFlag = !frameEndFlag;
 			events.updateGameCounter();
 		}
 


Commit: d67b8d364d8c2a48d26fd0349cc902786b50235b
    https://github.com/scummvm/scummvm/commit/d67b8d364d8c2a48d26fd0349cc902786b50235b
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-01-31T15:28:53-05:00

Commit Message:
XEEN: More automap dialog fixes

Changed paths:
    engines/xeen/dialogs_automap.cpp



diff --git a/engines/xeen/dialogs_automap.cpp b/engines/xeen/dialogs_automap.cpp
index da75f5e..5399110 100644
--- a/engines/xeen/dialogs_automap.cpp
+++ b/engines/xeen/dialogs_automap.cpp
@@ -80,8 +80,8 @@ void AutoMapDialog::execute() {
 	
 	events.updateGameCounter();
 	do {
-//		if (drawFlag)
-//			intf.draw3d(false);
+		if (drawFlag)
+			intf.draw3d(false);
 		screen._windows[5].writeString("\n");
 
 		if (map._isOutdoors) {
@@ -277,7 +277,7 @@ void AutoMapDialog::execute() {
 					// Draw the arrow if at the correct position
 					if ((arrowPt.x / 10) == xCtr && (14 - (arrowPt.y / 10)) == yCtr && frameEndFlag) {
 						globalSprites.draw(screen, party._mazeDirection + 1,
-							Common::Point(arrowPt.x, arrowPt.y + 29));
+							Common::Point(arrowPt.x + 81, arrowPt.y + 29));
 					}
 
 					v = map.mazeLookup(Common::Point(xDiff, yDiff), 12);
@@ -384,14 +384,14 @@ void AutoMapDialog::execute() {
 						map._tileSprites.draw(screen, frame, Common::Point(xp, yp));
 				}
 			}
-
+			
 			// Draw overlay on cells that haven't been stepped on yet
 			for (int yDiff = pt.y + 7, yp = 38; yp < 166; --yDiff, yp += 8) {
 				for (int xp = 80, xDiff = pt.x - 7; xp < 240; xp += 10, ++xDiff) {
 					v = map.mazeLookup(Common::Point(xDiff, yDiff), 0, 0xffff);
 
-					if (v != INVALID_CELL && !map._currentSteppedOn)
-						map._tileSprites.draw(screen, 0, Common::Point(xp, yp));
+					if (v == INVALID_CELL || !map._currentSteppedOn)
+						map._tileSprites.draw(screen, 1, Common::Point(xp, yp));
 				}
 			}
 		}
@@ -417,6 +417,7 @@ void AutoMapDialog::execute() {
 		screen._windows[3].update();
 
 		events.pollEvents();
+		drawFlag = false;
 	} while (!_vm->shouldQuit() && !events.isKeyMousePressed());
 
 	events.clearEvents();


Commit: 73a522150f5097e83f9ea24974265fcb1c827a99
    https://github.com/scummvm/scummvm/commit/73a522150f5097e83f9ea24974265fcb1c827a99
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-01-31T15:51:20-05:00

Commit Message:
XEEN: Yet more bugfixes for automap dialog

Changed paths:
    engines/xeen/dialogs_automap.cpp
    engines/xeen/interface_map.cpp



diff --git a/engines/xeen/dialogs_automap.cpp b/engines/xeen/dialogs_automap.cpp
index 5399110..6182142 100644
--- a/engines/xeen/dialogs_automap.cpp
+++ b/engines/xeen/dialogs_automap.cpp
@@ -120,7 +120,7 @@ void AutoMapDialog::execute() {
 			// Draw indoors map
 			frame2 = (frame2 + 2) % 8;
 
-			// Draw ground tiles
+			// Draw default ground for all the valid explored areas
 			for (int yp = 38, yDiff = pt.y + 7; yp < 166; yp += 8, --yDiff) {
 				for (int xp = 80, xDiff = pt.x - 7; xp < 240; xp += 10, ++xDiff) {
 					v = map.mazeLookup(Common::Point(xDiff, yDiff), 0, 0xffff);
@@ -159,8 +159,9 @@ void AutoMapDialog::execute() {
 				for (int xp = 85, xDiff = pt.x - 7; xp < 245; xp += 10, ++xDiff) {
 					v = map.mazeLookup(Common::Point(xDiff, yDiff), 0, 0xffff);
 
-					if (v != INVALID_CELL && map._currentSteppedOn)
-						map._tileSprites.draw(screen, 0, Common::Point(xp, yp));
+					if (v != INVALID_CELL && map._currentSurfaceId && map._currentSteppedOn)
+						map._tileSprites.draw(screen, map.mazeData()._surfaceTypes[
+							map._currentSurfaceId], Common::Point(xp, yp));
 				}
 			}
 
@@ -272,6 +273,7 @@ void AutoMapDialog::execute() {
 					map._tileSprites.draw(screen, frame, Common::Point(xp, 30));
 			}
 
+			// Draw any walls on the cells
 			for (int yCtr = 0, yp = 38, yDiff = pt.y + 7; yCtr < 16; ++yCtr, yp += 8, --yDiff) {
 				for (int xCtr = 0, xp = 80, xDiff = pt.x - 7; xCtr < 16; ++xCtr, xp += 10, ++xDiff) {
 					// Draw the arrow if at the correct position
diff --git a/engines/xeen/interface_map.cpp b/engines/xeen/interface_map.cpp
index 46f5272..84f8fa6 100644
--- a/engines/xeen/interface_map.cpp
+++ b/engines/xeen/interface_map.cpp
@@ -756,7 +756,13 @@ void InterfaceMap::draw3d(bool updateFlag) {
 	if (_vm->_mode == MODE_9) {
 		// TODO
 	}
-	events.wait(2);
+
+	// TODO: Check use of updateFlag here. Original doesn't have it, but I
+	// wanted to ensure in places like the AutoMapDialog, that the draw3d
+	// doesn't result in the screen updating until the dialog has had
+	// a chance to full render itself
+	if (updateFlag)
+		events.wait(2);
 }
 
 /**


Commit: 40b2f886c374129bcb275400d1228752f20154da
    https://github.com/scummvm/scummvm/commit/40b2f886c374129bcb275400d1228752f20154da
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-01-31T17:39:52-05:00

Commit Message:
XEEN: Implement the Info dialog

Changed paths:
  A engines/xeen/dialogs_info.cpp
  A engines/xeen/dialogs_info.h
    engines/xeen/interface.cpp
    engines/xeen/module.mk
    engines/xeen/resources.cpp
    engines/xeen/resources.h



diff --git a/engines/xeen/dialogs_info.cpp b/engines/xeen/dialogs_info.cpp
new file mode 100644
index 0000000..7ccaa7f
--- /dev/null
+++ b/engines/xeen/dialogs_info.cpp
@@ -0,0 +1,128 @@
+/* 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 "xeen/dialogs_info.h"
+#include "xeen/resources.h"
+#include "xeen/xeen.h"
+
+namespace Xeen {
+
+void InfoDialog::show(XeenEngine *vm) {
+	InfoDialog *dlg = new InfoDialog(vm);
+	dlg->execute();
+	delete dlg;
+}
+
+void InfoDialog::execute() {
+	Screen &screen = *_vm->_screen;
+	EventsManager &events = *_vm->_events;
+	Interface &intf = *_vm->_interface;
+	Party &party = *_vm->_party;
+	
+	protectionText();
+	Common::String statusText = "";
+	for (uint idx = 0; idx < _lines.size(); ++idx)
+		statusText += _lines[idx];
+
+	Common::String gameName;
+	if (_vm->getGameID() == GType_Swords)
+		gameName = SWORDS_GAME_TEXT;
+	else if (_vm->getGameID() == GType_Clouds)
+		gameName = CLOUDS_GAME_TEXT;
+	else if (_vm->getGameID() == GType_DarkSide)
+		gameName = DARKSIDE_GAME_TEXT;
+	else
+		gameName = WORLD_GAME_TEXT;
+
+	// Form the display message
+	int hour = party._minutes / 60;
+	Common::String details = Common::String::format(GAME_INFORMATION,
+		gameName.c_str(), WEEK_DAY_STRINGS[party._day % 10],
+		(hour > 12) ? hour - 12 : (!hour ? 12 : hour),
+		party._minutes % 60, (hour > 11) ? 'p' : 'a',
+		party._day, party._year, statusText.c_str());
+
+	Window &w = screen._windows[28];
+	w.setBounds(Common::Rect(88, 20, 248, 112));
+	w.open();
+
+	do {
+		events.updateGameCounter();
+		intf.draw3d(false);
+		w.frame();
+		w.writeString(details);
+		w.update();
+
+		events.wait(1, true);
+	} while (!_vm->shouldQuit() && !events.isKeyMousePressed());
+
+	events.clearEvents();
+	w.close();
+}
+
+void InfoDialog::protectionText() {
+	Party &party = *_vm->_party;
+	Common::StringArray _lines;
+	const char *const AA_L024 = "\x3l\n\x9""024";
+	const char *const AA_R124 = "\x3r\x9""124";
+
+	if (party._lightCount) {
+		_lines.push_back(Common::String::format(LIGHT_COUNT_TEXT, party._lightCount));
+	}
+
+	if (party._fireResistence) {
+		_lines.push_back(Common::String::format(FIRE_RESISTENCE_TEXT,
+			_lines.size() == 0 ? 10 : 1, AA_L024, AA_R124, party._fireResistence));
+	}
+
+	if (party._electricityResistence) {
+		_lines.push_back(Common::String::format(ELECRICITY_RESISTENCE_TEXT,
+			_lines.size() == 0 ? 10 : 1, AA_L024, AA_R124, party._electricityResistence));
+	}
+
+	if (party._coldResistence) {
+		_lines.push_back(Common::String::format(COLD_RESISTENCE_TEXT,
+			_lines.size() == 0 ? 10 : 1, AA_L024, AA_R124, party._coldResistence));
+	}
+
+	if (party._poisonResistence) {
+		_lines.push_back(Common::String::format(POISON_RESISTENCE_TEXT,
+			_lines.size() == 0 ? 10 : 1, AA_L024, AA_R124, party._poisonResistence));
+	}
+
+	if (party._clairvoyanceActive) {
+		_lines.push_back(Common::String::format(CLAIRVOYANCE_TEXT,
+			_lines.size() == 0 ? 10 : 1, AA_L024, AA_R124));
+	}
+
+	if (party._levitateActive) {
+		_lines.push_back(Common::String::format(LEVITATE_TEXT,
+			_lines.size() == 0 ? 10 : 1, AA_L024, AA_R124));
+	}
+
+	if (party._walkOnWaterActive) {
+		_lines.push_back(Common::String::format(WALK_ON_WATER_TEXT,
+			_lines.size() == 0 ? 10 : 1, AA_L024, AA_R124));
+	}
+}
+
+} // End of namespace Xeen
diff --git a/engines/xeen/dialogs_info.h b/engines/xeen/dialogs_info.h
new file mode 100644
index 0000000..66b9157
--- /dev/null
+++ b/engines/xeen/dialogs_info.h
@@ -0,0 +1,47 @@
+/* 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_INFO_H
+#define XEEN_DIALOGS_INFO_H
+
+#include "common/str-array.h"
+#include "xeen/dialogs.h"
+
+namespace Xeen {
+
+class InfoDialog : public ButtonContainer {
+private:
+	XeenEngine *_vm;
+	Common::StringArray _lines;
+
+	InfoDialog(XeenEngine *vm) : ButtonContainer(), _vm(vm) {}
+
+	void execute();
+
+	void protectionText();
+public:
+	static void show(XeenEngine *vm);
+};
+
+} // End of namespace Xeen
+
+#endif /* XEEN_DIALOGS_INFO_H */
diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp
index d3fe234..3e958b3 100644
--- a/engines/xeen/interface.cpp
+++ b/engines/xeen/interface.cpp
@@ -23,6 +23,7 @@
 #include "xeen/interface.h"
 #include "xeen/dialogs_error.h"
 #include "xeen/dialogs_automap.h"
+#include "xeen/dialogs_info.h"
 #include "xeen/resources.h"
 #include "xeen/xeen.h"
 
@@ -674,6 +675,11 @@ void Interface::perform() {
 		party._automapOn = !party._automapOn;
 		break;
 
+	case Common::KEYCODE_i:
+		// Show Info dialog
+		InfoDialog::show(_vm);
+		break;
+
 	case Common::KEYCODE_m:
 		// Show map dialog
 		AutoMapDialog::show(_vm);
diff --git a/engines/xeen/module.mk b/engines/xeen/module.mk
index 50a8947..4bb8bd9 100644
--- a/engines/xeen/module.mk
+++ b/engines/xeen/module.mk
@@ -13,6 +13,7 @@ MODULE_OBJS := \
 	dialogs_confirm.o \
 	dialogs_error.o \
 	dialogs_options.o \
+	dialogs_info.o \
 	dialogs_input.o \
 	dialogs_spells.o \
 	dialogs_whowill.o \
diff --git a/engines/xeen/resources.cpp b/engines/xeen/resources.cpp
index 05eff2d..dafe321 100644
--- a/engines/xeen/resources.cpp
+++ b/engines/xeen/resources.cpp
@@ -832,4 +832,38 @@ const char *const MAP_TEXT =
 	"\x3""c\xB""000\x9""000%s\x3l\xB""139"
 	"\x9""000X = %d\x3r\x9""000Y = %d\x3""c\x9""000%s";
 
+const char *const LIGHT_COUNT_TEXT = "\x3l\n\n\t024Light\x3r\t124%d";
+
+const char *const FIRE_RESISTENCE_TEXT = "%c%sFire%s%u";
+
+const char *const ELECRICITY_RESISTENCE_TEXT = "%c%sElectricity%s%u";
+
+const char *const COLD_RESISTENCE_TEXT = "c%sCold%s%u";
+
+const char *const POISON_RESISTENCE_TEXT = "%c%sPoison/Acid%s%u";
+
+const char *const CLAIRVOYANCE_TEXT = "%c%sClairvoyance%s";
+
+const char *const LEVITATE_TEXT = "%c%sLevitate%s";
+
+const char *const WALK_ON_WATER_TEXT = "%c%sWalk on Water";
+
+const char *const GAME_INFORMATION = 
+	"\xD\x3""c\x9""000\xB""001\xC""37%s of Xeen\xC""d\n"
+	"Game Information\n"
+	"\n"
+	"Today is \xC""37%ssday\xC""d\n"
+	"\n"
+	"\x9""032Time\x9""072Day\x9""112Year\n"
+	"\x9""032\xC""37%d:%02d%c\x9""072%u\x9""112%u\xC""d%s";
+
+const char *const WORLD_GAME_TEXT = "World";
+const char *const DARKSIDE_GAME_TEXT = "Darkside";
+const char *const CLOUDS_GAME_TEXT = "Clouds";
+const char *const SWORDS_GAME_TEXT = "Swords";
+
+const char *const WEEK_DAY_STRINGS[10] = {
+	"Ten", "One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine"
+};
+
 } // End of namespace Xeen
diff --git a/engines/xeen/resources.h b/engines/xeen/resources.h
index 70fdcf6..8beeb56 100644
--- a/engines/xeen/resources.h
+++ b/engines/xeen/resources.h
@@ -248,6 +248,34 @@ extern const char *const SPELL_DETAILS;
 
 extern const char *const MAP_TEXT;
 
+extern const char *const LIGHT_COUNT_TEXT;
+
+extern const char *const FIRE_RESISTENCE_TEXT;
+
+extern const char *const ELECRICITY_RESISTENCE_TEXT;
+
+extern const char *const COLD_RESISTENCE_TEXT;
+
+extern const char *const POISON_RESISTENCE_TEXT;
+
+extern const char *const CLAIRVOYANCE_TEXT;
+
+extern const char *const LEVITATE_TEXT;
+
+extern const char *const WALK_ON_WATER_TEXT;
+
+extern const char *const GAME_INFORMATION;
+
+extern const char *const WORLD_GAME_TEXT;
+
+extern const char *const DARKSIDE_GAME_TEXT;
+
+extern const char *const CLOUDS_GAME_TEXT;
+
+extern const char *const SWORDS_GAME_TEXT;
+
+extern const char *const WEEK_DAY_STRINGS[10];
+
 } // End of namespace Xeen
 
 #endif	/* XEEN_RESOURCES_H */


Commit: d3e3093b035bb0e13492098e3f304474d0886fa4
    https://github.com/scummvm/scummvm/commit/d3e3093b035bb0e13492098e3f304474d0886fa4
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-01-31T17:45:06-05:00

Commit Message:
XEEN: Add missing moveMonsters flag setting for automap and info dialogs

Changed paths:
    engines/xeen/interface.cpp



diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp
index 3e958b3..0ea5a8d 100644
--- a/engines/xeen/interface.cpp
+++ b/engines/xeen/interface.cpp
@@ -672,12 +672,16 @@ void Interface::perform() {
 	case Common::KEYCODE_EQUALS:
 	case Common::KEYCODE_KP_EQUALS:
 		// Toggle minimap
+		_vm->_moveMonsters = false;
 		party._automapOn = !party._automapOn;
+		_vm->_moveMonsters = true;
 		break;
 
 	case Common::KEYCODE_i:
 		// Show Info dialog
+		_vm->_moveMonsters = false;
 		InfoDialog::show(_vm);
+		_vm->_moveMonsters = true;
 		break;
 
 	case Common::KEYCODE_m:


Commit: d855aa0dab588f2993a4c4f103a4632a9f0ba278
    https://github.com/scummvm/scummvm/commit/d855aa0dab588f2993a4c4f103a4632a9f0ba278
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-02-01T11:56:08-05:00

Commit Message:
XEEN: Implemented Character Info dialog

Changed paths:
  A engines/xeen/dialogs_char_info.cpp
  A engines/xeen/dialogs_char_info.h
    engines/xeen/dialogs_automap.cpp
    engines/xeen/dialogs_spells.cpp
    engines/xeen/interface.cpp
    engines/xeen/interface_map.cpp
    engines/xeen/items.cpp
    engines/xeen/items.h
    engines/xeen/module.mk
    engines/xeen/party.cpp
    engines/xeen/party.h
    engines/xeen/resources.cpp
    engines/xeen/resources.h
    engines/xeen/town.h
    engines/xeen/xeen.h



diff --git a/engines/xeen/dialogs_automap.cpp b/engines/xeen/dialogs_automap.cpp
index 6182142..d9b7e8d 100644
--- a/engines/xeen/dialogs_automap.cpp
+++ b/engines/xeen/dialogs_automap.cpp
@@ -40,7 +40,6 @@ void AutoMapDialog::execute() {
 	Map &map = *_vm->_map;
 	Party &party = *_vm->_party;
 	int frame2 = intf._overallFrame * 2;
-	int varSI = 1;
 	bool frameEndFlag = false;
 
 	Common::Point pt = party._mazePosition;
@@ -74,7 +73,7 @@ void AutoMapDialog::execute() {
 	}
 
 	screen._windows[5].open();
-	MazeData &mazeData = map.mazeDataCurrent();
+//	MazeData &mazeData = map.mazeDataCurrent();
 	bool drawFlag = true;
 	int v;
 	
diff --git a/engines/xeen/dialogs_char_info.cpp b/engines/xeen/dialogs_char_info.cpp
new file mode 100644
index 0000000..3ff4003
--- /dev/null
+++ b/engines/xeen/dialogs_char_info.cpp
@@ -0,0 +1,567 @@
+/* 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 "xeen/dialogs_char_info.h"
+#include "xeen/resources.h"
+#include "xeen/xeen.h"
+
+namespace Xeen {
+
+void CharacterInfo::show(XeenEngine *vm, int charIndex) {
+	CharacterInfo *dlg = new CharacterInfo(vm);
+	dlg->execute(charIndex);
+	delete dlg;
+}
+
+void CharacterInfo::execute(int charIndex) {
+	Screen &screen = *_vm->_screen;
+	EventsManager &events = *_vm->_events;
+	Interface &intf = *_vm->_interface;
+	Party &party = *_vm->_party;
+	
+	bool redrawFlag = false;
+	Mode oldMode = _vm->_mode;
+	_vm->_mode = MODE_CHARACTER_INFO;
+	loadDrawStructs();
+	addButtons();
+
+	Character *c = (oldMode != MODE_InCombat) ? &party._activeParty[charIndex] : party._combatParty[charIndex];
+	intf.highlightChar(charIndex);
+	Window &w = screen._windows[24];
+	w.open();
+
+	do {
+		if (redrawFlag) {
+			Common::String charDetails = loadCharacterDetails(*c);
+			w.writeString(Common::String::format(CHARACTER_TEMPLATE, charDetails.c_str()));
+			w.drawList(_drawList, 24);
+			w.update();
+			redrawFlag = false;
+		}
+
+		// Wait for keypress, showing a blinking cursor
+		events.updateGameCounter();
+	bool cursorFlag = false;
+		while (!_vm->shouldQuit() && !events.isKeyMousePressed()) {
+			if (events.timeElapsed() > 4) {
+				cursorFlag = !cursorFlag;
+				events.updateGameCounter();
+			}
+
+			showCursor(cursorFlag);
+			w.update();
+		}
+		checkEvents(_vm);
+		events.clearEvents();
+
+		switch (_buttonValue) {
+		case Common::KEYCODE_F1:
+		case Common::KEYCODE_F2:
+		case Common::KEYCODE_F3:
+		case Common::KEYCODE_F4:
+		case Common::KEYCODE_F5:
+		case Common::KEYCODE_F6:
+			_buttonValue -= Common::KEYCODE_F1;
+			if (_buttonValue < (int)(oldMode == MODE_InCombat ? party._combatParty.size() : party._activeParty.size())) {
+				charIndex = _buttonValue;
+				c = (oldMode != MODE_InCombat) ? &party._activeParty[charIndex] : party._combatParty[charIndex];
+			}
+			else {
+				_iconSprites.load("view.icn");
+				_vm->_mode = MODE_CHARACTER_INFO;
+			}
+			break;
+
+		case Common::KEYCODE_UP:
+		case Common::KEYCODE_KP8:
+			if (_cursorCell > 0) {
+				showCursor(false);
+				--_cursorCell;
+				showCursor(true);
+			}
+			w.update();
+			break;
+
+		case Common::KEYCODE_DOWN:
+		case Common::KEYCODE_KP2:
+			if (_cursorCell < 20) {
+				showCursor(false);
+				++_cursorCell;
+				showCursor(true);
+			}
+			w.update();
+			break;
+
+		case Common::KEYCODE_LEFT:
+		case Common::KEYCODE_KP4:
+			if (_cursorCell >= 5) {
+				showCursor(false);
+				_cursorCell -= 5;
+				showCursor(true);
+			}
+			w.update();
+			break;
+
+		case Common::KEYCODE_RIGHT:
+		case Common::KEYCODE_KP6:
+			if (_cursorCell <= 15) {
+				showCursor(false);
+				_cursorCell += 5;
+				showCursor(true);
+			}
+			w.update();
+			break;
+
+		case Common::KEYCODE_RETURN:
+		case Common::KEYCODE_KP_ENTER:
+			_buttonValue = _cursorCell + Common::KEYCODE_a;
+			// Deliberate fall-through
+
+		case 1001:
+		case 1002:
+		case 1003:
+		case 1004:
+		case 1005:
+		case 1006:
+		case 1007:
+		case 1008:
+		case 1009:
+		case 1010:
+		case 1011:
+		case 1012:
+		case 1013:
+		case 1014:
+		case 1015:
+		case 1016:
+		case 1017:
+		case 1018:
+		case 1019:
+		case 1020: {
+			showCursor(false);
+			_cursorCell = _buttonValue - 1001;
+			showCursor(true);
+			w.update();
+
+			bool result = expandStat(_cursorCell, *c);
+			_vm->_mode = MODE_InCombat;
+			if (result)
+				redrawFlag = true;
+			break;
+		}
+
+		case Common::KEYCODE_e:
+			if (oldMode == MODE_InCombat) {
+				ErrorScroll::show(_vm, EXCHANGING_IN_COMBAT, WT_FREEZE_WAIT);
+			} else {
+				_vm->_mode = oldMode;
+				error("c = exchangeChar(&charIndex)");
+				_vm->_mode = MODE_CHARACTER_INFO;
+				redrawFlag = true;
+			}
+			break;
+
+		case Common::KEYCODE_i:
+			_vm->_mode = oldMode;
+			_vm->_treasure._v1 = _vm->_mode == MODE_InCombat;
+			error("TODO: c = ItemDialog::show");
+
+			if (!c) {
+				party._stepped = true;
+				goto exit;
+			}
+
+			_vm->_mode = MODE_CHARACTER_INFO;
+			break;
+
+		case Common::KEYCODE_ESCAPE:
+			goto exit;
+		}
+	} while (!_vm->shouldQuit());
+exit:	
+	w.close();
+	intf.unhighlightChar();
+	_vm->_mode = oldMode;
+	_vm->_treasure._v1 = false;
+}
+
+/**
+ * Load the draw structure list with frame numbers and positions
+ */
+void CharacterInfo::loadDrawStructs() {
+	_drawList[0] = DrawStruct(0, 2, 16);
+	_drawList[1] = DrawStruct(2, 2, 39);
+	_drawList[2] = DrawStruct(4, 2, 62);
+	_drawList[3] = DrawStruct(6, 2, 85);
+	_drawList[4] = DrawStruct(8, 2, 108);
+	_drawList[5] = DrawStruct(10, 53, 16);
+	_drawList[6] = DrawStruct(12, 53, 39);
+	_drawList[7] = DrawStruct(14, 53, 62);
+	_drawList[8] = DrawStruct(16, 53, 85);
+	_drawList[9] = DrawStruct(18, 53, 108);
+	_drawList[10] = DrawStruct(20, 104, 16);
+	_drawList[11] = DrawStruct(22, 104, 39);
+	_drawList[12] = DrawStruct(24, 104, 62);
+	_drawList[13] = DrawStruct(26, 104, 85);
+	_drawList[14] = DrawStruct(28, 104, 108);
+	_drawList[15] = DrawStruct(30, 169, 16);
+	_drawList[16] = DrawStruct(32, 169, 39);
+	_drawList[17] = DrawStruct(34, 169, 62);
+	_drawList[18] = DrawStruct(36, 169, 85);
+	_drawList[19] = DrawStruct(38, 169, 108);
+	_drawList[20] = DrawStruct(40, 277, 3);
+	_drawList[21] = DrawStruct(42, 277, 35);
+	_drawList[22] = DrawStruct(44, 277, 67);
+	_drawList[23] = DrawStruct(46, 277, 99);
+
+	_iconSprites.load("view.icn");
+	for (int idx = 0; idx < 24; ++idx)
+		_drawList[idx]._sprites = &_iconSprites;
+}
+
+/**
+ * Set up the button list for the dialog
+ */
+void CharacterInfo::addButtons() {
+	addButton(Common::Rect(10, 24, 34, 64), 1001, &_iconSprites);
+	addButton(Common::Rect(10, 47, 34, 67), 1002, &_iconSprites);
+	addButton(Common::Rect(10, 70, 34, 90), 1003, &_iconSprites);
+	addButton(Common::Rect(10, 93, 34, 113), 1004, &_iconSprites);
+	addButton(Common::Rect(10, 116, 34, 136), 1005, &_iconSprites);
+	addButton(Common::Rect(61, 24, 85, 44), 1006, &_iconSprites);
+	addButton(Common::Rect(61, 47, 85, 67), 1007, &_iconSprites);
+	addButton(Common::Rect(61, 70, 85, 90), 1008, &_iconSprites);
+	addButton(Common::Rect(61, 93, 85, 113), 1009, &_iconSprites);
+	addButton(Common::Rect(61, 116, 85, 136), 1010, &_iconSprites);
+	addButton(Common::Rect(112, 24, 136, 44), 1011, &_iconSprites);
+	addButton(Common::Rect(112, 47, 136, 67), 1012, &_iconSprites);
+	addButton(Common::Rect(112, 70, 136, 90), 1013, &_iconSprites);
+	addButton(Common::Rect(112, 93, 136, 113), 1014, &_iconSprites);
+	addButton(Common::Rect(112, 116, 136, 136), 1015, &_iconSprites);
+	addButton(Common::Rect(177, 24, 201, 44), 1016, &_iconSprites);
+	addButton(Common::Rect(177, 47, 201, 67), 1017, &_iconSprites);
+	addButton(Common::Rect(177, 70, 201, 90), 1018, &_iconSprites);
+	addButton(Common::Rect(177, 93, 201, 113), 1019, &_iconSprites);
+	addButton(Common::Rect(177, 116, 201, 136), 1020, &_iconSprites);
+	addButton(Common::Rect(285, 11, 309, 31), Common::KEYCODE_i, &_iconSprites);
+	addButton(Common::Rect(285, 43, 309, 63), Common::KEYCODE_q, &_iconSprites);
+	addButton(Common::Rect(285, 75, 309, 95), Common::KEYCODE_e, &_iconSprites);
+	addButton(Common::Rect(285, 107, 309, 127), Common::KEYCODE_ESCAPE, &_iconSprites);
+}
+
+/**
+ * Return a string containing the details of the character
+ */
+Common::String CharacterInfo::loadCharacterDetails(const Character &c) {
+	Condition condition = c.worstCondition();
+	Party &party = *_vm->_party;
+	int foodVal = party._food / party._partyCount / 3;
+
+	int totalResist =
+		c._fireResistence._permanent + c.itemScan(11) + c._fireResistence._temporary +
+		c._coldResistence._permanent + c.itemScan(13) + c._coldResistence._temporary +
+		c._electricityResistence._permanent + c.itemScan(12) + c._electricityResistence._temporary +
+		c._poisonResistence._permanent + c.itemScan(14) + c._poisonResistence._temporary +
+		c._energyResistence._permanent + c.itemScan(15) + c._energyResistence._temporary +
+		c._magicResistence._permanent + c.itemScan(16) + c._magicResistence._temporary;
+
+	return Common::String::format(CHARACTER_DETAILS,
+		PARTY_GOLD, c._name.c_str(), SEX_NAMES[c._sex],
+		RACE_NAMES[c._race], CLASS_NAMES[c._class],
+		c.statColor(c.getStat(MIGHT), c.getStat(MIGHT, true)), c.getStat(MIGHT),
+		c.statColor(c.getStat(ACCURACY), c.getStat(ACCURACY, true)), c.getStat(ACCURACY),
+		c.statColor(c._currentHp, c.getMaxHP()),
+		c.getCurrentExperience(),
+		c.statColor(c.getStat(INTELLECT), c.getStat(INTELLECT, true)), c.getStat(INTELLECT),
+		c.statColor(c.getStat(LUCK), c.getStat(LUCK, true)), c.getStat(LUCK),
+		c.statColor(c._currentSp, c.getMaxSP()), c._currentSp,
+		party._gold,
+		c.statColor(c.getStat(PERSONALITY), c.getStat(PERSONALITY, true)), c.getStat(PERSONALITY),
+		c.statColor(c.getAge(), c.getAge(true)), c.getAge(),
+		totalResist,
+		party._gems,
+		c.statColor(c.getStat(ENDURANCE), c.getStat(ENDURANCE, true)), c.getStat(ENDURANCE),
+		c.statColor(c.getCurrentLevel(), c._level._permanent), c.getCurrentLevel(),
+		c.getNumSkills(),
+		foodVal, (foodVal == 1) ? ' ' : 's',
+		c.statColor(c.getStat(SPEED), c.getStat(SPEED, true)), c.getStat(SPEED),
+		c.statColor(c.getArmorClass(), c.getArmorClass(true)), c.getArmorClass(),
+		c.getNumAwards(),
+		CONDITION_COLORS[condition], CONDITION_NAMES[condition],
+		condition == NO_CONDITION && party._blessed ? PLUS_14 : "",
+		condition == NO_CONDITION && party._powerShield ? PLUS_14 : "",
+		condition == NO_CONDITION && party._holyBonus ? PLUS_14 : "",
+		condition == NO_CONDITION && party._heroism ? PLUS_14 : ""
+	);
+}
+
+/**
+ * Cursor display handling
+ */
+void CharacterInfo::showCursor(bool flag) {
+	Screen &screen = *_vm->_screen;
+	const int CURSOR_X[5] = { 9, 60, 111, 176, 0 };
+	const int CURSOR_Y[5] = { 23, 46, 69, 92, 115 };
+
+	if (_cursorCell < 20) {
+		_iconSprites.draw(screen, flag ? 49 : 48,
+			Common::Point(CURSOR_X[_cursorCell / 5], CURSOR_Y[_cursorCell % 5]));
+	}
+}
+
+bool CharacterInfo::expandStat(int attrib, const Character &c) {
+	const int STAT_POS[2][20] = {
+		{
+			61, 61, 61, 61, 61, 112, 112, 112, 112, 112,
+			177, 177, 177, 177, 177, 34, 34, 34, 34, 34
+		}, {
+			24, 47, 70, 93, 116, 24, 47, 70, 93, 116,
+			24, 47, 70, 93, 116, 24, 47, 70, 93, 116
+		}
+	};
+	assert(attrib < 20);
+	Common::Rect bounds(STAT_POS[0][attrib], STAT_POS[1][attrib],
+		STAT_POS[0][attrib] + 143, STAT_POS[1][attrib] + 52);
+	Party &party = *_vm->_party;
+	int stat1, stat2;
+	uint idx;
+	Common::String msg;
+
+	switch (attrib) {
+	case 0:
+	case 1:
+	case 2:
+	case 3:
+	case 4:
+	case 5:
+	case 6:
+		// Basic attributes
+		stat1 = c.getStat((Attribute)attrib, false);
+		stat2 = c.getStat((Attribute)attrib, true);
+		idx = 0;
+		while (STAT_VALUES[idx] <= stat1)
+			++idx;
+
+		msg = Common::String::format(CURRENT_MAXIMUM_RATING_TEXT, STAT_NAMES[attrib],
+			stat1, stat2, RATING_TEXT[idx]);
+		break;
+
+	case 7:
+		// Age
+		stat1 = c.getAge(false);
+		stat2 = c.getAge(true);
+		msg = Common::String::format(AGE_TEXT, STAT_NAMES[attrib],
+			stat2, c._dbDay, c._ybDay);
+		break;
+
+	case 8: {
+		// Level
+		const int CLASS_ATTACK_GAINS[10] = { 5, 6, 6, 7, 8, 6, 5, 4, 7, 6 };
+		idx = c.getCurrentLevel() / CLASS_ATTACK_GAINS[c._class] + 1;
+
+		msg = Common::String::format(LEVEL_TEXT, STAT_NAMES[attrib], 
+			c.getCurrentLevel(), c._level._permanent,
+			idx, idx > 1 ? "s" : "",
+			c._level._permanent);
+		break;
+	}
+
+	case 9:
+		// Armor Class
+		stat1 = c.getArmorClass(false);
+		stat2 = c.getArmorClass(true);
+		msg = Common::String::format(CURRENT_MAXIMUM_TEXT, STAT_NAMES[attrib], 
+			stat1, stat2);
+		bounds.setHeight(42);
+		break;
+
+	case 10:
+		// Hit Points
+		stat1 = c._currentHp;
+		stat2 = c.getMaxHP();
+		msg = Common::String::format(CURRENT_MAXIMUM_TEXT, STAT_NAMES[attrib], 
+			stat1, stat2);
+		bounds.setHeight(42);
+		break;
+		
+	case 11:
+		// Spell Points
+		stat1 = c._currentSp;
+		stat2 = c.getMaxSP();
+		msg = Common::String::format(CURRENT_MAXIMUM_TEXT, STAT_NAMES[attrib], 
+			stat1, stat2);
+		bounds.setHeight(42);
+		break;
+
+	case 12:
+		// Resistences
+		msg = Common::String::format(RESISTENCES_TEXT, STAT_NAMES[attrib],
+			c._fireResistence._permanent + c.itemScan(11) + c._fireResistence._temporary,
+			c._coldResistence._permanent + c.itemScan(13) + c._coldResistence._temporary,
+			c._electricityResistence._permanent + c.itemScan(12) + c._electricityResistence._temporary,
+			c._poisonResistence._permanent + c.itemScan(14) + c._poisonResistence._temporary,
+			c._energyResistence._permanent + c.itemScan(15) + c._energyResistence._temporary,
+			c._magicResistence._permanent + c.itemScan(16) + c._magicResistence._temporary);
+		break;
+
+	case 13: {
+		// Skills
+		Common::String lines[20];
+		int numLines = c.getNumSkills();
+		if (numLines > 0) {
+			for (int skill = THIEVERY; skill <= DANGER_SENSE; ++skill) {
+				if (c._skills[skill]) {
+					if (skill == THIEVERY) {
+						lines[0] = Common::String::format("\n\t020%s%u",
+							SKILL_NAMES[THIEVERY], c.getThievery());
+					} else {
+						lines[skill] = Common::String::format("\n\t020%s", SKILL_NAMES[skill]);
+					}
+				}
+			}
+		} else {
+			lines[0] = NONE;
+			numLines = 1;
+		}
+
+		msg = Common::String::format("\x2\x3""c%s\x3l%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
+			STAT_NAMES[attrib], lines[0].c_str(), lines[1].c_str(),
+			lines[2].c_str(), lines[3].c_str(), lines[4].c_str(), lines[5].c_str(),
+			lines[17].c_str(), lines[6].c_str(), lines[7].c_str(), lines[8].c_str(),
+			lines[9].c_str(), lines[10].c_str(), lines[11].c_str(), lines[12].c_str(),
+			lines[13].c_str(), lines[16].c_str(), lines[14].c_str(), lines[15].c_str());
+
+		bounds.top -= (numLines / 2) * 8;
+		bounds.setHeight(numLines * 9 + 26);
+		if (bounds.bottom >= SCREEN_HEIGHT)
+			bounds.moveTo(bounds.left, SCREEN_HEIGHT - bounds.height() - 1);
+		break;
+	}
+
+	case 14:
+		// Awards
+		error("AwardsDialog::show");
+		return false;
+
+	case 15:
+		// Experience
+		stat1 = c.getCurrentExperience();
+		stat2 = c.nextExperienceLevel();
+		msg = Common::String::format(EXPERIENCE_TEXT,
+			STAT_NAMES[attrib], stat1,
+			stat2 == 0 ? ELIGIBLE : Common::String::format("%d", stat2)
+		);
+		bounds.setHeight(43);
+		break;
+
+	case 16:
+		// Gold
+		msg = Common::String::format(IN_PARTY_IN_BANK, STAT_NAMES[attrib],
+			party._gold, party._bankGold);
+		break;
+
+	case 17:
+		// Gems
+		msg = Common::String::format(IN_PARTY_IN_BANK, STAT_NAMES[attrib],
+			party._gems, party._bankGems);
+		bounds.setHeight(43);
+		break;
+
+	case 18: {
+		// Food
+		int food = (party._food / party._partyCount) / 3;
+		msg = Common::String::format(FOOD_TEXT, STAT_NAMES[attrib],
+			party._food, food, food != 1 ? "s" : "");
+		break;
+	}
+
+	case 19: {
+		// Conditions
+		Common::String lines[20];
+		int total = 0;
+		for (int condition = CURSED; condition <= ERADICATED; ++condition) {
+			if (c._conditions[condition]) {
+				if (condition >= UNCONSCIOUS) {
+					lines[condition] = Common::String::format("\n\t020%s",
+						CONDITION_NAMES[condition]);
+				} else {
+					lines[condition] = Common::String::format("\n\t020%s\t095-%d",
+						CONDITION_NAMES[condition], c._conditions[condition]);
+				}
+
+				++total;
+			}
+		}
+
+		Condition condition = c.worstCondition();
+		if (condition == NO_CONDITION) {
+			lines[0] = Common::String::format("\n\t020%s", GOOD);
+		}
+
+		if (party._blessed)
+			lines[16] = Common::String::format(BLESSED, party._blessed);
+		if (party._powerShield)
+			lines[17] = Common::String::format(POWER_SHIELD, party._powerShield);
+		if (party._holyBonus)
+			lines[18] = Common::String::format(HOLY_BONUS, party._holyBonus);
+		if (party._heroism)
+			lines[19] = Common::String::format(HEROISM, party._heroism);
+
+		msg = Common::String::format("\x2\x3""c%s\x3l%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\x1",
+			STAT_NAMES[attrib], lines[0].c_str(), lines[1].c_str(),
+			lines[2].c_str(), lines[3].c_str(), lines[4].c_str(),
+			lines[5].c_str(), lines[6].c_str(), lines[7].c_str(),
+			lines[8].c_str(), lines[9].c_str(), lines[10].c_str(),
+			lines[11].c_str(), lines[12].c_str(), lines[13].c_str(),
+			lines[14].c_str(), lines[15].c_str(), lines[16].c_str(),
+			lines[17].c_str(), lines[18].c_str(), lines[19].c_str()
+		);
+
+		bounds.top = ((total - 1) / 2) * 8;
+		bounds.setHeight(total * 9 + 26);
+		if (bounds.bottom >= SCREEN_HEIGHT)
+			bounds.moveTo(bounds.left, SCREEN_HEIGHT - bounds.height() - 1);
+		break;
+	}
+
+	default:
+		break;
+	}
+
+	// Write the data for the stat display
+	Window &w = _vm->_screen->_windows[28];
+	w.setBounds(bounds);
+	w.open();
+	w.writeString(msg);
+	w.update();
+
+	// Wait for a user key/click
+	EventsManager &events = *_vm->_events;
+	while (!_vm->shouldQuit() && !events.isKeyMousePressed())
+		events.pollEventsAndWait();
+	events.clearEvents();
+
+	w.close();
+	return false;
+}
+
+
+} // End of namespace Xeen
diff --git a/engines/xeen/dialogs_char_info.h b/engines/xeen/dialogs_char_info.h
new file mode 100644
index 0000000..5a20ff2
--- /dev/null
+++ b/engines/xeen/dialogs_char_info.h
@@ -0,0 +1,58 @@
+/* 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_CHAR_INFO_H
+#define XEEN_DIALOGS_CHAR_INFO_H
+
+#include "xeen/dialogs.h"
+#include "xeen/party.h"
+#include "xeen/screen.h"
+
+namespace Xeen {
+
+class CharacterInfo : public ButtonContainer {
+private:
+	XeenEngine *_vm;
+	SpriteResource _iconSprites;
+	DrawStruct _drawList[24];
+	int _cursorCell;
+
+	CharacterInfo(XeenEngine *vm) : ButtonContainer(), _vm(vm), _cursorCell(0) {}
+
+	void execute(int charIndex);
+
+	void loadDrawStructs();
+
+	void addButtons();
+
+	Common::String loadCharacterDetails(const Character &c);
+
+	void showCursor(bool flag);
+
+	bool expandStat(int attrib, const Character &c);
+public:
+	static void show(XeenEngine *vm, int charIndex);
+};
+
+} // End of namespace Xeen
+
+#endif /* XEEN_DIALOGS_CHAR_INFO_H */
diff --git a/engines/xeen/dialogs_spells.cpp b/engines/xeen/dialogs_spells.cpp
index 7ae5e7a..714e881 100644
--- a/engines/xeen/dialogs_spells.cpp
+++ b/engines/xeen/dialogs_spells.cpp
@@ -50,7 +50,7 @@ Character *SpellsScroll::execute(Character *c, int v2) {
 	int v2Copy = v2;
 	v2 &= 0x7f;
 	int selection = -1;
-	int topIndex = 0;
+	uint topIndex = 0;
 	int newSelection;
 	screen._windows[25].open();
 
@@ -109,7 +109,7 @@ Character *SpellsScroll::execute(Character *c, int v2) {
 		switch (_buttonValue) {
 		case Common::KEYCODE_F1:
 		case Common::KEYCODE_F6:
-			if (_vm->_mode != MODE_2) {
+			if (_vm->_mode != MODE_InCombat) {
 				_buttonValue -= Common::KEYCODE_F1;
 				if (_buttonValue < party._partyCount) {
 					c = &party._activeParty[_buttonValue];
@@ -233,12 +233,12 @@ Character *SpellsScroll::execute(Character *c, int v2) {
 
 		case Common::KEYCODE_PAGEUP:
 		case Common::KEYCODE_KP9:
-			topIndex = MAX(topIndex - 10, 0);
+			topIndex = MAX((int)topIndex - 10, 0);
 			break;
 
 		case Common::KEYCODE_PAGEDOWN:
 		case Common::KEYCODE_KP3:
-			topIndex = MIN(topIndex + 10, (((int)_spells.size() - 1) / 10) * 10);
+			topIndex = MIN(topIndex + 10, ((_spells.size() - 1) / 10) * 10);
 			break;
 
 		case Common::KEYCODE_UP:
@@ -249,7 +249,7 @@ Character *SpellsScroll::execute(Character *c, int v2) {
 
 		case Common::KEYCODE_DOWN:
 		case Common::KEYCODE_KP2:
-			if (topIndex < ((int)_spells.size() - 10))
+			if (topIndex < (_spells.size() - 10))
 				++topIndex;
 			break;
 		}
@@ -321,7 +321,7 @@ const char *SpellsScroll::setSpellText(Character *c, int v2) {
 
 		if (category != -1) {
 			if (party._mazeId == 49 || party._mazeId == 37) {
-				for (int spellId = 0; spellId < 76; ++spellId) {
+				for (uint spellId = 0; spellId < 76; ++spellId) {
 					int idx = 0;
 					while (idx < MAX_SPELLS_PER_CLASS && SPELLS_ALLOWED[category][idx] == spellId)
 						++idx;
@@ -338,8 +338,8 @@ const char *SpellsScroll::setSpellText(Character *c, int v2) {
 				}
 			} else if (isDarkCc) {
 				int groupIndex = (party._mazeId - 29) / 2;
-				for (int spellId = DARK_SPELL_RANGES[category][0];
-						spellId < DARK_SPELL_RANGES[category][1]; ++spellId) {
+				for (int spellId = DARK_SPELL_RANGES[groupIndex][0];
+						spellId < DARK_SPELL_RANGES[groupIndex][1]; ++spellId) {
 					int idx = 0;
 					while (idx < 40 && SPELLS_ALLOWED[category][idx] ==
 						DARK_SPELL_OFFSETS[category][spellId]);
@@ -357,7 +357,7 @@ const char *SpellsScroll::setSpellText(Character *c, int v2) {
 				for (int spellId = 0; spellId < 20; ++spellId) {
 					int idx = 0;
 					while (CLOUDS_SPELL_OFFSETS[party._mazeId - 29][spellId] !=
-						SPELLS_ALLOWED[category][idx] && idx < 40) ;
+						(int)SPELLS_ALLOWED[category][idx] && idx < 40) ;
 
 					if (idx < 40) {
 						if (!c->_spells[idx] || (v2 & 0x80)) {
diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp
index 0ea5a8d..a33c726 100644
--- a/engines/xeen/interface.cpp
+++ b/engines/xeen/interface.cpp
@@ -21,6 +21,7 @@
  */
 
 #include "xeen/interface.h"
+#include "xeen/dialogs_char_info.h"
 #include "xeen/dialogs_error.h"
 #include "xeen/dialogs_automap.h"
 #include "xeen/dialogs_info.h"
@@ -331,7 +332,7 @@ void Interface::setupFaces(int charIndex, Common::Array<int> xeenSideChars, bool
 
 void Interface::charIconsPrint(bool updateFlag) {
 	Screen &screen = *_vm->_screen;
-	bool stateFlag = _vm->_mode == MODE_2;
+	bool stateFlag = _vm->_mode == MODE_InCombat;
 	_restoreSprites.draw(screen, 0, Common::Point(8, 149));
 
 	// Handle drawing the party faces
@@ -669,6 +670,20 @@ void Interface::perform() {
 		}
 		break;
 
+	case Common::KEYCODE_F1:
+	case Common::KEYCODE_F2:
+	case Common::KEYCODE_F3:
+	case Common::KEYCODE_F4:
+	case Common::KEYCODE_F5:
+	case Common::KEYCODE_F6:
+		_buttonValue -= Common::KEYCODE_F1;
+		if (_buttonValue < party._partyCount) {
+			CharacterInfo::show(_vm, _buttonValue);
+			if (party._stepped)
+				moveMonsters();
+		}
+		break;
+
 	case Common::KEYCODE_EQUALS:
 	case Common::KEYCODE_KP_EQUALS:
 		// Toggle minimap
diff --git a/engines/xeen/interface_map.cpp b/engines/xeen/interface_map.cpp
index 84f8fa6..c8683a7 100644
--- a/engines/xeen/interface_map.cpp
+++ b/engines/xeen/interface_map.cpp
@@ -426,7 +426,7 @@ void InterfaceMap::draw3d(bool updateFlag) {
 	_flipUIFrame = (_flipUIFrame + 1) % 4;
 	if (_flipUIFrame == 0)
 		_flipWater = !_flipWater;
-	if (_tillMove && (_vm->_mode == MODE_1 || _vm->_mode == MODE_2) &&
+	if (_tillMove && (_vm->_mode == MODE_1 || _vm->_mode == MODE_InCombat) &&
 		!_flag1 && _vm->_moveMonsters) {
 		if (--_tillMove == 0)
 			moveMonsters();
diff --git a/engines/xeen/items.cpp b/engines/xeen/items.cpp
index f7dfecc..c55a227 100644
--- a/engines/xeen/items.cpp
+++ b/engines/xeen/items.cpp
@@ -56,6 +56,7 @@ int XeenItem::getAttributeCategory() const {
 
 Treasure::Treasure() {
 	_hasItems = false;
+	_v1 = false;
 }
 
 } // End of namespace Xeen
diff --git a/engines/xeen/items.h b/engines/xeen/items.h
index 958a0b8..8e8f172 100644
--- a/engines/xeen/items.h
+++ b/engines/xeen/items.h
@@ -55,6 +55,7 @@ public:
 	XeenItem _armor[TOTAL_ITEMS];
 	XeenItem _weapons[TOTAL_ITEMS];
 	bool _hasItems;
+	bool _v1;
 public:
 	Treasure();
 };
diff --git a/engines/xeen/module.mk b/engines/xeen/module.mk
index 4bb8bd9..6a9ff30 100644
--- a/engines/xeen/module.mk
+++ b/engines/xeen/module.mk
@@ -10,6 +10,7 @@ MODULE_OBJS := \
 	dialogs.o \
 	automap.o \
 	dialogs_automap.o \
+	dialogs_char_info.o \
 	dialogs_confirm.o \
 	dialogs_error.o \
 	dialogs_options.o \
diff --git a/engines/xeen/party.cpp b/engines/xeen/party.cpp
index 66078b6..3cfc56e 100644
--- a/engines/xeen/party.cpp
+++ b/engines/xeen/party.cpp
@@ -238,7 +238,7 @@ int Character::getMaxSP() const {
 /**
  * Get the effective value of a given stat for the character
  */
-int Character::getStat(Attribute attrib, bool baseOnly) const {
+uint Character::getStat(Attribute attrib, bool baseOnly) const {
 	AttributePair attr;
 	int mode = 0;
 
@@ -289,7 +289,24 @@ int Character::getStat(Attribute attrib, bool baseOnly) const {
 		attr._permanent += attr._temporary;
 	}
 
-	return MAX(attr._permanent, 0);
+	return MAX(attr._permanent, (uint)0);
+}
+
+/**
+ * Return the color number to use for a given stat value in the character
+ * info or quick reference dialogs
+ */
+int Character::statColor(int amount, int threshold) {
+	if (amount < 1)
+		return 6;
+	else if (amount > threshold)
+		return 2;
+	else if (amount == threshold)
+		return 15;
+	else if (amount <= (threshold / 4))
+		return 9;
+	else
+		return 32;
 }
 
 int Character::statBonus(int statValue) const {
@@ -422,8 +439,8 @@ int Character::getThievery() const {
 	return MAX(result, 0);
 }
 
-int Character::getCurrentLevel() const {
-	return MAX(_level._permanent + _level._temporary, 0);
+uint Character::getCurrentLevel() const {
+	return MAX(_level._permanent + _level._temporary, (uint)0);
 }
 
 int Character::itemScan(int itemId) const {
@@ -817,6 +834,28 @@ uint Character::getCurrentExperience() const {
 		_experience;
 }
 
+
+int Character::getNumSkills() const {
+	int total = 0;
+	for (int idx = THIEVERY; idx <= DANGER_SENSE; ++idx) {
+		if (_skills[idx])
+			++total;
+	}
+
+	return total;
+}
+
+int Character::getNumAwards() const {
+	int total = 0;
+	for (int idx = 0; idx < 88; ++idx) {
+		if (hasAward(idx))
+			++total;
+	}
+
+	return total;
+}
+
+
 /*------------------------------------------------------------------------*/
 
 void Roster::synchronize(Common::Serializer &s) {
diff --git a/engines/xeen/party.h b/engines/xeen/party.h
index e00b424..b793b5c 100644
--- a/engines/xeen/party.h
+++ b/engines/xeen/party.h
@@ -80,8 +80,8 @@ class XeenEngine;
 
 class AttributePair {
 public:	
-	int _permanent;
-	int _temporary;
+	uint _permanent;
+	uint _temporary;
 public:
 	AttributePair();
 	void synchronize(Common::Serializer &s);
@@ -141,13 +141,15 @@ public:
 
 	Condition worstCondition() const;
 
-	int getAge(bool ignoreTemp) const;
+	int getAge(bool ignoreTemp = false) const;
 
 	int getMaxHP() const;
 
 	int getMaxSP() const;
 
-	int getStat(Attribute attrib, bool baseOnly = false) const;
+	uint getStat(Attribute attrib, bool baseOnly = false) const;
+
+	static int statColor(int amount, int threshold);
 
 	int statBonus(int statValue) const;
 
@@ -159,11 +161,11 @@ public:
 
 	bool hasAward(int awardId) const;
 
-	int getArmorClass(bool baseOnly) const;
+	int getArmorClass(bool baseOnly = false) const;
 
 	int getThievery() const;
 
-	int getCurrentLevel() const;
+	uint getCurrentLevel() const;
 
 	int itemScan(int itemId) const;
 
@@ -176,6 +178,10 @@ public:
 	uint currentExperienceLevel() const;
 
 	uint getCurrentExperience() const;
+
+	int getNumSkills() const;
+
+	int getNumAwards() const;
 };
 
 class Roster: public Common::Array<Character> {
@@ -247,6 +253,7 @@ public:
 public:
 	// Other party related runtime data
 	Common::Array<Character> _activeParty;
+	Common::Array<Character *> _combatParty;
 	int _combatPartyCount;
 	bool _partyDead;
 	bool _newDay;
diff --git a/engines/xeen/resources.cpp b/engines/xeen/resources.cpp
index dafe321..4e958a1 100644
--- a/engines/xeen/resources.cpp
+++ b/engines/xeen/resources.cpp
@@ -287,6 +287,13 @@ const char *const ALIGNMENT_NAMES[3] = { "Good", "Neutral", "Evil" };
 
 const char *const SEX_NAMES[2] = { "Male", "Female" };
 
+const char *const SKILL_NAMES[18] = {
+	"Thievery", "Arms Master", "Astrologer", "Body Builder", "Cartographer",
+	"Crusader", "Direction Sense", "Linguist", "Merchant", "Mountaineer", 
+	"Navigator", "Path Finder", "Prayer Master", "Prestidigitator",
+	"Swimmer", "Tracker", "Spot Secret Door", "Danger Sense"
+};
+
 const char *const CLASS_NAMES[11] = {
 	"Knight", "Paladin", "Archer", "Cleric", "Sorcerer", "Robber", 
 	"Ninja", "Barbarian", "Druid", "Ranger", nullptr
@@ -296,12 +303,26 @@ const uint CLASS_EXP_LEVELS[10] = {
 	1500, 2000, 2000, 1500, 2000, 1000, 1500, 1500, 1500, 2000
 };
 
-const char *const CONDITION_NAMES[18] = {
+const char *const CONDITION_NAMES[17] = {
 	nullptr, "Cursed", "Heart Broken", "Weak", "Poisoned", "Diseased", 
 	"Insane", "In Love", "Drunk", "Asleep", "Depressed", "Confused", 
-	"Paralyzed", "Unconscious", "Dead", "Stone", "Eradicated", "Good"
+	"Paralyzed", "Unconscious", "Dead", "Stone", "Eradicated" 
 };
 
+const int CONDITION_COLORS[17] = {
+	9, 9, 9, 9, 9, 9, 9, 9, 32, 32, 32, 32, 6, 6, 6, 6, 15
+};
+
+const char *const GOOD = "Good";
+
+const char *const BLESSED = "\n\t020Blessed\t095%+d";
+
+const char *const POWER_SHIELD = "\n\t020Power Shield\t095%+d";
+
+const char *const HOLY_BONUS = "\n\t020Holy Bonus\t095%+d";
+
+const char *const HEROISM = "\n\t020Heroism\t095%+d";
+
 const char *const IN_PARTY = "\014""15In Party\014""d";
 
 const char *const PARTY_DETAILS = "\015\003l\002\014""00"
@@ -494,7 +515,7 @@ const int MONSTER_EFFECT_FLAGS[15][8] = {
 	{ 0x108, 0x108, 0x108, 0x108, 0x108, 0x108, 0x108, 0x108 }
 };
 
-const int SPELLS_ALLOWED[3][40] = {
+const uint SPELLS_ALLOWED[3][40] = {
 	{
 		0, 1, 2, 3, 5, 6, 7, 8, 9, 10,
 		12, 14, 16, 23, 26, 27, 28, 30, 31, 32,
@@ -760,7 +781,7 @@ const int CLOUDS_SPELL_OFFSETS[5][20] = {
 	}
 };
 
-const int DARK_SPELL_OFFSETS[3][39] = {
+const uint DARK_SPELL_OFFSETS[3][39] = {
 	{
 		42, 1, 26, 59, 27, 10, 50, 68, 55, 62, 67, 73, 2,
 		5, 3, 31, 30, 52, 49, 28, 74, 0, 9, 7, 14, 8,
@@ -866,4 +887,86 @@ const char *const WEEK_DAY_STRINGS[10] = {
 	"Ten", "One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine"
 };
 
+const char *const CHARACTER_DETAILS =
+	"\x3l\xB""041\x9""196%s\x9""000\xB""002%s : %s %s %s"
+	"\x3r\x9""053\xB""028\xC%02u%u\xC""d\x9""103\xC""%02u%u\xC""d"
+	"\x3l\x9""131\xC""%02u%d\xC""d\x9""196\xC""15%lu\xC""d\x3r"
+	"\x9""053\xB""051\xC""%02u%u\xC""d\x9""103\xC""%02u%u\xC""d"
+	"\x3l\x9""131\xC""%02u%u\xC""d\x9""196\xC""15%lu\xC""d"
+	"\x3r\x9""053\xB""074\xC""%02u%u\xC""d\x9""103\xC""%02u%u\xC""d"
+	"\x3l\x9""131\xC""15%u\xC""d\x9""196\xC""15%lu\xC""d"
+	"\x3r\x9""053\xB""097\xC""%02u%u\xC""d\x9""103\xC""%02u%u\xC""d"
+	"\x3l\x9""131\xC""15%u\xC""d\x9""196\xC""15%u day%c\xC""d"
+	"\x3r\x9""053\xB""120\xC""%02u%u\xC""d\x9""103\xC""%02u%u\xC""d"
+	"\x3l\x9""131\xC""15%u\xC""d\x9""196\xC""%02u%s\xC""d"
+	"\x9""230%s%s%s%s\xC""d";
+
+const char *const PARTY_GOLD = "Party Gold";
+
+const char *const PLUS_14 = "14+";
+
+const char *const CHARACTER_TEMPLATE =
+	"\x1\xC""00\xD\x3l\x9""029\xB""018Mgt\x9""080Acy\x9""131H.P.\x9""196Experience"
+	"\x9""029\xB""041Int\x9""080Lck\x9""131S.P.\x9""029\xB""064Per\x9""080Age"
+	"\x9""131Resis\x9""196Party Gems\x9""029\xB""087End\x9""080Lvl\x9""131Skills"
+	"\x9""196Party Food\x9""029\xB""110Spd\x9""080AC\x9""131Awrds\x9""196Condition\x3""c"
+	"\x9""290\xB""025\xC""37I\xC""dtem\x9""290\xB""057\xC""37Q"
+	"\xC""duick\x9""290\xB""089\xC""37E\xC""dxch\x9""290\xB""121Exit\x3l%s";
+
+const char *const EXCHANGING_IN_COMBAT = "\x3""c\xB""007\x9""000Exchanging in combat is not allowed!";
+
+const char *const CURRENT_MAXIMUM_RATING_TEXT = "\x2\x3""c%s\n"
+	"Current / Maximum\n"
+	"\x3r\x9""054%lu\x3l\x9""058/ %lu\n"
+	"\x3""cRating: %s";
+
+const char *const CURRENT_MAXIMUM_TEXT = "\x2\x3""c%s\n"
+	"Current / Maximum\n"
+	"\x3r\x9""054%u\x3l\x9""058/ %u";
+
+const char *const RATING_TEXT[24] = {
+	"Nonexistant", "Very Poor", "Poor", "Very Low", "Low", "Averarage", "Good",
+	"Very Good", "High", "Very High", "Great", "Super", "Amazing", "Incredible",
+	"Gigantic", "Fantastic", "Astoundig", "Astonishing", "Monumental", "Tremendous",
+	"Collosal", "Awesome", "AweInspiring", "aUltimate"
+};
+
+const char *const AGE_TEXT = "\x2\x3""c%s\n"
+	"Current / Natural\n"
+	"\x3r\x9""057%u\x3l\x9""061/ %u\n"
+	"\x3""cBorn: %u / %u\x1";
+
+const char *const LEVEL_TEXT =
+	"\x2\x3""c%s\n"
+	"Current / Maximum\n"
+	"\x3r\x9""054%u\x3l\x9""058/ %u\n"
+	"\x3""c%u Attack%s/Round\x1";
+
+const char *const RESISTENCES_TEXT = 
+	"\x2\x3""c%s\x3l\n"
+	"\x9""020Fire\x9""100%u\n"
+	"\x9""020Cold\x9""100%u\n"
+	"\x9""020Electricity\x9""100%u\n"
+	"\x9""020Poison\x9""100%u\n"
+	"\x9""020Energy\x9""100%u\n"
+	"\x9""020Magic\x9""100%u";
+
+const char *const NONE = "\n\x9""020";
+
+const char *const EXPERIENCE_TEXT = "\x2\x3""c%s\x3l\n"
+	"\x9""010Current:\x9""070%lu\n"
+	"\x9""010Next Level:\x9""070%s\x1";
+
+const char *const ELIGIBLE = "\xC""12Eligible\xC""d";
+
+const char *const IN_PARTY_IN_BANK =
+	"\x2\x3""cParty %s\n"
+	"%lu on hand\n"
+	"%lu in bank\x1\x3l";
+
+const char *const FOOD_TEXT =
+	"\x2\x3""cParty %s\n"
+	"%u on hand\n"
+   "Enough for %u day%s\x3l";
+
 } // End of namespace Xeen
diff --git a/engines/xeen/resources.h b/engines/xeen/resources.h
index 8beeb56..a696e54 100644
--- a/engines/xeen/resources.h
+++ b/engines/xeen/resources.h
@@ -74,8 +74,21 @@ extern const char *const ALIGNMENT_NAMES[3];
 
 extern const char *const SEX_NAMES[2];
 
-extern const char *const CONDITION_NAMES[18];
+extern const char *const SKILL_NAMES[18];
 
+extern const char *const CONDITION_NAMES[17];
+
+extern const int CONDITION_COLORS[17];
+
+extern const char *const GOOD;
+
+extern const char *const BLESSED;
+
+extern const char *const POWER_SHIELD;
+
+extern const char *const HOLY_BONUS;
+
+extern const char *const HEROISM;
 extern const char *const IN_PARTY;
 
 extern const char *const PARTY_DETAILS;
@@ -126,7 +139,7 @@ extern const int COMBAT_FLOAT_Y[8];
 
 extern const int MONSTER_EFFECT_FLAGS[15][8];
 
-extern const int SPELLS_ALLOWED[3][40];
+extern const uint SPELLS_ALLOWED[3][40];
 
 extern const int BASE_HP_BY_CLASS[10];
 
@@ -220,7 +233,7 @@ extern const int SPELL_COSTS[77];
 
 extern const int CLOUDS_SPELL_OFFSETS[5][20];
 
-extern const int DARK_SPELL_OFFSETS[3][39];
+extern const uint DARK_SPELL_OFFSETS[3][39];
 
 extern const int DARK_SPELL_RANGES[12][2];
 
@@ -276,6 +289,38 @@ extern const char *const SWORDS_GAME_TEXT;
 
 extern const char *const WEEK_DAY_STRINGS[10];
 
+extern const char *const CHARACTER_DETAILS;
+
+extern const char *const PARTY_GOLD;
+
+extern const char *const PLUS_14;
+
+extern const char *const CHARACTER_TEMPLATE;
+
+extern const char *const EXCHANGING_IN_COMBAT;
+
+extern const char *const CURRENT_MAXIMUM_RATING_TEXT;
+
+extern const char *const CURRENT_MAXIMUM_TEXT;
+
+extern const char *const RATING_TEXT[24];
+
+extern const char *const AGE_TEXT;
+
+extern const char *const LEVEL_TEXT;
+
+extern const char *const RESISTENCES_TEXT;
+
+extern const char *const NONE;
+
+extern const char *const EXPERIENCE_TEXT;
+
+extern const char *const ELIGIBLE;
+
+extern const char *const IN_PARTY_IN_BANK;
+
+extern const char *const FOOD_TEXT;
+
 } // End of namespace Xeen
 
 #endif	/* XEEN_RESOURCES_H */
diff --git a/engines/xeen/town.h b/engines/xeen/town.h
index 8237f81..807f6b5 100644
--- a/engines/xeen/town.h
+++ b/engines/xeen/town.h
@@ -47,7 +47,7 @@ private:
 	int _v5, _v6;
 	int _v10, _v11, _v12;
 	int _v13, _v14;
-	int _v20;
+	uint _v20;
 	int _v21;
 	uint _v22;
 	int _v23;
diff --git a/engines/xeen/xeen.h b/engines/xeen/xeen.h
index cb09c28..7f1a2cd 100644
--- a/engines/xeen/xeen.h
+++ b/engines/xeen/xeen.h
@@ -77,7 +77,7 @@ enum Mode {
 	MODE_FF = -1,
 	MODE_0 = 0,
 	MODE_1 = 1,
-	MODE_2 = 2,
+	MODE_InCombat = 2,
 	MODE_3 = 3,
 	MODE_4 = 4,
 	MODE_5 = 5,
@@ -85,6 +85,7 @@ enum Mode {
 	MODE_7 = 7,
 	MODE_8 = 8,
 	MODE_9 = 9,
+	MODE_CHARACTER_INFO = 10,
 	MODE_17 = 17
 };
 


Commit: 3ae4958f0ba6823b74cf86db6dbd905a8f2d4c47
    https://github.com/scummvm/scummvm/commit/3ae4958f0ba6823b74cf86db6dbd905a8f2d4c47
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-02-01T13:57:02-05:00

Commit Message:
XEEN: Implemented Exchange character dialog

Changed paths:
  A engines/xeen/dialogs_exchange.cpp
  A engines/xeen/dialogs_exchange.h
    engines/xeen/dialogs_char_info.cpp
    engines/xeen/interface.h
    engines/xeen/module.mk
    engines/xeen/resources.cpp
    engines/xeen/resources.h



diff --git a/engines/xeen/dialogs_char_info.cpp b/engines/xeen/dialogs_char_info.cpp
index 3ff4003..9fedb56 100644
--- a/engines/xeen/dialogs_char_info.cpp
+++ b/engines/xeen/dialogs_char_info.cpp
@@ -21,6 +21,7 @@
  */
 
 #include "xeen/dialogs_char_info.h"
+#include "xeen/dialogs_exchange.h"
 #include "xeen/resources.h"
 #include "xeen/xeen.h"
 
@@ -38,7 +39,7 @@ void CharacterInfo::execute(int charIndex) {
 	Interface &intf = *_vm->_interface;
 	Party &party = *_vm->_party;
 	
-	bool redrawFlag = false;
+	bool redrawFlag = true;
 	Mode oldMode = _vm->_mode;
 	_vm->_mode = MODE_CHARACTER_INFO;
 	loadDrawStructs();
@@ -60,8 +61,10 @@ void CharacterInfo::execute(int charIndex) {
 
 		// Wait for keypress, showing a blinking cursor
 		events.updateGameCounter();
-	bool cursorFlag = false;
-		while (!_vm->shouldQuit() && !events.isKeyMousePressed()) {
+		bool cursorFlag = false;
+		_buttonValue = 0;
+		while (!_vm->shouldQuit() && !_buttonValue) {
+			events.pollEventsAndWait();
 			if (events.timeElapsed() > 4) {
 				cursorFlag = !cursorFlag;
 				events.updateGameCounter();
@@ -69,8 +72,8 @@ void CharacterInfo::execute(int charIndex) {
 
 			showCursor(cursorFlag);
 			w.update();
+			checkEvents(_vm);
 		}
-		checkEvents(_vm);
 		events.clearEvents();
 
 		switch (_buttonValue) {
@@ -84,8 +87,7 @@ void CharacterInfo::execute(int charIndex) {
 			if (_buttonValue < (int)(oldMode == MODE_InCombat ? party._combatParty.size() : party._activeParty.size())) {
 				charIndex = _buttonValue;
 				c = (oldMode != MODE_InCombat) ? &party._activeParty[charIndex] : party._combatParty[charIndex];
-			}
-			else {
+			} else {
 				_iconSprites.load("view.icn");
 				_vm->_mode = MODE_CHARACTER_INFO;
 			}
@@ -173,7 +175,7 @@ void CharacterInfo::execute(int charIndex) {
 				ErrorScroll::show(_vm, EXCHANGING_IN_COMBAT, WT_FREEZE_WAIT);
 			} else {
 				_vm->_mode = oldMode;
-				error("c = exchangeChar(&charIndex)");
+				ExchangeDialog::show(_vm, c, charIndex);
 				_vm->_mode = MODE_CHARACTER_INFO;
 				redrawFlag = true;
 			}
diff --git a/engines/xeen/dialogs_exchange.cpp b/engines/xeen/dialogs_exchange.cpp
new file mode 100644
index 0000000..56a310a
--- /dev/null
+++ b/engines/xeen/dialogs_exchange.cpp
@@ -0,0 +1,82 @@
+/* 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 "xeen/dialogs_exchange.h"
+#include "xeen/resources.h"
+#include "xeen/xeen.h"
+
+namespace Xeen {
+
+void ExchangeDialog::show(XeenEngine *vm, Character *&c, int &charIndex) {
+	ExchangeDialog *dlg = new ExchangeDialog(vm);
+	dlg->execute(c, charIndex);
+	delete dlg;
+}
+
+void ExchangeDialog::execute(Character *&c, int &charIndex) {
+	Screen &screen = *_vm->_screen;
+	EventsManager &events = *_vm->_events;
+	Interface &intf = *_vm->_interface;
+	Party &party = *_vm->_party;
+	loadButtons();
+
+	Window &w = screen._windows[31];
+	w.open();
+	w.writeString(EXCHANGE_WITH_WHOM);
+	_iconSprites.draw(w, 0, Common::Point(225, 120));
+	w.update();
+
+	while (!_vm->shouldQuit()) {
+		events.pollEventsAndWait();
+		checkEvents(_vm);
+
+		if (_buttonValue >= Common::KEYCODE_F1 && _buttonValue <= Common::KEYCODE_F6) {
+			_buttonValue -= Common::KEYCODE_F1;
+			if (_buttonValue < party._partyCount) {
+				SWAP(party._activeParty[charIndex], party._activeParty[_buttonValue]);
+				SWAP(party._partyMembers[charIndex], party._partyMembers[_buttonValue]);
+				SWAP(intf._partyFaces[charIndex], intf._partyFaces[_buttonValue]);
+
+				charIndex = _buttonValue;
+				c = &party._activeParty[charIndex];
+				break;
+			}
+		} else if (_buttonValue == Common::KEYCODE_ESCAPE) {
+			break;
+		}
+	}
+
+	w.close();
+	intf.charIconsPrint(true);
+	intf.highlightChar(charIndex);
+}
+
+void ExchangeDialog::loadButtons() {
+	_iconSprites.load("esc.icn");
+	addButton(Common::Rect(225, 120, 249, 245), Common::KEYCODE_ESCAPE, &_iconSprites, true);
+	addButton(Common::Rect(16, 16, 48, 48), Common::KEYCODE_1, &_iconSprites, false);
+	addButton(Common::Rect(117, 16, 149, 48), Common::KEYCODE_2, &_iconSprites, false);
+	addButton(Common::Rect(16, 59, 48, 91), Common::KEYCODE_3, &_iconSprites, false);
+	addButton(Common::Rect(117, 59, 149, 91), Common::KEYCODE_4, &_iconSprites, false);
+}
+
+} // End of namespace Xeen
diff --git a/engines/xeen/dialogs_exchange.h b/engines/xeen/dialogs_exchange.h
new file mode 100644
index 0000000..e8c4a2d
--- /dev/null
+++ b/engines/xeen/dialogs_exchange.h
@@ -0,0 +1,47 @@
+/* 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_EXCHANGE_H
+#define XEEN_DIALOGS_EXCHANGE_H
+
+#include "xeen/dialogs.h"
+#include "xeen/party.h"
+
+namespace Xeen {
+
+class ExchangeDialog : public ButtonContainer {
+private:
+	XeenEngine *_vm;
+	SpriteResource _iconSprites;
+
+	ExchangeDialog(XeenEngine *vm) : ButtonContainer(), _vm(vm) {}
+
+	void execute(Character *&c, int &charIndex);
+
+	void loadButtons();
+public:
+	static void show(XeenEngine *vm, Character *&c, int &charIndex);
+};
+
+} // End of namespace Xeen
+
+#endif /* XEEN_DIALOGS_EXCHANGE_H */
diff --git a/engines/xeen/interface.h b/engines/xeen/interface.h
index 73cd509..103b8b6 100644
--- a/engines/xeen/interface.h
+++ b/engines/xeen/interface.h
@@ -45,7 +45,6 @@ private:
 	SpriteResource _uiSprites;
 	SpriteResource _iconSprites;
 	SpriteResource _charFaces[TOTAL_CHARACTERS];
-	SpriteResource *_partyFaces[MAX_ACTIVE_PARTY];
 	DrawStruct _faceDrawStructs[4];
 	DrawStruct _mainList[16];
 	int _combatCharIds[8];
@@ -78,6 +77,7 @@ private:
 public:
 	int _intrIndex1;
 	Common::String _interfaceText;
+	SpriteResource *_partyFaces[MAX_ACTIVE_PARTY];
 public:
 	Interface(XeenEngine *vm);
 
diff --git a/engines/xeen/module.mk b/engines/xeen/module.mk
index 6a9ff30..8d3a5e5 100644
--- a/engines/xeen/module.mk
+++ b/engines/xeen/module.mk
@@ -13,6 +13,7 @@ MODULE_OBJS := \
 	dialogs_char_info.o \
 	dialogs_confirm.o \
 	dialogs_error.o \
+	dialogs_exchange.o \
 	dialogs_options.o \
 	dialogs_info.o \
 	dialogs_input.o \
diff --git a/engines/xeen/resources.cpp b/engines/xeen/resources.cpp
index 4e958a1..467dbe2 100644
--- a/engines/xeen/resources.cpp
+++ b/engines/xeen/resources.cpp
@@ -969,4 +969,6 @@ const char *const FOOD_TEXT =
 	"%u on hand\n"
    "Enough for %u day%s\x3l";
 
+const char *const EXCHANGE_WITH_WHOM = "\t010\v005Exchange with whom?";
+
 } // End of namespace Xeen
diff --git a/engines/xeen/resources.h b/engines/xeen/resources.h
index a696e54..64387e7 100644
--- a/engines/xeen/resources.h
+++ b/engines/xeen/resources.h
@@ -321,6 +321,8 @@ extern const char *const IN_PARTY_IN_BANK;
 
 extern const char *const FOOD_TEXT;
 
+extern const char *const EXCHANGE_WITH_WHOM;
+
 } // End of namespace Xeen
 
 #endif	/* XEEN_RESOURCES_H */


Commit: d57c9f20213e66539fc7686a8b8abc26090aaa59
    https://github.com/scummvm/scummvm/commit/d57c9f20213e66539fc7686a8b8abc26090aaa59
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-02-01T15:24:12-05:00

Commit Message:
XEEN: Fixes to the Character Info dialog

Changed paths:
    engines/xeen/dialogs_char_info.cpp
    engines/xeen/party.cpp
    engines/xeen/resources.cpp
    engines/xeen/screen.cpp



diff --git a/engines/xeen/dialogs_char_info.cpp b/engines/xeen/dialogs_char_info.cpp
index 9fedb56..1c0d0bf 100644
--- a/engines/xeen/dialogs_char_info.cpp
+++ b/engines/xeen/dialogs_char_info.cpp
@@ -88,9 +88,9 @@ void CharacterInfo::execute(int charIndex) {
 				charIndex = _buttonValue;
 				c = (oldMode != MODE_InCombat) ? &party._activeParty[charIndex] : party._combatParty[charIndex];
 			} else {
-				_iconSprites.load("view.icn");
 				_vm->_mode = MODE_CHARACTER_INFO;
 			}
+			redrawFlag = true;
 			break;
 
 		case Common::KEYCODE_UP:
@@ -290,7 +290,7 @@ Common::String CharacterInfo::loadCharacterDetails(const Character &c) {
 		RACE_NAMES[c._race], CLASS_NAMES[c._class],
 		c.statColor(c.getStat(MIGHT), c.getStat(MIGHT, true)), c.getStat(MIGHT),
 		c.statColor(c.getStat(ACCURACY), c.getStat(ACCURACY, true)), c.getStat(ACCURACY),
-		c.statColor(c._currentHp, c.getMaxHP()),
+		c.statColor(c._currentHp, c.getMaxHP()), c._currentHp,
 		c.getCurrentExperience(),
 		c.statColor(c.getStat(INTELLECT), c.getStat(INTELLECT, true)), c.getStat(INTELLECT),
 		c.statColor(c.getStat(LUCK), c.getStat(LUCK, true)), c.getStat(LUCK),
diff --git a/engines/xeen/party.cpp b/engines/xeen/party.cpp
index 3cfc56e..42500dd 100644
--- a/engines/xeen/party.cpp
+++ b/engines/xeen/party.cpp
@@ -187,7 +187,7 @@ int Character::getMaxSP() const {
 	Attribute attrib;
 	Skill skill;
 
-	if (_hasSpells)
+	if (!_hasSpells)
 		return 0;
 
 	if (_class == CLASS_SORCERER || _class == CLASS_ARCHER) {
@@ -202,7 +202,7 @@ int Character::getMaxSP() const {
 
 	for (;;) {
 		// Get the base number of spell points
-		result = statBonus(getStat(attrib));
+		result = statBonus(getStat(attrib)) + 3;
 		result += RACE_SP_BONUSES[_race][attrib - 1];
 
 		if (_skills[skill])
diff --git a/engines/xeen/resources.cpp b/engines/xeen/resources.cpp
index 467dbe2..0847944 100644
--- a/engines/xeen/resources.cpp
+++ b/engines/xeen/resources.cpp
@@ -304,9 +304,9 @@ const uint CLASS_EXP_LEVELS[10] = {
 };
 
 const char *const CONDITION_NAMES[17] = {
-	nullptr, "Cursed", "Heart Broken", "Weak", "Poisoned", "Diseased", 
+	"Cursed", "Heart Broken", "Weak", "Poisoned", "Diseased", 
 	"Insane", "In Love", "Drunk", "Asleep", "Depressed", "Confused", 
-	"Paralyzed", "Unconscious", "Dead", "Stone", "Eradicated" 
+	"Paralyzed", "Unconscious", "Dead", "Stone", "Eradicated", "Good"
 };
 
 const int CONDITION_COLORS[17] = {
diff --git a/engines/xeen/screen.cpp b/engines/xeen/screen.cpp
index 9c9783b..bb2f356 100644
--- a/engines/xeen/screen.cpp
+++ b/engines/xeen/screen.cpp
@@ -192,9 +192,12 @@ void Window::drawList(DrawStruct *items, int count) {
 		if (items->_frame == -1 || items->_scale == -1 || items->_sprites == nullptr)
 			continue;
 			
+		Common::Point pt(items->_x, items->_y);
+		pt.x += _innerBounds.left;
+		pt.y += _innerBounds.top;
+
 		// TODO: There are two sprite calls in this method. Figure out why
-		items->_sprites->draw(*this, items->_frame,
-			Common::Point(items->_x, items->_y), items->_flags, items->_scale);
+		items->_sprites->draw(*this, items->_frame, pt, items->_flags, items->_scale);
 	}
 }
 


Commit: 2b2ce19012c6b51e35704331d8b322f38c97f462
    https://github.com/scummvm/scummvm/commit/2b2ce19012c6b51e35704331d8b322f38c97f462
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-02-01T16:51:04-05:00

Commit Message:
XEEN: Fixes for Character Info dialog stat details display

Changed paths:
    engines/xeen/dialogs_char_info.cpp
    engines/xeen/party.cpp
    engines/xeen/party.h
    engines/xeen/town.cpp
    engines/xeen/town.h



diff --git a/engines/xeen/dialogs_char_info.cpp b/engines/xeen/dialogs_char_info.cpp
index 1c0d0bf..44ce73e 100644
--- a/engines/xeen/dialogs_char_info.cpp
+++ b/engines/xeen/dialogs_char_info.cpp
@@ -243,7 +243,7 @@ void CharacterInfo::loadDrawStructs() {
  * Set up the button list for the dialog
  */
 void CharacterInfo::addButtons() {
-	addButton(Common::Rect(10, 24, 34, 64), 1001, &_iconSprites);
+	addButton(Common::Rect(10, 24, 34, 44), 1001, &_iconSprites);
 	addButton(Common::Rect(10, 47, 34, 67), 1002, &_iconSprites);
 	addButton(Common::Rect(10, 70, 34, 90), 1003, &_iconSprites);
 	addButton(Common::Rect(10, 93, 34, 113), 1004, &_iconSprites);
@@ -343,7 +343,7 @@ bool CharacterInfo::expandStat(int attrib, const Character &c) {
 	Common::Rect bounds(STAT_POS[0][attrib], STAT_POS[1][attrib],
 		STAT_POS[0][attrib] + 143, STAT_POS[1][attrib] + 52);
 	Party &party = *_vm->_party;
-	int stat1, stat2;
+	uint stat1, stat2;
 	uint idx;
 	Common::String msg;
 
@@ -371,7 +371,7 @@ bool CharacterInfo::expandStat(int attrib, const Character &c) {
 		stat1 = c.getAge(false);
 		stat2 = c.getAge(true);
 		msg = Common::String::format(AGE_TEXT, STAT_NAMES[attrib],
-			stat2, c._dbDay, c._ybDay);
+			stat1, stat2, c._birthDay, c._birthYear);
 		break;
 
 	case 8: {
@@ -422,6 +422,7 @@ bool CharacterInfo::expandStat(int attrib, const Character &c) {
 			c._poisonResistence._permanent + c.itemScan(14) + c._poisonResistence._temporary,
 			c._energyResistence._permanent + c.itemScan(15) + c._energyResistence._temporary,
 			c._magicResistence._permanent + c.itemScan(16) + c._magicResistence._temporary);
+		bounds.setHeight(80);
 		break;
 
 	case 13: {
@@ -466,10 +467,10 @@ bool CharacterInfo::expandStat(int attrib, const Character &c) {
 	case 15:
 		// Experience
 		stat1 = c.getCurrentExperience();
-		stat2 = c.nextExperienceLevel();
+		stat2 = c.experienceToNextLevel();
 		msg = Common::String::format(EXPERIENCE_TEXT,
 			STAT_NAMES[attrib], stat1,
-			stat2 == 0 ? ELIGIBLE : Common::String::format("%d", stat2)
+			stat2 == 0 ? ELIGIBLE : Common::String::format("%d", stat2).c_str()
 		);
 		bounds.setHeight(43);
 		break;
@@ -478,6 +479,7 @@ bool CharacterInfo::expandStat(int attrib, const Character &c) {
 		// Gold
 		msg = Common::String::format(IN_PARTY_IN_BANK, STAT_NAMES[attrib],
 			party._gold, party._bankGold);
+		bounds.setHeight(43);
 		break;
 
 	case 17:
@@ -516,6 +518,7 @@ bool CharacterInfo::expandStat(int attrib, const Character &c) {
 		Condition condition = c.worstCondition();
 		if (condition == NO_CONDITION) {
 			lines[0] = Common::String::format("\n\t020%s", GOOD);
+			++total;
 		}
 
 		if (party._blessed)
@@ -537,7 +540,7 @@ bool CharacterInfo::expandStat(int attrib, const Character &c) {
 			lines[17].c_str(), lines[18].c_str(), lines[19].c_str()
 		);
 
-		bounds.top = ((total - 1) / 2) * 8;
+		bounds.top -= ((total - 1) / 2) * 8;
 		bounds.setHeight(total * 9 + 26);
 		if (bounds.bottom >= SCREEN_HEIGHT)
 			bounds.moveTo(bounds.left, SCREEN_HEIGHT - bounds.height() - 1);
diff --git a/engines/xeen/party.cpp b/engines/xeen/party.cpp
index 42500dd..d046595 100644
--- a/engines/xeen/party.cpp
+++ b/engines/xeen/party.cpp
@@ -49,7 +49,7 @@ Character::Character() {
 	_xeenSide = 0;
 	_class = CLASS_KNIGHT;
 	_ACTemp = 0;
-	_dbDay = 0;
+	_birthDay = 0;
 	_tempAge = 0;
 	Common::fill(&_skills[0], &_skills[18], 0);
 	Common::fill(&_awards[0], &_awards[128], false);
@@ -64,7 +64,7 @@ Character::Character() {
 	_savedMazeId = 0;
 	_currentHp = 0;
 	_currentSp = 0;
-	_ybDay = 0;
+	_birthYear = 0;
 	_experience = 0;
 	_currentAdventuringSpell = 0;
 	_currentCombatSpell = 0;
@@ -93,7 +93,7 @@ void Character::synchronize(Common::Serializer &s) {
 	_luck.synchronize(s);
 	s.syncAsByte(_ACTemp);
 	_level.synchronize(s);
-	s.syncAsByte(_dbDay);
+	s.syncAsByte(_birthDay);
 	s.syncAsByte(_tempAge);
 	
 	// Synchronize the skill list
@@ -144,7 +144,7 @@ void Character::synchronize(Common::Serializer &s) {
 	s.syncAsByte(_savedMazeId);
 	s.syncAsUint16LE(_currentHp);
 	s.syncAsUint16LE(_currentSp);
-	s.syncAsUint16LE(_ybDay);
+	s.syncAsUint16LE(_birthYear);
 	s.syncAsUint32LE(_experience);
 	s.syncAsByte(_currentAdventuringSpell);
 	s.syncAsByte(_currentCombatSpell);
@@ -160,7 +160,7 @@ Condition Character::worstCondition() const {
 }
 
 int Character::getAge(bool ignoreTemp) const {
-	int year = MIN(Party::_vm->_party->_year - _ybDay, 254);
+	int year = MIN(Party::_vm->_party->_year - _birthYear, (uint)254);
 
 	return ignoreTemp ? year : year + _tempAge;
 }
@@ -796,22 +796,22 @@ bool Character::guildMember() const {
 	}
 }
 
-uint Character::nextExperienceLevel() const {
-	uint base = currentExperienceLevel();
+uint Character::experienceToNextLevel() const {
+	uint next = nextExperienceLevel();
 	uint curr = getCurrentExperience();
-	return (curr < base) ? 0 : curr - base;
+	return (curr >= next) ? 0 : next - curr;
 }
 
-uint Character::currentExperienceLevel() const {
+uint Character::nextExperienceLevel() const {
 	int shift, base;
 	if (_level._permanent >= 12) {
 		base = _level._permanent - 12;
 		shift = 10;
 	} else {
 		base = 0;
-		shift = _level._permanent;
+		shift = _level._permanent - 1;
 	}
-	
+
 	return (base * 1024000) + (CLASS_EXP_LEVELS[_class] << shift);
 }
 
diff --git a/engines/xeen/party.h b/engines/xeen/party.h
index b793b5c..5adc9b1 100644
--- a/engines/xeen/party.h
+++ b/engines/xeen/party.h
@@ -105,7 +105,7 @@ public:
 	AttributePair _luck;
 	int _ACTemp;
 	AttributePair _level;
-	int _dbDay;
+	uint _birthDay;
 	int _tempAge;
 	int _skills[18];
 	bool _awards[128];
@@ -131,7 +131,7 @@ public:
 	int _savedMazeId;
 	int _currentHp;
 	int _currentSp;
-	int _ybDay;
+	uint _birthYear;
 	uint32 _experience;
 	int _currentAdventuringSpell;
 	int _currentCombatSpell;
@@ -173,9 +173,9 @@ public:
 
 	bool guildMember() const;
 
-	uint nextExperienceLevel() const;
+	uint experienceToNextLevel() const;
 
-	uint currentExperienceLevel() const;
+	uint nextExperienceLevel() const;
 
 	uint getCurrentExperience() const;
 
@@ -223,7 +223,7 @@ public:
 	bool _worldEnd;
 	int _ctr24;	// TODO: Figure out proper name
 	int _day;
-	int _year;
+	uint _year;
 	int _minutes;
 	uint _food;
 	int _lightCount;
diff --git a/engines/xeen/town.cpp b/engines/xeen/town.cpp
index 2f31113..3449c2e 100644
--- a/engines/xeen/town.cpp
+++ b/engines/xeen/town.cpp
@@ -51,7 +51,7 @@ Town::Town(XeenEngine *vm) : _vm(vm) {
 	_dayOfWeek = 0;
 	_uncurseCost = 0;
 	_flag1 = false;
-	_nextExperienceLevel = 0;
+	_experienceToNextLevel = 0;
 	_drawCtr1 = _drawCtr2 = 0;
 }
 
@@ -458,14 +458,14 @@ Common::String Town::createTownText(Character &ch) {
 			}
 		}
 
-		_nextExperienceLevel = ch.nextExperienceLevel();
+		_experienceToNextLevel = ch.experienceToNextLevel();
 
-		if (_nextExperienceLevel >= 0x10000 && ch._level._permanent < _v20) {
+		if (_experienceToNextLevel >= 0x10000 && ch._level._permanent < _v20) {
 			int nextLevel = ch._level._permanent + 1;
 			return Common::String::format(EXPERIENCE_FOR_LEVEL,
-				ch._name.c_str(), _nextExperienceLevel, nextLevel);
+				ch._name.c_str(), _experienceToNextLevel, nextLevel);
 		} else if (ch._level._permanent >= 20) {
-			_nextExperienceLevel = 1;
+			_experienceToNextLevel = 1;
 			msg = Common::String::format(LEARNED_ALL, ch._name.c_str());
 		} else {
 			msg = Common::String::format(ELIGIBLE_FOR_LEVEL,
@@ -906,7 +906,7 @@ Character *Town::doTrainingOptions(Character *c) {
 		break;
 
 	case Common::KEYCODE_t:
-		if (_nextExperienceLevel) {
+		if (_experienceToNextLevel) {
 			sound.playSample(nullptr, 0);
 			_drawFrameIndex = 0;
 
@@ -927,7 +927,7 @@ Character *Town::doTrainingOptions(Character *c) {
 				File f(isDarkCc ? "prtygd.voc" : "trainin2.voc");
 				sound.playSample(&f, 1);
 
-				c->_experience -=  c->currentExperienceLevel() - 
+				c->_experience -=  c->nextExperienceLevel() - 
 					(c->getCurrentExperience() - c->_experience);
 				c->_level._permanent++;
 
diff --git a/engines/xeen/town.h b/engines/xeen/town.h
index 807f6b5..de87f03 100644
--- a/engines/xeen/town.h
+++ b/engines/xeen/town.h
@@ -58,7 +58,7 @@ private:
 	int _arr1[6];
 	int _currentCharLevel;
 	bool _flag1;
-	uint _nextExperienceLevel;
+	uint _experienceToNextLevel;
 	int _drawFrameIndex;
 	int _drawCtr1, _drawCtr2;
 


Commit: 78234db2c02c95e1b9e88b4096b9a9c96fd95adf
    https://github.com/scummvm/scummvm/commit/78234db2c02c95e1b9e88b4096b9a9c96fd95adf
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-02-01T19:04:28-05:00

Commit Message:
XEEN: Add Quick Reference dialog

Changed paths:
  A engines/xeen/dialogs_quick_ref.cpp
  A engines/xeen/dialogs_quick_ref.h
    engines/xeen/combat.cpp
    engines/xeen/combat.h
    engines/xeen/dialogs_char_info.cpp
    engines/xeen/font.cpp
    engines/xeen/interface.cpp
    engines/xeen/module.mk
    engines/xeen/party.cpp
    engines/xeen/party.h
    engines/xeen/resources.cpp
    engines/xeen/resources.h



diff --git a/engines/xeen/combat.cpp b/engines/xeen/combat.cpp
index 4d3cb53..6237e0c 100644
--- a/engines/xeen/combat.cpp
+++ b/engines/xeen/combat.cpp
@@ -33,6 +33,7 @@ Combat::Combat(XeenEngine *vm): _vm(vm) {
 	Common::fill(&_elemPow[0], &_elemPow[12], 0);
 	Common::fill(&_elemScale[0], &_elemScale[12], 0);
 	Common::fill(&_shooting[0], &_shooting[8], 0);
+	_globalCombat = 0;
 }
 
 void Combat::clear() {
diff --git a/engines/xeen/combat.h b/engines/xeen/combat.h
index 550b39f..c2554d5 100644
--- a/engines/xeen/combat.h
+++ b/engines/xeen/combat.h
@@ -58,6 +58,7 @@ public:
 	int _elemPow[12];
 	int _elemScale[12];
 	bool _shooting[8];
+	int _globalCombat;
 public:
 	Combat(XeenEngine *vm);
 
diff --git a/engines/xeen/dialogs_char_info.cpp b/engines/xeen/dialogs_char_info.cpp
index 44ce73e..985309a 100644
--- a/engines/xeen/dialogs_char_info.cpp
+++ b/engines/xeen/dialogs_char_info.cpp
@@ -22,6 +22,7 @@
 
 #include "xeen/dialogs_char_info.h"
 #include "xeen/dialogs_exchange.h"
+#include "xeen/dialogs_quick_ref.h"
 #include "xeen/resources.h"
 #include "xeen/xeen.h"
 
@@ -194,6 +195,11 @@ void CharacterInfo::execute(int charIndex) {
 			_vm->_mode = MODE_CHARACTER_INFO;
 			break;
 
+		case Common::KEYCODE_q:
+			QuickReferenceDialog::show(_vm);
+			redrawFlag = true;
+			break;
+
 		case Common::KEYCODE_ESCAPE:
 			goto exit;
 		}
@@ -568,5 +574,4 @@ bool CharacterInfo::expandStat(int attrib, const Character &c) {
 	return false;
 }
 
-
 } // End of namespace Xeen
diff --git a/engines/xeen/dialogs_quick_ref.cpp b/engines/xeen/dialogs_quick_ref.cpp
new file mode 100644
index 0000000..a54bb06
--- /dev/null
+++ b/engines/xeen/dialogs_quick_ref.cpp
@@ -0,0 +1,89 @@
+/* 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 "xeen/dialogs_quick_ref.h"
+#include "xeen/resources.h"
+#include "xeen/xeen.h"
+
+namespace Xeen {
+
+void QuickReferenceDialog::show(XeenEngine *vm) {
+	QuickReferenceDialog *dlg = new QuickReferenceDialog(vm);
+	dlg->execute();
+	delete dlg;
+}
+
+void QuickReferenceDialog::execute() {
+	Combat &combat = *_vm->_combat;
+	EventsManager &events = *_vm->_events;
+	Interface &intf = *_vm->_interface;
+	Party &party = *_vm->_party;
+	Screen &screen = *_vm->_screen;
+	Common::String lines[8];
+
+	events.setCursor(0);
+
+	for (uint idx = 0; idx < (combat._globalCombat == 2 ? party._combatParty.size() :
+			party._partyCount); ++idx) {
+		Character &c = combat._globalCombat == 2 ? *party._combatParty[idx] :
+			party._activeParty[idx];
+		Condition condition = c.worstCondition();
+		lines[idx] = Common::String::format(QUICK_REF_LINE,
+			idx * 10 + 24, idx + 1, c._name.c_str(),
+			CLASS_NAMES[c._class][0], CLASS_NAMES[c._class][1], CLASS_NAMES[c._class][2],
+			c.statColor(c.getCurrentLevel(), c._level._permanent), c._level._permanent,
+			c.statColor(c._currentHp, c.getMaxHP()), c._currentHp,
+			c.statColor(c._currentSp, c.getMaxSP()), c._currentSp,
+			c.statColor(c.getArmorClass(), c.getArmorClass(true)), c.getArmorClass(),
+			CONDITION_COLORS[condition],
+			CONDITION_NAMES[condition][0], CONDITION_NAMES[condition][1],
+			CONDITION_NAMES[condition][2], CONDITION_NAMES[condition][3]
+		);
+	}
+
+	int food = (party._food / party._partyCount) / 3;
+	Common::String msg = Common::String::format(QUICK_REFERENCE,
+		lines[0].c_str(), lines[1].c_str(), lines[2].c_str(),
+		lines[3].c_str(), lines[4].c_str(), lines[5].c_str(),
+		lines[6].c_str(), lines[7].c_str(),
+		party._gold, party._gems,
+		food, food == 1 ? "" : "s"
+	);
+
+	Window &w = screen._windows[24];
+	bool windowOpen = w._enabled;
+	if (!windowOpen)
+		w.open();
+	w.writeString(msg);
+	w.update();
+
+	// Wait for a key/mouse press
+	events.clearEvents();
+	while (!_vm->shouldQuit() && !events.isKeyMousePressed())
+		events.pollEventsAndWait();
+	events.clearEvents();
+
+	if (!windowOpen)
+		w.close();
+}
+
+} // End of namespace Xeen
diff --git a/engines/xeen/dialogs_quick_ref.h b/engines/xeen/dialogs_quick_ref.h
new file mode 100644
index 0000000..0c1b8e3
--- /dev/null
+++ b/engines/xeen/dialogs_quick_ref.h
@@ -0,0 +1,43 @@
+/* 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_QUICK_REF_H
+#define XEEN_DIALOGS_QUICK_REF_H
+
+#include "xeen/dialogs.h"
+
+namespace Xeen {
+
+class QuickReferenceDialog : public ButtonContainer {
+private:
+	XeenEngine *_vm;
+
+	QuickReferenceDialog(XeenEngine *vm) : ButtonContainer(), _vm(vm) {}
+
+	void execute();
+public:
+	static void show(XeenEngine *vm);
+};
+
+} // End of namespace Xeen
+
+#endif /* XEEN_DIALOGS_QUICK_REF_H */
diff --git a/engines/xeen/font.cpp b/engines/xeen/font.cpp
index 1668ef5..aca747e 100644
--- a/engines/xeen/font.cpp
+++ b/engines/xeen/font.cpp
@@ -28,19 +28,13 @@ namespace Xeen {
 
 FontSurface::FontSurface() : XSurface(), _fontData(nullptr), _bgColor(DEFAULT_BG_COLOR), 
 		_fontReduced(false),_fontJustify(JUSTIFY_NONE), _msgWraps(false) {
-	_textColors[0] = 0;
-	_textColors[1] = 0x40;
-	_textColors[2] = 0x30;
-	_textColors[3] = 0x20;
+	setTextColor(0);
 }
 
 FontSurface::FontSurface(int wv, int hv) : XSurface(wv, hv), _fontData(nullptr), _msgWraps(false),
 		_bgColor(DEFAULT_BG_COLOR), _fontReduced(false), _fontJustify(JUSTIFY_NONE) {
 	create(w, h);
-	_textColors[0] = 0;
-	_textColors[1] = 0x40;
-	_textColors[2] = 0x30;
-	_textColors[3] = 0x20;
+	setTextColor(0);
 }
 
 /**
diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp
index a33c726..520cad5 100644
--- a/engines/xeen/interface.cpp
+++ b/engines/xeen/interface.cpp
@@ -25,6 +25,7 @@
 #include "xeen/dialogs_error.h"
 #include "xeen/dialogs_automap.h"
 #include "xeen/dialogs_info.h"
+#include "xeen/dialogs_quick_ref.h"
 #include "xeen/resources.h"
 #include "xeen/xeen.h"
 
@@ -704,6 +705,11 @@ void Interface::perform() {
 		AutoMapDialog::show(_vm);
 		break;
 
+	case Common::KEYCODE_q:
+		// Show the quick reference dialog
+		QuickReferenceDialog::show(_vm);
+		break;
+
 	default:
 		break;
 	}
diff --git a/engines/xeen/module.mk b/engines/xeen/module.mk
index 8d3a5e5..eef8d78 100644
--- a/engines/xeen/module.mk
+++ b/engines/xeen/module.mk
@@ -17,6 +17,7 @@ MODULE_OBJS := \
 	dialogs_options.o \
 	dialogs_info.o \
 	dialogs_input.o \
+	dialogs_quick_ref.o \
 	dialogs_spells.o \
 	dialogs_whowill.o \
 	dialogs_yesno.o \
diff --git a/engines/xeen/party.cpp b/engines/xeen/party.cpp
index d046595..ce5ccd0 100644
--- a/engines/xeen/party.cpp
+++ b/engines/xeen/party.cpp
@@ -309,7 +309,7 @@ int Character::statColor(int amount, int threshold) {
 		return 32;
 }
 
-int Character::statBonus(int statValue) const {
+int Character::statBonus(uint statValue) const {
 	int idx;
 	for (idx = 0; STAT_VALUES[idx] <= statValue; ++idx)
 		;
diff --git a/engines/xeen/party.h b/engines/xeen/party.h
index 5adc9b1..65e6608 100644
--- a/engines/xeen/party.h
+++ b/engines/xeen/party.h
@@ -151,7 +151,7 @@ public:
 
 	static int statColor(int amount, int threshold);
 
-	int statBonus(int statValue) const;
+	int statBonus(uint statValue) const;
 
 	bool charSavingThrow(DamageType attackType) const;
 
diff --git a/engines/xeen/resources.cpp b/engines/xeen/resources.cpp
index 0847944..eecc5b8 100644
--- a/engines/xeen/resources.cpp
+++ b/engines/xeen/resources.cpp
@@ -543,9 +543,9 @@ const int AGE_RANGES_ADJUST[2][10] = {
 	{ -250, -50, -20, -10, 0, 2, 5, 10, 20, 50 }
 };
 
-const int STAT_VALUES[24] = {
+const uint STAT_VALUES[24] = {
 	3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 25, 30, 35, 40, 
-	50, 75, 100, 125, 150, 175, 200, 225, 250, 65535
+	50, 75, 100, 125, 150, 175, 200, 225, 250, 
 };
 
 const int STAT_BONUSES[24] = {
@@ -971,4 +971,17 @@ const char *const FOOD_TEXT =
 
 const char *const EXCHANGE_WITH_WHOM = "\t010\v005Exchange with whom?";
 
+const char *const QUICK_REF_LINE = 
+	"\xB%3d\x9""007%u)\x9""027%s\x9""110%c%c%c\x3r\x9""160\xC%02u%u\xC""d"
+	"\x3l\x9""170\xC%02u%d\xC""d\x9""208\xC%02u%u\xC""d\x9""247\xC"
+	"%02u%u\xC""d\x9""270\xC%02u%c%c%c%c\xC""d";
+
+const char *const QUICK_REFERENCE =
+	"\xD\x3""cQuick Reference Chart\xB""012\x3l"
+	"\x9""007#\x9""027Name\x9""110Cls\x9""140Lvl\x9""176H.P."
+	"\x9""212S.P.\x9""241A.C.\x9""270Cond"
+	"%s%s%s%s%s%s%s%s"
+	"\xB""110\x9""064\x3""cGold\x9""144Gems\x9""224Food\xB""119"
+	"\x9""064\xC""15%lu\x9""144%lu\x9""224%u day%s\xC""d";
+
 } // End of namespace Xeen
diff --git a/engines/xeen/resources.h b/engines/xeen/resources.h
index 64387e7..e8f5c31 100644
--- a/engines/xeen/resources.h
+++ b/engines/xeen/resources.h
@@ -147,7 +147,7 @@ extern const int AGE_RANGES[10];
 
 extern const int AGE_RANGES_ADJUST[2][10];
 
-extern const int STAT_VALUES[24];
+extern const uint STAT_VALUES[24];
 
 extern const int STAT_BONUSES[24];
 
@@ -323,6 +323,10 @@ extern const char *const FOOD_TEXT;
 
 extern const char *const EXCHANGE_WITH_WHOM;
 
+extern const char *const QUICK_REF_LINE;
+
+extern const char *const QUICK_REFERENCE;
+
 } // End of namespace Xeen
 
 #endif	/* XEEN_RESOURCES_H */


Commit: 7febe773008db7cee0ed1b3f5f1f2fb114d22334
    https://github.com/scummvm/scummvm/commit/7febe773008db7cee0ed1b3f5f1f2fb114d22334
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-02-01T23:32:16-05:00

Commit Message:
XEEN: Beginnings of Items dialog

Changed paths:
  A engines/xeen/dialogs_items.cpp
  A engines/xeen/dialogs_items.h
    engines/xeen/dialogs_char_info.cpp
    engines/xeen/dialogs_quick_ref.cpp
    engines/xeen/items.cpp
    engines/xeen/items.h
    engines/xeen/module.mk
    engines/xeen/party.cpp
    engines/xeen/party.h
    engines/xeen/resources.cpp
    engines/xeen/resources.h
    engines/xeen/scripts.cpp
    engines/xeen/town.cpp
    engines/xeen/town.h



diff --git a/engines/xeen/dialogs_char_info.cpp b/engines/xeen/dialogs_char_info.cpp
index 985309a..1d907cf 100644
--- a/engines/xeen/dialogs_char_info.cpp
+++ b/engines/xeen/dialogs_char_info.cpp
@@ -22,6 +22,7 @@
 
 #include "xeen/dialogs_char_info.h"
 #include "xeen/dialogs_exchange.h"
+#include "xeen/dialogs_items.h"
 #include "xeen/dialogs_quick_ref.h"
 #include "xeen/resources.h"
 #include "xeen/xeen.h"
@@ -185,7 +186,7 @@ void CharacterInfo::execute(int charIndex) {
 		case Common::KEYCODE_i:
 			_vm->_mode = oldMode;
 			_vm->_treasure._v1 = _vm->_mode == MODE_InCombat;
-			error("TODO: c = ItemDialog::show");
+			c = ItemsDialog::show(_vm, c, ITEMMODE_CHAR_INFO);
 
 			if (!c) {
 				party._stepped = true;
diff --git a/engines/xeen/dialogs_items.cpp b/engines/xeen/dialogs_items.cpp
new file mode 100644
index 0000000..fea0432
--- /dev/null
+++ b/engines/xeen/dialogs_items.cpp
@@ -0,0 +1,292 @@
+/* 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 "xeen/dialogs_items.h"
+#include "xeen/resources.h"
+#include "xeen/xeen.h"
+
+namespace Xeen {
+
+Character *ItemsDialog::show(XeenEngine *vm, Character *c, ItemsMode mode) {
+	ItemsDialog *dlg = new ItemsDialog(vm);
+	Character *result = dlg->execute(c, mode);
+	delete dlg;
+
+	return result;
+}
+
+Character *ItemsDialog::execute(Character *c, ItemsMode mode) {
+	EventsManager &events = *_vm->_events;
+	Interface &intf = *_vm->_interface;
+	Party &party = *_vm->_party;
+	Screen &screen = *_vm->_screen;
+	
+	Character *tempChar = c;
+	int typeNum = mode == ITEMMODE_4 || mode == ITEMMODE_COMBAT ? 3 : 0;
+	int varA = mode == ITEMMODE_COMBAT ? 1 : 0;
+	if (varA != 0)
+		mode = ITEMMODE_CHAR_INFO;
+	int varE = mode == 1 ? 1 : 0;
+
+	events.setCursor(0);
+	loadButtons(mode, c);
+
+	screen._windows[29].open();
+	screen._windows[30].open();
+
+	bool redrawFlag = true;
+	while (!_vm->shouldQuit()) {
+		if (redrawFlag) {
+			if ((mode != ITEMMODE_CHAR_INFO || typeNum != 3) && mode != ITEMMODE_6
+					&& mode != ITEMMODE_4 && mode != ITEMMODE_TO_GOLD) {
+				_buttons[8]._bounds.moveTo(148, _buttons[8]._bounds.top);
+				_buttons[9]._draw = false;
+			} else if (mode == ITEMMODE_4) {
+				_buttons[4]._value = Common::KEYCODE_r;
+			} else if (mode == ITEMMODE_6) {
+				_buttons[4]._value = Common::KEYCODE_e;
+			} else if (mode == ITEMMODE_TO_GOLD) {
+				_buttons[4]._value = Common::KEYCODE_g;
+			} else {
+				_buttons[8]._bounds.moveTo(0, _buttons[8]._bounds.top);
+				_buttons[9]._draw = true;
+				_buttons[9]._value = Common::KEYCODE_u;
+			}
+
+			// Write text for the dialog
+			Common::String msg;
+			if (mode != ITEMMODE_CHAR_INFO && mode != ITEMMODE_8 && mode != ITEMMODE_6
+					&& mode != ITEMMODE_4 && mode != ITEMMODE_TO_GOLD) {
+				msg = Common::String::format(ITEMS_DIALOG_TEXT1,
+					BTN_SELL, BTN_IDENTIFY, BTN_FIX);
+			} else if (mode != ITEMMODE_6  && mode != ITEMMODE_4 && mode != ITEMMODE_TO_GOLD) {
+				msg = Common::String::format(ITEMS_DIALOG_TEXT1,
+					typeNum == 3 ? BTN_USE : BTN_EQUIP, 
+					BTN_REMOVE, BTN_DISCARD, BTN_QUEST);
+			} else if (mode == ITEMMODE_6) {
+				msg = Common::String::format(ITEMS_DIALOG_TEXT2, BTN_ENCHANT);
+			} else if (mode == ITEMMODE_4) {
+				msg = Common::String::format(ITEMS_DIALOG_TEXT2, BTN_RECHARGE);
+			} else {
+				msg = Common::String::format(ITEMS_DIALOG_TEXT2, BTN_GOLD);
+			}
+
+			screen._windows[29].writeString(msg);
+			drawButtons(&screen);
+		}
+
+		int arr[40];
+		Common::fill(&arr[0], &arr[40], false);
+		int var2 = -1;
+	
+		if (mode == ITEMMODE_CHAR_INFO || typeNum != 3) {
+			_iconSprites.draw(screen, 8, Common::Point(148, 109));
+		}
+		if (mode != ITEMMODE_6 && mode != ITEMMODE_4 && mode != ITEMMODE_TO_GOLD) {
+			_iconSprites.draw(screen, 10, Common::Point(182, 109));
+			_iconSprites.draw(screen, 12, Common::Point(216, 109));
+			_iconSprites.draw(screen, 14, Common::Point(250, 109));
+		}
+
+		switch (mode) {
+		case ITEMMODE_CHAR_INFO:
+			_iconSprites.draw(screen, 9, Common::Point(148, 109));
+			break;
+		case ITEMMODE_BLACKSMITH:
+			_iconSprites.draw(screen, 11, Common::Point(182, 109));
+			break;
+		case ITEMMODE_9:
+			_iconSprites.draw(screen, 15, Common::Point(250, 109));
+			break;
+		case ITEMMODE_10:
+			_iconSprites.draw(screen, 13, Common::Point(216, 109));
+			break;
+		default:
+			break;
+		}
+
+		for (int idx = 0; idx < 9; ++idx) {
+			_itemsDrawList[idx]._y = 10 + idx * 9;
+
+			switch (typeNum) {
+			case 0:
+				if (c->_weapons[idx]._id) {
+					if (mode == ITEMMODE_CHAR_INFO || mode == ITEMMODE_8
+							|| mode == ITEMMODE_6 || mode == ITEMMODE_4) {
+						// TODO
+					}
+				} else if (_itemsDrawList[idx]._sprites == nullptr) {
+					// TODO
+				}
+				break;
+				// TODO
+			default:
+				break;
+			}
+		}
+	}
+
+	return c;
+}
+
+/**
+ * Load the buttons for the dialog
+ */
+void ItemsDialog::loadButtons(ItemsMode mode, Character *&c) {
+	_iconSprites.load(Common::String::format("%s.icn",
+		(mode == ITEMMODE_CHAR_INFO) ? "items" : "buy"));
+	_equipSprites.load("equip.icn");
+
+	if (mode == ITEMMODE_6 || mode == ITEMMODE_4 || mode == ITEMMODE_TO_GOLD) {
+		// Enchant button list
+		addButton(Common::Rect(12, 109, 36, 129), Common::KEYCODE_w, &_iconSprites);
+		addButton(Common::Rect(46, 109, 70, 129), Common::KEYCODE_a, &_iconSprites);
+		addButton(Common::Rect(80, 109, 104, 129), Common::KEYCODE_c, &_iconSprites);
+		addButton(Common::Rect(114, 109, 138, 129), Common::KEYCODE_n, &_iconSprites);
+		addButton(Common::Rect(148, 109, 172, 129), Common::KEYCODE_e, &_iconSprites);
+		addButton(Common::Rect(284, 109, 308, 129), Common::KEYCODE_ESCAPE, &_iconSprites);
+		addButton(Common::Rect(148, 109, 172, 129), Common::KEYCODE_u, &_iconSprites);
+		addButton(Common::Rect(8, 20, 263, 28), Common::KEYCODE_1, &_iconSprites, false);
+		addButton(Common::Rect(8, 29, 263, 37), Common::KEYCODE_2, &_iconSprites, false);
+		addButton(Common::Rect(8, 38, 263, 46), Common::KEYCODE_3, &_iconSprites, false);
+		addButton(Common::Rect(8, 47, 263, 55), Common::KEYCODE_4, &_iconSprites, false);
+		addButton(Common::Rect(8, 56, 263, 64), Common::KEYCODE_5, &_iconSprites, false);
+		addButton(Common::Rect(8, 65, 263, 73), Common::KEYCODE_6, &_iconSprites, false);
+		addButton(Common::Rect(8, 74, 263, 82), Common::KEYCODE_7, &_iconSprites, false);
+		addButton(Common::Rect(8, 83, 263, 91), Common::KEYCODE_8, &_iconSprites, false);
+		addButton(Common::Rect(8, 92, 263, 100), Common::KEYCODE_9, &_iconSprites, false);
+	} else {
+		addButton(Common::Rect(12, 109, 36, 129), Common::KEYCODE_w, &_iconSprites);
+		addButton(Common::Rect(46, 109, 70, 129), Common::KEYCODE_a, &_iconSprites);
+		addButton(Common::Rect(80, 109, 104, 129), Common::KEYCODE_c, &_iconSprites);
+		addButton(Common::Rect(114, 109, 138, 129), Common::KEYCODE_n, &_iconSprites);
+		addButton(Common::Rect(148, 109, 172, 129), Common::KEYCODE_e, &_iconSprites);
+		addButton(Common::Rect(182, 109, 206, 129), Common::KEYCODE_r, &_iconSprites);
+		addButton(Common::Rect(216, 109, 240, 129), Common::KEYCODE_d, &_iconSprites);
+		addButton(Common::Rect(250, 109, 274, 129), Common::KEYCODE_q, &_iconSprites);
+		addButton(Common::Rect(284, 109, 308, 129), Common::KEYCODE_ESCAPE, &_iconSprites);
+		addButton(Common::Rect(8, 20, 263, 28), Common::KEYCODE_1, &_iconSprites, false);
+		addButton(Common::Rect(8, 29, 263, 37), Common::KEYCODE_2, &_iconSprites, false);
+		addButton(Common::Rect(8, 38, 263, 46), Common::KEYCODE_3, &_iconSprites, false);
+		addButton(Common::Rect(8, 47, 263, 55), Common::KEYCODE_4, &_iconSprites, false);
+		addButton(Common::Rect(8, 56, 263, 64), Common::KEYCODE_5, &_iconSprites, false);
+		addButton(Common::Rect(8, 65, 263, 73), Common::KEYCODE_6, &_iconSprites, false);
+		addButton(Common::Rect(8, 74, 263, 82), Common::KEYCODE_7, &_iconSprites, false);
+		addButton(Common::Rect(8, 83, 263, 91), Common::KEYCODE_8, &_iconSprites, false);
+		addButton(Common::Rect(8, 92, 263, 100), Common::KEYCODE_9, &_iconSprites, false);
+	}
+
+	if (mode == ITEMMODE_BLACKSMITH) {
+		_oldCharacter = c;
+		c = &_itemsCharacter;
+		blackData2CharData();
+
+		_buttons[4]._value = Common::KEYCODE_b;
+		_buttons[5]._value = Common::KEYCODE_s;
+		_buttons[6]._value = Common::KEYCODE_i;
+		_buttons[7]._value = Common::KEYCODE_f;
+
+		setEquipmentIcons();
+	} else {
+		_buttons[4]._value = Common::KEYCODE_e;
+		_buttons[5]._value = Common::KEYCODE_r;
+		_buttons[6]._value = Common::KEYCODE_d;
+		_buttons[7]._value = Common::KEYCODE_q;
+	}
+}
+
+/**
+ * Loads the temporary _itemsCharacter character with the item set
+ * the given blacksmith has available, so the user can "view" the
+ * set as if it were a standard character's inventory
+ */
+void ItemsDialog::blackData2CharData() {
+	Party &party = *_vm->_party;
+	bool isDarkCc = _vm->_files->_isDarkCc;
+	int slotIndex = 0;
+	while (party._mazeId != (int)BLACKSMITH_MAP_IDS[isDarkCc][slotIndex] && slotIndex < 4)
+		++slotIndex;
+	if (slotIndex == 4)
+		slotIndex = 0;
+
+	for (int idx = 0; idx < INV_ITEMS_TOTAL; ++idx) {
+		_itemsCharacter._weapons[idx] = party._blacksmithWeapons[isDarkCc][idx];
+		_itemsCharacter._armor[idx] = party._blacksmithArmor[isDarkCc][idx];
+		_itemsCharacter._accessories[idx] = party._blacksmithAccessories[isDarkCc][idx];
+		_itemsCharacter._misc[idx] = party._blacksmithMisc[isDarkCc][idx];
+	}
+}
+
+/**
+ * Sets the equipment icon to use for each item for display
+ */
+void ItemsDialog::setEquipmentIcons() {
+	for (int typeIndex = 0; typeIndex < 4; ++typeIndex) {
+		for (int idx = 0; idx < INV_ITEMS_TOTAL; ++idx) {
+			switch (typeIndex) {
+			case 0: {
+				XeenItem &i = _itemsCharacter._weapons[idx];
+				if (i._id <= 17)
+					i._equipped = 1;
+				else if (i._id <= 29 || i._id > 33)
+					i._equipped = 13;
+				else
+					i._equipped = 4;
+				break;
+			}
+
+			case 1: {
+				XeenItem &i = _itemsCharacter._armor[idx];
+				if (i._id <= 7)
+					i._equipped = 3;
+				else if (i._id == 9)
+					i._equipped = 5;
+				else if (i._id == 10)
+					i._equipped = 9;
+				else if (i._id <= 12)
+					i._equipped = 10;
+				else
+					i._equipped = 6;
+				break;
+			}
+
+			case 2: {
+				XeenItem &i = _itemsCharacter._accessories[idx];
+				if (i._id == 1)
+					i._id = 8;
+				else if (i._id == 2)
+					i._equipped = 12;
+				else if (i._id <= 7)
+					i._equipped = 7;
+				else
+					i._equipped = 11;
+				break;
+			}
+			
+			default:
+				break;
+			}
+		}
+	}
+}
+
+} // End of namespace Xeen
diff --git a/engines/xeen/dialogs_items.h b/engines/xeen/dialogs_items.h
new file mode 100644
index 0000000..100ac5c
--- /dev/null
+++ b/engines/xeen/dialogs_items.h
@@ -0,0 +1,63 @@
+/* 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_ITEMS_H
+#define XEEN_DIALOGS_ITEMS_H
+
+#include "xeen/dialogs.h"
+#include "xeen/party.h"
+#include "xeen/screen.h"
+
+namespace Xeen {
+
+enum ItemsMode {
+	ITEMMODE_CHAR_INFO = 0, ITEMMODE_BLACKSMITH = 1, ITEMMODE_4 = 4, 
+	ITEMMODE_6 = 6, ITEMMODE_COMBAT = 7, ITEMMODE_8 = 8, 
+	ITEMMODE_9 = 9, ITEMMODE_10 = 10, ITEMMODE_TO_GOLD = 11
+};
+
+class ItemsDialog : public ButtonContainer {
+private:
+	XeenEngine *_vm;
+	SpriteResource _iconSprites;
+	SpriteResource _equipSprites;
+	Character _itemsCharacter;
+	Character *_oldCharacter;
+	DrawStruct _itemsDrawList[9];
+
+	ItemsDialog(XeenEngine *vm) : ButtonContainer(), 
+		_vm(vm), _oldCharacter(nullptr) {}
+
+	Character *execute(Character *c, ItemsMode mode);
+
+	void loadButtons(ItemsMode mode, Character *&c);
+
+	void blackData2CharData();
+
+	void setEquipmentIcons();
+public:
+	static Character *show(XeenEngine *vm, Character *c, ItemsMode mode);
+};
+
+} // End of namespace Xeen
+
+#endif /* XEEN_DIALOGS_ITEMS_H */
diff --git a/engines/xeen/dialogs_quick_ref.cpp b/engines/xeen/dialogs_quick_ref.cpp
index a54bb06..6c8da5e 100644
--- a/engines/xeen/dialogs_quick_ref.cpp
+++ b/engines/xeen/dialogs_quick_ref.cpp
@@ -35,7 +35,6 @@ void QuickReferenceDialog::show(XeenEngine *vm) {
 void QuickReferenceDialog::execute() {
 	Combat &combat = *_vm->_combat;
 	EventsManager &events = *_vm->_events;
-	Interface &intf = *_vm->_interface;
 	Party &party = *_vm->_party;
 	Screen &screen = *_vm->_screen;
 	Common::String lines[8];
diff --git a/engines/xeen/items.cpp b/engines/xeen/items.cpp
index c55a227..fd06af1 100644
--- a/engines/xeen/items.cpp
+++ b/engines/xeen/items.cpp
@@ -26,13 +26,13 @@
 namespace Xeen {
 
 XeenItem::XeenItem() {
-	_material = _name = _bonusFlags = 0;
-	_equipped = false;
+	_material = _id = _bonusFlags = 0;
+	_equipped = 0;
 }
 
 void XeenItem::synchronize(Common::Serializer &s) {
 	s.syncAsByte(_material);
-	s.syncAsByte(_name);
+	s.syncAsByte(_id);
 	s.syncAsByte(_bonusFlags);
 	s.syncAsByte(_equipped);
 }
diff --git a/engines/xeen/items.h b/engines/xeen/items.h
index 8e8f172..154fd21 100644
--- a/engines/xeen/items.h
+++ b/engines/xeen/items.h
@@ -35,9 +35,9 @@ enum BonusFlags { FLAG_CURSED = 0x40 };
 class XeenItem {
 public:
 	int _material;
-	uint _name;
+	uint _id;
 	int _bonusFlags;
-	bool _equipped;
+	int _equipped;
 public:
 	XeenItem();
 
diff --git a/engines/xeen/module.mk b/engines/xeen/module.mk
index eef8d78..c1cdd05 100644
--- a/engines/xeen/module.mk
+++ b/engines/xeen/module.mk
@@ -17,6 +17,7 @@ MODULE_OBJS := \
 	dialogs_options.o \
 	dialogs_info.o \
 	dialogs_input.o \
+	dialogs_items.o \
 	dialogs_quick_ref.o \
 	dialogs_spells.o \
 	dialogs_whowill.o \
diff --git a/engines/xeen/party.cpp b/engines/xeen/party.cpp
index ce5ccd0..0353506 100644
--- a/engines/xeen/party.cpp
+++ b/engines/xeen/party.cpp
@@ -487,7 +487,7 @@ int Character::itemScan(int itemId) const {
 					}
 
 					if (itemId == 9) {
-						result += ARMOR_STRENGTHS[item._name];
+						result += ARMOR_STRENGTHS[item._id];
 
 						if (item._material >= 37 && item._material <= 58)
 							result += METAL_LAC[item._material - 37];
@@ -959,13 +959,13 @@ void Party::synchronize(Common::Serializer &s) {
 	s.syncAsByte(_difficulty);
 
 	for (int i = 0; i < ITEMS_COUNT; ++i)
-		_blacksmithWeapons[i].synchronize(s);
+		_blacksmithWeapons[0][i].synchronize(s);
 	for (int i = 0; i < ITEMS_COUNT; ++i)
-		_blacksmithArmor[i].synchronize(s);
+		_blacksmithArmor[0][i].synchronize(s);
 	for (int i = 0; i < ITEMS_COUNT; ++i)
-		_blacksmithAccessories[i].synchronize(s);
+		_blacksmithAccessories[0][i].synchronize(s);
 	for (int i = 0; i < ITEMS_COUNT; ++i)
-		_blacksmithMisc[i].synchronize(s);
+		_blacksmithMisc[0][i].synchronize(s);
 
 	s.syncAsUint16LE(_cloudsEnd);
 	s.syncAsUint16LE(_darkSideEnd);
@@ -998,13 +998,13 @@ void Party::synchronize(Common::Serializer &s) {
 		s.syncAsByte(_questItems[i]);
 
 	for (int i = 0; i < ITEMS_COUNT; ++i)
-		_blacksmithWeapons2[i].synchronize(s);
+		_blacksmithWeapons[1][i].synchronize(s);
 	for (int i = 0; i < ITEMS_COUNT; ++i)
-		_blacksmithArmor2[i].synchronize(s);
+		_blacksmithArmor[1][i].synchronize(s);
 	for (int i = 0; i < ITEMS_COUNT; ++i)
-		_blacksmithAccessories2[i].synchronize(s);
+		_blacksmithAccessories[1][i].synchronize(s);
 	for (int i = 0; i < ITEMS_COUNT; ++i)
-		_blacksmithMisc2[i].synchronize(s);
+		_blacksmithMisc[1][i].synchronize(s);
 
 	for (int i = 0; i < TOTAL_CHARACTERS; ++i)
 		SavesManager::syncBitFlags(s, &_characterFlags[i][0], &_characterFlags[i][24]);
diff --git a/engines/xeen/party.h b/engines/xeen/party.h
index 65e6608..8285ddf 100644
--- a/engines/xeen/party.h
+++ b/engines/xeen/party.h
@@ -214,10 +214,10 @@ public:
 	int _holyBonus;
 	int _heroism;
 	Difficulty _difficulty;
-	XeenItem _blacksmithWeapons[ITEMS_COUNT];
-	XeenItem _blacksmithArmor[ITEMS_COUNT];
-	XeenItem _blacksmithAccessories[ITEMS_COUNT];
-	XeenItem _blacksmithMisc[ITEMS_COUNT];
+	XeenItem _blacksmithWeapons[2][ITEMS_COUNT];
+	XeenItem _blacksmithArmor[2][ITEMS_COUNT];
+	XeenItem _blacksmithAccessories[2][ITEMS_COUNT];
+	XeenItem _blacksmithMisc[2][ITEMS_COUNT];
 	bool _cloudsEnd;
 	bool _darkSideEnd;
 	bool _worldEnd;
@@ -245,10 +245,6 @@ public:
 	bool _worldFlags[128];
 	bool _quests[64];
 	int _questItems[85];
-	XeenItem _blacksmithWeapons2[ITEMS_COUNT];
-	XeenItem _blacksmithArmor2[ITEMS_COUNT];
-	XeenItem _blacksmithAccessories2[ITEMS_COUNT];
-	XeenItem _blacksmithMisc2[ITEMS_COUNT];
 	bool _characterFlags[30][24];
 public:
 	// Other party related runtime data
diff --git a/engines/xeen/resources.cpp b/engines/xeen/resources.cpp
index eecc5b8..d89d2e6 100644
--- a/engines/xeen/resources.cpp
+++ b/engines/xeen/resources.cpp
@@ -984,4 +984,29 @@ const char *const QUICK_REFERENCE =
 	"\xB""110\x9""064\x3""cGold\x9""144Gems\x9""224Food\xB""119"
 	"\x9""064\xC""15%lu\x9""144%lu\x9""224%u day%s\xC""d";
 
+const uint BLACKSMITH_MAP_IDS[2][4] = { { 28, 30, 73, 49 }, { 29, 31, 37, 43 } };
+
+char *const ITEMS_DIALOG_TEXT1 =
+	"\r\x2\x3""c\v021\t017\f37W\fdeap\t051\f37A\fdrmor\t085A"
+	"\f37c\fdces\t119\f37M\fdisc\t153%s\t187%s\t221%s"
+	"\t255%s\t289Exit";
+
+char *const ITEMS_DIALOG_TEXT2 =
+	"\r\x2\x3""c\v021\t017\f37W\fdeap\t051\f37A\fdrmor\t085A"
+	"\f37c\fdces\t119\f37M\fdisc\t153\f37%s\t289Exit";
+
+const char *const BTN_BUY = "\f37B\fduy";
+const char *const BTN_SELL = "\f37S\fdell";
+const char *const BTN_IDENTIFY = "\f37I\fddentify";
+const char *const BTN_FIX = "\f37F\fdix";
+const char *const BTN_USE = "\f37U\fdse";
+const char *const BTN_EQUIP = "\f37E\fdquip";
+const char *const BTN_REMOVE = "\f37R\fdem";
+const char *const BTN_DISCARD = "\f37D\fdisc";
+const char *const BTN_QUEST = "\f37Q\fduest";
+const char *const BTN_ENCHANT = "E\fdnchant";
+const char *const BTN_RECHARGE = "R\fdechrg";
+const char *const BTN_GOLD = "G\fdold";
+
+
 } // End of namespace Xeen
diff --git a/engines/xeen/resources.h b/engines/xeen/resources.h
index e8f5c31..5437d40 100644
--- a/engines/xeen/resources.h
+++ b/engines/xeen/resources.h
@@ -327,6 +327,25 @@ extern const char *const QUICK_REF_LINE;
 
 extern const char *const QUICK_REFERENCE;
 
+extern const uint BLACKSMITH_MAP_IDS[2][4];
+
+extern char *const ITEMS_DIALOG_TEXT1;
+extern char *const ITEMS_DIALOG_TEXT2;
+
+extern const char *const BTN_BUY;
+extern const char *const BTN_SELL;
+extern const char *const BTN_IDENTIFY;
+extern const char *const BTN_FIX;
+extern const char *const BTN_USE;
+extern const char *const BTN_EQUIP;
+extern const char *const BTN_REMOVE;
+extern const char *const BTN_DISCARD;
+extern const char *const BTN_EQUIP;
+extern const char *const BTN_QUEST;
+extern const char *const BTN_ENCHANT;
+extern const char *const BTN_RECHARGE;
+extern const char *const BTN_GOLD;
+
 } // End of namespace Xeen
 
 #endif	/* XEEN_RESOURCES_H */
diff --git a/engines/xeen/scripts.cpp b/engines/xeen/scripts.cpp
index 3ba6329..12fe2f1 100644
--- a/engines/xeen/scripts.cpp
+++ b/engines/xeen/scripts.cpp
@@ -623,8 +623,8 @@ void Scripts::cmdConfirmWord(Common::Array<byte> &params) {
 			if (result == 59 && !_vm->_files->_isDarkCc) {
 				for (int idx = 0; idx < TOTAL_ITEMS; ++idx) {
 					XeenItem &item = _vm->_treasure._weapons[idx];
-					if (!item._name) {
-						item._name = 34;
+					if (!item._id) {
+						item._id = 34;
 						item._material = 0;
 						item._bonusFlags = 0;
 						_vm->_treasure._hasItems = true;
@@ -1007,22 +1007,22 @@ bool Scripts::ifProc(int action, uint32 mask, int mode, int charIndex) {
 		if (mask < 82) {
 			for (int idx = 0; idx < 9; ++idx) {
 				if (mask == 35) {
-					if (ps._weapons[idx]._name == mask) {
+					if (ps._weapons[idx]._id == mask) {
 						v = mask;
 						break;
 					}
 				} else if (mask < 49) {
-					if (ps._armor[idx]._name == (mask - 35)) {
+					if (ps._armor[idx]._id == (mask - 35)) {
 						v = mask;
 						break;
 					}
 				} else if (mask < 60) {
-					if (ps._accessories[idx]._name == (mask - 49)) {
+					if (ps._accessories[idx]._id == (mask - 49)) {
 						v = mask;
 						break;
 					}
 				} else {
-					if (ps._misc[idx]._name == (mask - 60)) {
+					if (ps._misc[idx]._id == (mask - 60)) {
 						v = mask;
 						break;
 					}
diff --git a/engines/xeen/town.cpp b/engines/xeen/town.cpp
index 3449c2e..c5cf0b6 100644
--- a/engines/xeen/town.cpp
+++ b/engines/xeen/town.cpp
@@ -22,6 +22,7 @@
 
 #include "xeen/town.h"
 #include "xeen/dialogs_input.h"
+#include "xeen/dialogs_items.h"
 #include "xeen/dialogs_yesno.h"
 #include "xeen/dialogs_spells.h"
 #include "xeen/resources.h"
@@ -536,8 +537,8 @@ Character *Town::doBlacksmithOptions(Character *c) {
 			intf.highlightChar(_buttonValue);
 		}
 	}
-	else if (_buttonValue == Common::KEYCODE_c) {
-		c = showItems(c, 1);
+	else if (_buttonValue == Common::KEYCODE_b) {
+		c = ItemsDialog::show(_vm, c, ITEMMODE_BLACKSMITH);
 		_buttonValue = 0;
 	}
 
@@ -1190,8 +1191,4 @@ bool Town::isActive() const {
 	return _townSprites.size() > 0 && !_townSprites[0].empty();
 }
 
-Character *Town::showItems(Character *c, int v2) {
-	error("TODO: showItems");
-}
-
 } // End of namespace Xeen
diff --git a/engines/xeen/town.h b/engines/xeen/town.h
index de87f03..8f6ef15 100644
--- a/engines/xeen/town.h
+++ b/engines/xeen/town.h
@@ -95,8 +95,6 @@ private:
 	Character *doTrainingOptions(Character *c);
 
 	void depositWithdrawl(int choice);
-
-	Character *showItems(Character *c, int v2);
 public:
 	Town(XeenEngine *vm);
 


Commit: 2b8303c0d8b54ee5251296c86a320735422b62e2
    https://github.com/scummvm/scummvm/commit/2b8303c0d8b54ee5251296c86a320735422b62e2
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-02-02T18:20:27-05:00

Commit Message:
XEEN: Implemented assembleItemName method

Changed paths:
    engines/xeen/items.h
    engines/xeen/party.cpp
    engines/xeen/party.h
    engines/xeen/resources.cpp
    engines/xeen/resources.h
    engines/xeen/town.cpp



diff --git a/engines/xeen/items.h b/engines/xeen/items.h
index 154fd21..943b187 100644
--- a/engines/xeen/items.h
+++ b/engines/xeen/items.h
@@ -30,7 +30,9 @@ namespace Xeen {
 
 #define TOTAL_ITEMS 10
 
-enum BonusFlags { FLAG_CURSED = 0x40 };
+enum BonusFlags { 
+	ITEMFLAG_BONUS_MASK = 0xBF,  ITEMFLAG_CURSED = 0x40, ITEMFLAG_BROKEN = 0x80 
+};
 
 class XeenItem {
 public:
diff --git a/engines/xeen/party.cpp b/engines/xeen/party.cpp
index 0353506..2108526 100644
--- a/engines/xeen/party.cpp
+++ b/engines/xeen/party.cpp
@@ -855,6 +855,70 @@ int Character::getNumAwards() const {
 	return total;
 }
 
+/**
+ * Assembles a full lines description for a specified item for use in
+ * the Items dialog
+ */
+Common::String Character::assembleItemName(int itemIndex, int displayNum, int typeNum) {
+	Spells &spells = *Party::_vm->_spells;
+
+	switch (typeNum) {
+	case 0: {
+		// Weapons
+		XeenItem &i = _weapons[itemIndex];
+		return Common::String::format("\f%02u%s%s%s\f%02u%s%s%s", displayNum,
+			!i._bonusFlags ? spells._maeNames[i._material] : "",
+			(i._bonusFlags & ITEMFLAG_BROKEN) ? ITEM_BROKEN : "",
+			(i._bonusFlags & ITEMFLAG_CURSED) ? ITEM_CURSED : "",
+			WEAPON_NAMES[i._id],
+			!i._bonusFlags ? "" : BONUS_NAMES[i._bonusFlags & ITEMFLAG_BONUS_MASK],
+			(i._bonusFlags & (ITEMFLAG_BROKEN | ITEMFLAG_CURSED)) || 
+				!i._bonusFlags ? "\b " : ""
+		);
+	}
+
+	case 1: {
+		// Armor
+		XeenItem &i = _armor[itemIndex];
+		return Common::String::format("\f%02u%s%s%s\f%02u%s%s", displayNum,
+			!i._bonusFlags ? "" : spells._maeNames[i._material],
+			(i._bonusFlags & ITEMFLAG_BROKEN) ? ITEM_BROKEN : "",
+			(i._bonusFlags & ITEMFLAG_CURSED) ? ITEM_CURSED : "",
+			ARMOR_NAMES[i._id],
+			(i._bonusFlags & (ITEMFLAG_BROKEN | ITEMFLAG_CURSED)) ||
+				!i._bonusFlags ? "\b " : ""
+		);
+	}
+		
+	case 2: {
+		// Accessories
+		XeenItem &i = _accessories[itemIndex];
+		return Common::String::format("\f%02u%s%s%s\f%02u%s%s", displayNum,
+			!i._bonusFlags ? "" : spells._maeNames[i._material],
+			(i._bonusFlags & ITEMFLAG_BROKEN) ? ITEM_BROKEN : "",
+			(i._bonusFlags & ITEMFLAG_CURSED) ? ITEM_CURSED : "",
+			ARMOR_NAMES[i._id],
+			(i._bonusFlags & (ITEMFLAG_BROKEN | ITEMFLAG_CURSED)) ||
+				!i._bonusFlags ? "\b " : ""
+		);
+	}
+
+	case 3: {
+		// Misc
+		XeenItem &i = _misc[itemIndex];
+		return Common::String::format("\f%02u%s%s%s\f%02u%s%s", displayNum,
+			!i._bonusFlags ? "" : spells._maeNames[i._material],
+			(i._bonusFlags & ITEMFLAG_BROKEN) ? ITEM_BROKEN : "",
+			(i._bonusFlags & ITEMFLAG_CURSED) ? ITEM_CURSED : "",
+			ARMOR_NAMES[i._id],
+			(i._bonusFlags & (ITEMFLAG_BROKEN | ITEMFLAG_CURSED)) ||
+				!i._id ? "\b " : ""
+		);
+	}
+	default:
+		return "";
+	}
+}
 
 /*------------------------------------------------------------------------*/
 
diff --git a/engines/xeen/party.h b/engines/xeen/party.h
index 8285ddf..d719320 100644
--- a/engines/xeen/party.h
+++ b/engines/xeen/party.h
@@ -182,6 +182,8 @@ public:
 	int getNumSkills() const;
 
 	int getNumAwards() const;
+	
+	Common::String assembleItemName(int itemIndex, int displayNum, int typeNum);
 };
 
 class Roster: public Common::Array<Character> {
diff --git a/engines/xeen/resources.cpp b/engines/xeen/resources.cpp
index d89d2e6..89f6c8a 100644
--- a/engines/xeen/resources.cpp
+++ b/engines/xeen/resources.cpp
@@ -1008,5 +1008,37 @@ const char *const BTN_ENCHANT = "E\fdnchant";
 const char *const BTN_RECHARGE = "R\fdechrg";
 const char *const BTN_GOLD = "G\fdold";
 
+const char *const ITEM_BROKEN = "\f32broken ";
+const char *const ITEM_CURSED = "\f09cursed ";
+const char *const BONUS_NAMES[7] = {
+	"", "Dragon Slayer", "Undead Eater", "Golem Smasher",
+	"Bug Zapper", "Monster Masher", "Beast Bopper"
+};
+const char *const WEAPON_NAMES[35] = {
+	nullptr, "long sword ", "short sword ", "broad sword ", "scimitar ", 
+	"cutlass ", "sabre ", "club ", "hand axe ", "katana ", "nunchakas ", 
+	"wakazashi ", "dagger ", "mace ", "flail ", "cudgel ", "maul ", "spear ", 
+	"bardiche ", "glaive ", "halberd ", "pike ", "flamberge ", "trident ",
+	"staff ", "hammer ", "naginata ", "battle axe ", "grand axe ", "great axe ", 
+	"short bow ", "long bow ", "crossbow ", "sling ", "Xeen Slayer Sword"
+};
+
+const char *const ARMOR_NAMES[14] = {
+	nullptr, "Robes ", "Scale rmor ", "ring mail ", "chain mail ",
+	"splint mail ", "plate mail ", "plate armor ", "shield ",
+	"helm ", "boots ", "cloak ", "cape ", "gauntlets "
+};
+
+const char *const ACCESSORY_NAMES[11] = {
+	nullptr, "ring ", "belt ", "broach ", "medal ", "charm ", "cameo ",
+	"scarab ", "pendant ", "necklace ", "amulet "
+};
+
+const char *const MISC_NAMES[22] = {
+	nullptr, "rod ", "jewel ", "gem ", "box ", "orb ", "horn ", "coin ",
+	"wand ", "whistle ", "potion ", "scroll ", "RogueVM", 
+	"bogus", "bogus", "bogus", "bogus", "bogus", 
+	"bogus", "bogus", "bogus", "bogus"
+};
 
 } // End of namespace Xeen
diff --git a/engines/xeen/resources.h b/engines/xeen/resources.h
index 5437d40..4b08615 100644
--- a/engines/xeen/resources.h
+++ b/engines/xeen/resources.h
@@ -346,6 +346,14 @@ extern const char *const BTN_ENCHANT;
 extern const char *const BTN_RECHARGE;
 extern const char *const BTN_GOLD;
 
+extern const char *const ITEM_BROKEN;
+extern const char *const ITEM_CURSED;
+extern const char *const BONUS_NAMES[7];
+extern const char *const WEAPON_NAMES[35];
+extern const char *const ARMOR_NAMES[14];
+extern const char *const ACCESSORY_NAMES[11];
+extern const char *const MISC_NAMES[22];
+
 } // End of namespace Xeen
 
 #endif	/* XEEN_RESOURCES_H */
diff --git a/engines/xeen/town.cpp b/engines/xeen/town.cpp
index c5cf0b6..3df2685 100644
--- a/engines/xeen/town.cpp
+++ b/engines/xeen/town.cpp
@@ -863,10 +863,10 @@ Character *Town::doTempleOptions(Character *c) {
 	case Common::KEYCODE_u:
 		if (_uncurseCost && party.subtract(0, _uncurseCost, 0, WT_2)) {
 			for (int idx = 0; idx < 9; ++idx) {
-				c->_weapons[idx]._bonusFlags &= ~FLAG_CURSED;
-				c->_armor[idx]._bonusFlags &= ~FLAG_CURSED;
-				c->_accessories[idx]._bonusFlags &= ~FLAG_CURSED;
-				c->_misc[idx]._bonusFlags &= ~FLAG_CURSED;
+				c->_weapons[idx]._bonusFlags &= ~ITEMFLAG_CURSED;
+				c->_armor[idx]._bonusFlags &= ~ITEMFLAG_CURSED;
+				c->_accessories[idx]._bonusFlags &= ~ITEMFLAG_CURSED;
+				c->_misc[idx]._bonusFlags &= ~ITEMFLAG_CURSED;
 			}
 
 			_v1 = 1440;


Commit: 3767f316195940bbe02a3f10e7139f0267197ce8
    https://github.com/scummvm/scummvm/commit/3767f316195940bbe02a3f10e7139f0267197ce8
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-02-02T21:29:58-05:00

Commit Message:
XEEN: Implemented calcItemCost

Changed paths:
    engines/xeen/dialogs_items.cpp
    engines/xeen/dialogs_items.h
    engines/xeen/resources.cpp
    engines/xeen/resources.h



diff --git a/engines/xeen/dialogs_items.cpp b/engines/xeen/dialogs_items.cpp
index fea0432..6777877 100644
--- a/engines/xeen/dialogs_items.cpp
+++ b/engines/xeen/dialogs_items.cpp
@@ -94,8 +94,9 @@ Character *ItemsDialog::execute(Character *c, ItemsMode mode) {
 			drawButtons(&screen);
 		}
 
+		Common::StringArray lines;
 		int arr[40];
-		Common::fill(&arr[0], &arr[40], false);
+		Common::fill(&arr[0], &arr[40], 0);
 		int var2 = -1;
 	
 		if (mode == ITEMMODE_CHAR_INFO || typeNum != 3) {
@@ -132,8 +133,20 @@ Character *ItemsDialog::execute(Character *c, ItemsMode mode) {
 				if (c->_weapons[idx]._id) {
 					if (mode == ITEMMODE_CHAR_INFO || mode == ITEMMODE_8
 							|| mode == ITEMMODE_6 || mode == ITEMMODE_4) {
-						// TODO
+						lines.push_back(Common::String::format(ITEMS_DIALOG_LINE1, 
+							arr[idx], idx + 1,
+							c->assembleItemName(idx, arr[idx], typeNum)));
+					} else {
+						lines.push_back(Common::String::format(ITEMS_DIALOG_LINE2,
+							arr[idx], idx + 1,
+							c->assembleItemName(idx, arr[idx], typeNum),
+							calcItemCost(c, idx, mode,
+								mode == ITEMMODE_TO_GOLD ? 1 : c->_skills[MERCHANT],
+								typeNum)
+						));
 					}
+
+					// TODO
 				} else if (_itemsDrawList[idx]._sprites == nullptr) {
 					// TODO
 				}
@@ -289,4 +302,112 @@ void ItemsDialog::setEquipmentIcons() {
 	}
 }
 
+/**
+ * Calculate the cost of an item
+ */
+int ItemsDialog::calcItemCost(Character *c, int itemIndex, int mode,
+		int skillLevel, int typeNum) {
+	int amount1 = 0, amount2 = 0, amount3 = 0, amount4 = 0;
+	int result = 0;
+	int level = skillLevel & 0x7f;
+
+	switch (mode) {
+	case ITEMMODE_BLACKSMITH:
+		level = 0;
+		break;
+	case ITEMMODE_2:
+	case ITEMMODE_TO_GOLD:
+		level = level == 0 ? 1 : 0;
+		break;
+	case ITEMMODE_10:
+		level = 2;
+		break;
+	case ITEMMODE_9:
+		level = 3;
+		break;
+	default:
+		break;
+	}
+	
+	switch (typeNum) {
+	case 0:
+	case 1:
+	case 2: {
+		// 0=Weapons, 1=Armor, 2=Accessories
+		XeenItem &i = (mode == 0) ? c->_weapons[itemIndex] :
+			(mode == 1 ? c->_armor[itemIndex] : c->_accessories[itemIndex]);
+		amount1 = (mode == 0) ? WEAPON_BASE_COSTS[i._id] :
+			(mode == 1 ? ARMOR_BASE_COSTS[i._id] : ACCESSORY_BASE_COSTS[i._id]);
+		
+		if (i._material > 36 && i._material < 59) {
+			switch (i._material) {
+			case 37:
+				amount1 /= 10;
+				break;
+			case 38:
+				amount1 /= 4;
+				break;
+			case 39:
+				amount1 /= 2;
+				break;
+			case 40:
+				amount1 /= 4;
+				break;
+			default:
+				amount1 *= METAL_BASE_MULTIPLIERS[i._material - 37];
+				break;
+			}
+		}
+
+		if (i._material < 37)
+			amount2 = ELEMENTAL_DAMAGE[i._material] * 100;
+		else if (i._material > 58)
+			amount3 = METAL_BASE_MULTIPLIERS[i._material] * 100;
+		
+		switch (mode) {
+		case ITEMMODE_BLACKSMITH:
+		case ITEMMODE_2:
+		case ITEMMODE_9:
+		case ITEMMODE_10:
+		case ITEMMODE_TO_GOLD:
+			result = (amount1 + amount2 + amount3 + amount4) / ITEM_SKILL_DIVISORS[level];
+			if (!result)
+				result = 1;
+			break;
+		default:
+			break;
+		}
+		break;
+	}
+
+	case 3: {
+		// Misc
+		XeenItem &i = c->_misc[itemIndex];
+		amount1 = MISC_MATERIAL_COSTS[i._material];
+		amount4 = MISC_BASE_COSTS[i._id];
+		
+		switch (mode) {
+		case ITEMMODE_BLACKSMITH:
+		case ITEMMODE_2:
+		case ITEMMODE_9:
+		case ITEMMODE_10:
+		case ITEMMODE_TO_GOLD:
+			result = (amount1 + amount2 + amount3 + amount4) / ITEM_SKILL_DIVISORS[level];
+			if (!result)
+				result = 1;
+			break;
+		default:
+			break;
+		}
+		break;
+	}
+
+	default:
+		break;
+	}
+
+	return (mode == ITEMMODE_CHAR_INFO) ? 0 : result;
+}
+
+
 } // End of namespace Xeen
diff --git a/engines/xeen/dialogs_items.h b/engines/xeen/dialogs_items.h
index 100ac5c..1259b25 100644
--- a/engines/xeen/dialogs_items.h
+++ b/engines/xeen/dialogs_items.h
@@ -30,8 +30,8 @@
 namespace Xeen {
 
 enum ItemsMode {
-	ITEMMODE_CHAR_INFO = 0, ITEMMODE_BLACKSMITH = 1, ITEMMODE_4 = 4, 
-	ITEMMODE_6 = 6, ITEMMODE_COMBAT = 7, ITEMMODE_8 = 8, 
+	ITEMMODE_CHAR_INFO = 0, ITEMMODE_BLACKSMITH = 1, ITEMMODE_2 = 2,
+	ITEMMODE_4 = 4, ITEMMODE_6 = 6, ITEMMODE_COMBAT = 7, ITEMMODE_8 = 8, 
 	ITEMMODE_9 = 9, ITEMMODE_10 = 10, ITEMMODE_TO_GOLD = 11
 };
 
@@ -54,6 +54,8 @@ private:
 	void blackData2CharData();
 
 	void setEquipmentIcons();
+
+	int calcItemCost(Character *c, int itemIndex, int mode, int skillLevel, int typeNum);
 public:
 	static Character *show(XeenEngine *vm, Character *c, ItemsMode mode);
 };
diff --git a/engines/xeen/resources.cpp b/engines/xeen/resources.cpp
index 89f6c8a..b856baa 100644
--- a/engines/xeen/resources.cpp
+++ b/engines/xeen/resources.cpp
@@ -986,14 +986,15 @@ const char *const QUICK_REFERENCE =
 
 const uint BLACKSMITH_MAP_IDS[2][4] = { { 28, 30, 73, 49 }, { 29, 31, 37, 43 } };
 
-char *const ITEMS_DIALOG_TEXT1 =
+const char *const ITEMS_DIALOG_TEXT1 =
 	"\r\x2\x3""c\v021\t017\f37W\fdeap\t051\f37A\fdrmor\t085A"
 	"\f37c\fdces\t119\f37M\fdisc\t153%s\t187%s\t221%s"
 	"\t255%s\t289Exit";
-
-char *const ITEMS_DIALOG_TEXT2 =
+const char *const ITEMS_DIALOG_TEXT2 =
 	"\r\x2\x3""c\v021\t017\f37W\fdeap\t051\f37A\fdrmor\t085A"
 	"\f37c\fdces\t119\f37M\fdisc\t153\f37%s\t289Exit";
+const char *const ITEMS_DIALOG_LINE1 = "\x3r\f%02u\f023%2d)\x3l\t028%s\n";
+const char *const ITEMS_DIALOG_LINE2 = "\x3r\f%02u\t023%2d)\x3l\t028%s\x3r\t000%lu\n";
 
 const char *const BTN_BUY = "\f37B\fduy";
 const char *const BTN_SELL = "\f37S\fdell";
@@ -1037,8 +1038,38 @@ const char *const ACCESSORY_NAMES[11] = {
 const char *const MISC_NAMES[22] = {
 	nullptr, "rod ", "jewel ", "gem ", "box ", "orb ", "horn ", "coin ",
 	"wand ", "whistle ", "potion ", "scroll ", "RogueVM", 
-	"bogus", "bogus", "bogus", "bogus", "bogus", 
+	"bogusg", "bogus", "bogus", "bogus", "bogus", 
 	"bogus", "bogus", "bogus", "bogus"
 };
 
+const int WEAPON_BASE_COSTS[35] = {
+	0, 50, 15, 100, 80, 40, 60, 1, 10, 150, 30, 60, 8, 50,
+	100, 15, 30, 15, 200, 80, 250, 150, 400, 100, 40, 120,
+	300, 100, 200, 300, 25, 100, 50, 15, 0
+};
+const int ARMOR_BASE_COSTS[25] = {
+	0, 20, 100, 200, 400, 600, 1000, 2000, 100, 60, 40, 250, 200, 100
+};
+const int ACCESSORY_BASE_COSTS[11] = {
+	0, 100, 100, 250, 100, 50, 300, 200, 500, 1000, 2000
+};
+const int MISC_MATERIAL_COSTS[22] = {
+	0, 50, 1000, 500, 10, 100, 20, 10, 50, 10, 10, 100,
+	1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+};
+const int MISC_BASE_COSTS[76] = {
+	0, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100,
+	100, 100, 100, 100, 200, 200, 200, 200, 200, 200, 200, 200,
+	200, 200, 200, 200, 200, 200, 200, 300, 300, 300, 300, 300,
+	300, 300, 300, 300, 300, 400, 400, 400, 400, 400, 400, 400,
+	400, 400, 400, 500, 500, 500, 500, 500, 500, 500, 500, 500,
+	500, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600,
+	600, 600, 600, 600
+};
+const int METAL_BASE_MULTIPLIERS[22] = {
+	10, 25, 5, 75, 2, 5, 10, 20, 50, 2, 3, 5, 10, 20, 30, 40,
+	50, 60, 70, 80, 90, 100
+};
+const int ITEM_SKILL_DIVISORS[4] = { 1, 2, 100, 10 };
+
 } // End of namespace Xeen
diff --git a/engines/xeen/resources.h b/engines/xeen/resources.h
index 4b08615..4dae93e 100644
--- a/engines/xeen/resources.h
+++ b/engines/xeen/resources.h
@@ -329,8 +329,10 @@ extern const char *const QUICK_REFERENCE;
 
 extern const uint BLACKSMITH_MAP_IDS[2][4];
 
-extern char *const ITEMS_DIALOG_TEXT1;
-extern char *const ITEMS_DIALOG_TEXT2;
+extern const char *const ITEMS_DIALOG_TEXT1;
+extern const char *const ITEMS_DIALOG_TEXT2;
+extern const char *const ITEMS_DIALOG_LINE1;
+extern const char *const ITEMS_DIALOG_LINE2;
 
 extern const char *const BTN_BUY;
 extern const char *const BTN_SELL;
@@ -354,6 +356,14 @@ extern const char *const ARMOR_NAMES[14];
 extern const char *const ACCESSORY_NAMES[11];
 extern const char *const MISC_NAMES[22];
 
+extern const int WEAPON_BASE_COSTS[35];
+extern const int ARMOR_BASE_COSTS[25];
+extern const int ACCESSORY_BASE_COSTS[11];
+extern const int MISC_MATERIAL_COSTS[22];
+extern const int MISC_BASE_COSTS[76];
+extern const int METAL_BASE_MULTIPLIERS[22];
+extern const int ITEM_SKILL_DIVISORS[4];
+
 } // End of namespace Xeen
 
 #endif	/* XEEN_RESOURCES_H */


Commit: 38df23ace070902d5808e77a7260f5d62ef88108
    https://github.com/scummvm/scummvm/commit/38df23ace070902d5808e77a7260f5d62ef88108
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-02-02T22:11:08-05:00

Commit Message:
XEEN: Implemented passRestrictions

Changed paths:
    engines/xeen/dialogs_items.cpp
    engines/xeen/dialogs_items.h
    engines/xeen/items.h
    engines/xeen/party.cpp
    engines/xeen/party.h
    engines/xeen/resources.cpp
    engines/xeen/resources.h



diff --git a/engines/xeen/dialogs_items.cpp b/engines/xeen/dialogs_items.cpp
index 6777877..511c27d 100644
--- a/engines/xeen/dialogs_items.cpp
+++ b/engines/xeen/dialogs_items.cpp
@@ -41,7 +41,8 @@ Character *ItemsDialog::execute(Character *c, ItemsMode mode) {
 	Screen &screen = *_vm->_screen;
 	
 	Character *tempChar = c;
-	int typeNum = mode == ITEMMODE_4 || mode == ITEMMODE_COMBAT ? 3 : 0;
+	ItemCategory category = mode == ITEMMODE_4 || mode == ITEMMODE_COMBAT ? 
+		CATEGORY_MISC : CATEGORY_WEAPON;
 	int varA = mode == ITEMMODE_COMBAT ? 1 : 0;
 	if (varA != 0)
 		mode = ITEMMODE_CHAR_INFO;
@@ -56,7 +57,7 @@ Character *ItemsDialog::execute(Character *c, ItemsMode mode) {
 	bool redrawFlag = true;
 	while (!_vm->shouldQuit()) {
 		if (redrawFlag) {
-			if ((mode != ITEMMODE_CHAR_INFO || typeNum != 3) && mode != ITEMMODE_6
+			if ((mode != ITEMMODE_CHAR_INFO || category != CATEGORY_MISC) && mode != ITEMMODE_6
 					&& mode != ITEMMODE_4 && mode != ITEMMODE_TO_GOLD) {
 				_buttons[8]._bounds.moveTo(148, _buttons[8]._bounds.top);
 				_buttons[9]._draw = false;
@@ -80,7 +81,7 @@ Character *ItemsDialog::execute(Character *c, ItemsMode mode) {
 					BTN_SELL, BTN_IDENTIFY, BTN_FIX);
 			} else if (mode != ITEMMODE_6  && mode != ITEMMODE_4 && mode != ITEMMODE_TO_GOLD) {
 				msg = Common::String::format(ITEMS_DIALOG_TEXT1,
-					typeNum == 3 ? BTN_USE : BTN_EQUIP, 
+					category == 3 ? BTN_USE : BTN_EQUIP, 
 					BTN_REMOVE, BTN_DISCARD, BTN_QUEST);
 			} else if (mode == ITEMMODE_6) {
 				msg = Common::String::format(ITEMS_DIALOG_TEXT2, BTN_ENCHANT);
@@ -99,7 +100,7 @@ Character *ItemsDialog::execute(Character *c, ItemsMode mode) {
 		Common::fill(&arr[0], &arr[40], 0);
 		int var2 = -1;
 	
-		if (mode == ITEMMODE_CHAR_INFO || typeNum != 3) {
+		if (mode == ITEMMODE_CHAR_INFO || category != 3) {
 			_iconSprites.draw(screen, 8, Common::Point(148, 109));
 		}
 		if (mode != ITEMMODE_6 && mode != ITEMMODE_4 && mode != ITEMMODE_TO_GOLD) {
@@ -128,21 +129,21 @@ Character *ItemsDialog::execute(Character *c, ItemsMode mode) {
 		for (int idx = 0; idx < 9; ++idx) {
 			_itemsDrawList[idx]._y = 10 + idx * 9;
 
-			switch (typeNum) {
-			case 0:
+			switch (category) {
+			case CATEGORY_WEAPON:
 				if (c->_weapons[idx]._id) {
 					if (mode == ITEMMODE_CHAR_INFO || mode == ITEMMODE_8
 							|| mode == ITEMMODE_6 || mode == ITEMMODE_4) {
 						lines.push_back(Common::String::format(ITEMS_DIALOG_LINE1, 
 							arr[idx], idx + 1,
-							c->assembleItemName(idx, arr[idx], typeNum)));
+							c->assembleItemName(idx, arr[idx], category)));
 					} else {
 						lines.push_back(Common::String::format(ITEMS_DIALOG_LINE2,
 							arr[idx], idx + 1,
-							c->assembleItemName(idx, arr[idx], typeNum),
+							c->assembleItemName(idx, arr[idx], category),
 							calcItemCost(c, idx, mode,
 								mode == ITEMMODE_TO_GOLD ? 1 : c->_skills[MERCHANT],
-								typeNum)
+								category)
 						));
 					}
 
@@ -306,7 +307,7 @@ void ItemsDialog::setEquipmentIcons() {
  * Calculate the cost of an item
  */
 int ItemsDialog::calcItemCost(Character *c, int itemIndex, int mode,
-		int skillLevel, int typeNum) {
+		int skillLevel, ItemCategory category) {
 	int amount1 = 0, amount2 = 0, amount3 = 0, amount4 = 0;
 	int result = 0;
 	int level = skillLevel & 0x7f;
@@ -329,10 +330,10 @@ int ItemsDialog::calcItemCost(Character *c, int itemIndex, int mode,
 		break;
 	}
 	
-	switch (typeNum) {
-	case 0:
-	case 1:
-	case 2: {
+	switch (category) {
+	case CATEGORY_WEAPON:
+	case CATEGORY_ARMOR:
+	case CATEGORY_ACCESSORY: {
 		// 0=Weapons, 1=Armor, 2=Accessories
 		XeenItem &i = (mode == 0) ? c->_weapons[itemIndex] :
 			(mode == 1 ? c->_armor[itemIndex] : c->_accessories[itemIndex]);
@@ -409,5 +410,54 @@ int ItemsDialog::calcItemCost(Character *c, int itemIndex, int mode,
 	return (mode == ITEMMODE_CHAR_INFO) ? 0 : result;
 }
 
+bool ItemsDialog::passRestrictions(CharacterClass charClass, int itemId, 
+		bool showError, ItemCategory category) const {
+	switch (charClass) {
+	case CLASS_KNIGHT:
+	case CLASS_PALADIN:
+		return true;
+
+	case CLASS_ARCHER:
+	case CLASS_CLERIC:
+	case CLASS_SORCERER:
+	case CLASS_ROBBER:
+	case CLASS_NINJA:
+	case CLASS_BARBARIAN:
+	case CLASS_DRUID:
+	case CLASS_RANGER: {
+		if (!(ITEM_RESTRICTIONS[itemId + RESTRICTION_OFFSETS[category]] &
+				(1 << (charClass - CLASS_ARCHER))))
+			return true;
+		break;
+	}
+
+	default:
+		break;
+	}
+	
+	Common::String name;
+	switch (category) {
+	case CATEGORY_WEAPON:
+		name = WEAPON_NAMES[itemId];
+		break;
+	case CATEGORY_ARMOR:
+		name = ARMOR_NAMES[itemId];
+		break;
+	case CATEGORY_ACCESSORY:
+		name = ACCESSORY_NAMES[itemId];
+		break;
+	case CATEGORY_MISC:
+		name = MISC_NAMES[itemId];
+		break;
+	}
+
+	if (showError) {
+		Common::String msg = Common::String::format(NOT_PROFICIENT, 
+			CLASS_NAMES[charClass], name.c_str());
+		ErrorScroll::show(_vm, msg, WT_FREEZE_WAIT);
+	}
+
+	return false;
+}
 
 } // End of namespace Xeen
diff --git a/engines/xeen/dialogs_items.h b/engines/xeen/dialogs_items.h
index 1259b25..74be921 100644
--- a/engines/xeen/dialogs_items.h
+++ b/engines/xeen/dialogs_items.h
@@ -55,7 +55,11 @@ private:
 
 	void setEquipmentIcons();
 
-	int calcItemCost(Character *c, int itemIndex, int mode, int skillLevel, int typeNum);
+	int calcItemCost(Character *c, int itemIndex, int mode, int skillLevel, 
+		ItemCategory category);
+
+	bool passRestrictions(CharacterClass charClass, int itemId,
+		bool showError, ItemCategory category) const;
 public:
 	static Character *show(XeenEngine *vm, Character *c, ItemsMode mode);
 };
diff --git a/engines/xeen/items.h b/engines/xeen/items.h
index 943b187..bfc7608 100644
--- a/engines/xeen/items.h
+++ b/engines/xeen/items.h
@@ -34,6 +34,10 @@ enum BonusFlags {
 	ITEMFLAG_BONUS_MASK = 0xBF,  ITEMFLAG_CURSED = 0x40, ITEMFLAG_BROKEN = 0x80 
 };
 
+enum ItemCategory {
+	CATEGORY_WEAPON = 0, CATEGORY_ARMOR = 1, CATEGORY_ACCESSORY = 2, CATEGORY_MISC = 3
+};
+
 class XeenItem {
 public:
 	int _material;
diff --git a/engines/xeen/party.cpp b/engines/xeen/party.cpp
index 2108526..2590abc 100644
--- a/engines/xeen/party.cpp
+++ b/engines/xeen/party.cpp
@@ -859,11 +859,12 @@ int Character::getNumAwards() const {
  * Assembles a full lines description for a specified item for use in
  * the Items dialog
  */
-Common::String Character::assembleItemName(int itemIndex, int displayNum, int typeNum) {
+Common::String Character::assembleItemName(int itemIndex, int displayNum, 
+		ItemCategory category) {
 	Spells &spells = *Party::_vm->_spells;
 
-	switch (typeNum) {
-	case 0: {
+	switch (category) {
+	case CATEGORY_WEAPON: {
 		// Weapons
 		XeenItem &i = _weapons[itemIndex];
 		return Common::String::format("\f%02u%s%s%s\f%02u%s%s%s", displayNum,
@@ -877,7 +878,7 @@ Common::String Character::assembleItemName(int itemIndex, int displayNum, int ty
 		);
 	}
 
-	case 1: {
+	case CATEGORY_ARMOR: {
 		// Armor
 		XeenItem &i = _armor[itemIndex];
 		return Common::String::format("\f%02u%s%s%s\f%02u%s%s", displayNum,
@@ -890,7 +891,7 @@ Common::String Character::assembleItemName(int itemIndex, int displayNum, int ty
 		);
 	}
 		
-	case 2: {
+	case CATEGORY_ACCESSORY: {
 		// Accessories
 		XeenItem &i = _accessories[itemIndex];
 		return Common::String::format("\f%02u%s%s%s\f%02u%s%s", displayNum,
@@ -903,7 +904,7 @@ Common::String Character::assembleItemName(int itemIndex, int displayNum, int ty
 		);
 	}
 
-	case 3: {
+	case CATEGORY_MISC: {
 		// Misc
 		XeenItem &i = _misc[itemIndex];
 		return Common::String::format("\f%02u%s%s%s\f%02u%s%s", displayNum,
diff --git a/engines/xeen/party.h b/engines/xeen/party.h
index d719320..6f70c4b 100644
--- a/engines/xeen/party.h
+++ b/engines/xeen/party.h
@@ -183,7 +183,7 @@ public:
 
 	int getNumAwards() const;
 	
-	Common::String assembleItemName(int itemIndex, int displayNum, int typeNum);
+	Common::String assembleItemName(int itemIndex, int displayNum, ItemCategory category);
 };
 
 class Roster: public Common::Array<Character> {
diff --git a/engines/xeen/resources.cpp b/engines/xeen/resources.cpp
index b856baa..3935104 100644
--- a/engines/xeen/resources.cpp
+++ b/engines/xeen/resources.cpp
@@ -1072,4 +1072,17 @@ const int METAL_BASE_MULTIPLIERS[22] = {
 };
 const int ITEM_SKILL_DIVISORS[4] = { 1, 2, 100, 10 };
 
+const int RESTRICTION_OFFSETS[4] = { 0, 35, 49, 60 };
+
+const int ITEM_RESTRICTIONS[86] = {
+	0, 86, 86, 86, 86, 86, 86, 0, 6, 239, 239, 239, 2, 4, 4, 4, 4, 
+	6, 70, 70, 70, 70, 94, 70, 0, 4, 239, 86, 86, 86, 70, 70, 70, 70, 
+	0, 0, 0, 68, 100, 116, 125, 255, 255, 85, 0, 0, 0, 0, 0, 0, 0, 0, 
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+const char *const NOT_PROFICIENT =
+	"\t000\v007\x3""c%ss are not proficient with a %s!";
+
 } // End of namespace Xeen
diff --git a/engines/xeen/resources.h b/engines/xeen/resources.h
index 4dae93e..bcd4dae 100644
--- a/engines/xeen/resources.h
+++ b/engines/xeen/resources.h
@@ -364,6 +364,11 @@ extern const int MISC_BASE_COSTS[76];
 extern const int METAL_BASE_MULTIPLIERS[22];
 extern const int ITEM_SKILL_DIVISORS[4];
 
+extern const int RESTRICTION_OFFSETS[4];
+extern const int ITEM_RESTRICTIONS[86];
+
+extern const char *const NOT_PROFICIENT;
+
 } // End of namespace Xeen
 
 #endif	/* XEEN_RESOURCES_H */


Commit: f34c5ad9b65f626884736faf802d627dc2fe68c0
    https://github.com/scummvm/scummvm/commit/f34c5ad9b65f626884736faf802d627dc2fe68c0
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-02-02T22:38:16-05:00

Commit Message:
XEEN: Finished Items dailog loading block for weapons

Changed paths:
    engines/xeen/dialogs_items.cpp
    engines/xeen/items.cpp
    engines/xeen/items.h
    engines/xeen/party.cpp
    engines/xeen/resources.cpp
    engines/xeen/resources.h



diff --git a/engines/xeen/dialogs_items.cpp b/engines/xeen/dialogs_items.cpp
index 511c27d..1043be8 100644
--- a/engines/xeen/dialogs_items.cpp
+++ b/engines/xeen/dialogs_items.cpp
@@ -147,9 +147,14 @@ Character *ItemsDialog::execute(Character *c, ItemsMode mode) {
 						));
 					}
 
-					// TODO
+					DrawStruct &ds = _itemsDrawList[idx];
+					ds._sprites = &_equipSprites;
+					if (passRestrictions(c->_class, c->_weapons[idx]._id, true, CATEGORY_WEAPON))
+						ds._frame = c->_weapons[idx]._frame;
+					else
+						ds._frame = 14;
 				} else if (_itemsDrawList[idx]._sprites == nullptr) {
-					// TODO
+					lines.push_back(NO_ITEMS_AVAILABLE);
 				}
 				break;
 				// TODO
@@ -260,26 +265,26 @@ void ItemsDialog::setEquipmentIcons() {
 			case 0: {
 				XeenItem &i = _itemsCharacter._weapons[idx];
 				if (i._id <= 17)
-					i._equipped = 1;
+					i._frame = 1;
 				else if (i._id <= 29 || i._id > 33)
-					i._equipped = 13;
+					i._frame = 13;
 				else
-					i._equipped = 4;
+					i._frame = 4;
 				break;
 			}
 
 			case 1: {
 				XeenItem &i = _itemsCharacter._armor[idx];
 				if (i._id <= 7)
-					i._equipped = 3;
+					i._frame = 3;
 				else if (i._id == 9)
-					i._equipped = 5;
+					i._frame = 5;
 				else if (i._id == 10)
-					i._equipped = 9;
+					i._frame = 9;
 				else if (i._id <= 12)
-					i._equipped = 10;
+					i._frame = 10;
 				else
-					i._equipped = 6;
+					i._frame = 6;
 				break;
 			}
 
@@ -288,11 +293,11 @@ void ItemsDialog::setEquipmentIcons() {
 				if (i._id == 1)
 					i._id = 8;
 				else if (i._id == 2)
-					i._equipped = 12;
+					i._frame = 12;
 				else if (i._id <= 7)
-					i._equipped = 7;
+					i._frame = 7;
 				else
-					i._equipped = 11;
+					i._frame = 11;
 				break;
 			}
 			
@@ -410,6 +415,9 @@ int ItemsDialog::calcItemCost(Character *c, int itemIndex, int mode,
 	return (mode == ITEMMODE_CHAR_INFO) ? 0 : result;
 }
 
+/**
+ * Return whether a given item passes class-based usage restrictions
+ */
 bool ItemsDialog::passRestrictions(CharacterClass charClass, int itemId, 
 		bool showError, ItemCategory category) const {
 	switch (charClass) {
diff --git a/engines/xeen/items.cpp b/engines/xeen/items.cpp
index fd06af1..5881fb3 100644
--- a/engines/xeen/items.cpp
+++ b/engines/xeen/items.cpp
@@ -27,14 +27,14 @@ namespace Xeen {
 
 XeenItem::XeenItem() {
 	_material = _id = _bonusFlags = 0;
-	_equipped = 0;
+	_frame = 0;
 }
 
 void XeenItem::synchronize(Common::Serializer &s) {
 	s.syncAsByte(_material);
 	s.syncAsByte(_id);
 	s.syncAsByte(_bonusFlags);
-	s.syncAsByte(_equipped);
+	s.syncAsByte(_frame);
 }
 
 int XeenItem::getElementalCategory() const {
diff --git a/engines/xeen/items.h b/engines/xeen/items.h
index bfc7608..5a8c4d7 100644
--- a/engines/xeen/items.h
+++ b/engines/xeen/items.h
@@ -43,7 +43,7 @@ public:
 	int _material;
 	uint _id;
 	int _bonusFlags;
-	int _equipped;
+	int _frame;
 public:
 	XeenItem();
 
diff --git a/engines/xeen/party.cpp b/engines/xeen/party.cpp
index 2590abc..0a276b2 100644
--- a/engines/xeen/party.cpp
+++ b/engines/xeen/party.cpp
@@ -452,7 +452,7 @@ int Character::itemScan(int itemId) const {
 			for (int idx = 0; idx < INV_ITEMS_TOTAL; ++idx) {
 				const XeenItem &item = _weapons[idx];
 
-				if (item._equipped && !(item._bonusFlags & 0xC0) && itemId < 11
+				if (item._frame && !(item._bonusFlags & 0xC0) && itemId < 11
 						&& itemId != 3 && item._material >= 59 && item._material <= 130) {
 					int mIndex = item.getAttributeCategory();
 					if (mIndex > 2)
@@ -468,7 +468,7 @@ int Character::itemScan(int itemId) const {
 			for (int idx = 0; idx < INV_ITEMS_TOTAL; ++idx) {
 				const XeenItem &item = _armor[idx];
 
-				if (item._equipped && !(item._bonusFlags & 0xC0)) {
+				if (item._frame && !(item._bonusFlags & 0xC0)) {
 					if (itemId < 11 && itemId != 3 && item._material >= 59 && item._material <= 130) {
 						int mIndex = item.getAttributeCategory();
 						if (mIndex > 2)
@@ -500,7 +500,7 @@ int Character::itemScan(int itemId) const {
 			for (int idx = 0; idx < INV_ITEMS_TOTAL; ++idx) {
 				const XeenItem &item = _accessories[idx];
 
-				if (item._equipped && !(item._bonusFlags & 0xC0) && itemId < 11 && itemId != 3) {
+				if (item._frame && !(item._bonusFlags & 0xC0) && itemId < 11 && itemId != 3) {
 					if (item._material >= 59 && item._material <= 130) {
 						int mIndex = item.getAttributeCategory();
 						if (mIndex > 2)
diff --git a/engines/xeen/resources.cpp b/engines/xeen/resources.cpp
index 3935104..8a23216 100644
--- a/engines/xeen/resources.cpp
+++ b/engines/xeen/resources.cpp
@@ -1085,4 +1085,7 @@ const int ITEM_RESTRICTIONS[86] = {
 const char *const NOT_PROFICIENT =
 	"\t000\v007\x3""c%ss are not proficient with a %s!";
 
+const char *const NO_ITEMS_AVAILABLE = "\x3""c\n"
+	"\t000No items available.";
+
 } // End of namespace Xeen
diff --git a/engines/xeen/resources.h b/engines/xeen/resources.h
index bcd4dae..c851db7 100644
--- a/engines/xeen/resources.h
+++ b/engines/xeen/resources.h
@@ -369,6 +369,8 @@ extern const int ITEM_RESTRICTIONS[86];
 
 extern const char *const NOT_PROFICIENT;
 
+extern const char *const NO_ITEMS_AVAILABLE;
+
 } // End of namespace Xeen
 
 #endif	/* XEEN_RESOURCES_H */


Commit: 4953b7954aca078be9655971f925f82c51e472db
    https://github.com/scummvm/scummvm/commit/4953b7954aca078be9655971f925f82c51e472db
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-02-04T19:18:51-05:00

Commit Message:
XEEN: Partial implementation of doItemOptions

Changed paths:
    engines/xeen/combat.cpp
    engines/xeen/combat.h
    engines/xeen/dialogs_char_info.cpp
    engines/xeen/dialogs_error.cpp
    engines/xeen/dialogs_error.h
    engines/xeen/dialogs_items.cpp
    engines/xeen/dialogs_items.h
    engines/xeen/interface_map.h
    engines/xeen/items.cpp
    engines/xeen/items.h
    engines/xeen/party.cpp
    engines/xeen/party.h
    engines/xeen/resources.cpp
    engines/xeen/resources.h
    engines/xeen/spells.cpp
    engines/xeen/spells.h



diff --git a/engines/xeen/combat.cpp b/engines/xeen/combat.cpp
index 6237e0c..fec244b 100644
--- a/engines/xeen/combat.cpp
+++ b/engines/xeen/combat.cpp
@@ -34,6 +34,8 @@ Combat::Combat(XeenEngine *vm): _vm(vm) {
 	Common::fill(&_elemScale[0], &_elemScale[12], 0);
 	Common::fill(&_shooting[0], &_shooting[8], 0);
 	_globalCombat = 0;
+	_whosTurn = -1;
+	_itemFlag = false;
 }
 
 void Combat::clear() {
diff --git a/engines/xeen/combat.h b/engines/xeen/combat.h
index c2554d5..ef82de5 100644
--- a/engines/xeen/combat.h
+++ b/engines/xeen/combat.h
@@ -59,6 +59,8 @@ public:
 	int _elemScale[12];
 	bool _shooting[8];
 	int _globalCombat;
+	int _whosTurn;
+	bool _itemFlag;
 public:
 	Combat(XeenEngine *vm);
 
diff --git a/engines/xeen/dialogs_char_info.cpp b/engines/xeen/dialogs_char_info.cpp
index 1d907cf..0c71bfb 100644
--- a/engines/xeen/dialogs_char_info.cpp
+++ b/engines/xeen/dialogs_char_info.cpp
@@ -185,7 +185,7 @@ void CharacterInfo::execute(int charIndex) {
 
 		case Common::KEYCODE_i:
 			_vm->_mode = oldMode;
-			_vm->_treasure._v1 = _vm->_mode == MODE_InCombat;
+			_vm->_combat->_itemFlag = _vm->_mode == MODE_InCombat;
 			c = ItemsDialog::show(_vm, c, ITEMMODE_CHAR_INFO);
 
 			if (!c) {
@@ -209,7 +209,7 @@ exit:
 	w.close();
 	intf.unhighlightChar();
 	_vm->_mode = oldMode;
-	_vm->_treasure._v1 = false;
+	_vm->_combat->_itemFlag = false;
 }
 
 /**
diff --git a/engines/xeen/dialogs_error.cpp b/engines/xeen/dialogs_error.cpp
index e851221..a58e0e9 100644
--- a/engines/xeen/dialogs_error.cpp
+++ b/engines/xeen/dialogs_error.cpp
@@ -38,7 +38,16 @@ void ErrorScroll::execute(const Common::String &msg, ErrorWaitType waitType) {
 	EventsManager &events = *_vm->_events;
 	Window &w = screen._windows[6];
 
-	Common::String s = Common::String::format("\x03c\v010\t000%s", msg.c_str());
+	Common::String s;
+	if (waitType == WT_UNFORMATTED) {
+		// This type isn't technically a waiting type, but it saved on adding 
+		// yet another parameter
+		waitType = WT_FREEZE_WAIT;
+		s = msg;
+	} else {
+		s = Common::String::format("\x03c\v010\t000%s", msg.c_str());
+	}
+
 	w.open();
 	w.writeString(s);
 	w.update();
diff --git a/engines/xeen/dialogs_error.h b/engines/xeen/dialogs_error.h
index ba36f28..1a86afc 100644
--- a/engines/xeen/dialogs_error.h
+++ b/engines/xeen/dialogs_error.h
@@ -28,7 +28,7 @@
 namespace Xeen {
 
 enum ErrorWaitType { WT_FREEZE_WAIT = 0, WT_NONFREEZED_WAIT = 1, 
-	WT_2 = 2, WT_3 = 3};
+	WT_2 = 2, WT_3 = 3, WT_UNFORMATTED = 9 };
 
 class ErrorScroll: public ButtonContainer {
 private:
diff --git a/engines/xeen/dialogs_items.cpp b/engines/xeen/dialogs_items.cpp
index 1043be8..634fb2d 100644
--- a/engines/xeen/dialogs_items.cpp
+++ b/engines/xeen/dialogs_items.cpp
@@ -40,7 +40,7 @@ Character *ItemsDialog::execute(Character *c, ItemsMode mode) {
 	Party &party = *_vm->_party;
 	Screen &screen = *_vm->_screen;
 	
-	Character *tempChar = c;
+	Character *startingChar = c;
 	ItemCategory category = mode == ITEMMODE_4 || mode == ITEMMODE_COMBAT ? 
 		CATEGORY_MISC : CATEGORY_WEAPON;
 	int varA = mode == ITEMMODE_COMBAT ? 1 : 0;
@@ -130,8 +130,13 @@ Character *ItemsDialog::execute(Character *c, ItemsMode mode) {
 			_itemsDrawList[idx]._y = 10 + idx * 9;
 
 			switch (category) {
-			case CATEGORY_WEAPON:
-				if (c->_weapons[idx]._id) {
+			case CATEGORY_WEAPON: 
+			case CATEGORY_ARMOR:
+			case CATEGORY_ACCESSORY: {
+				XeenItem &i = (category == CATEGORY_WEAPON) ? c->_weapons[idx] :
+					((category == CATEGORY_ARMOR) ? c->_armor[idx] : c->_accessories[idx]);
+
+				if (i._id) {
 					if (mode == ITEMMODE_CHAR_INFO || mode == ITEMMODE_8
 							|| mode == ITEMMODE_6 || mode == ITEMMODE_4) {
 						lines.push_back(Common::String::format(ITEMS_DIALOG_LINE1, 
@@ -142,26 +147,143 @@ Character *ItemsDialog::execute(Character *c, ItemsMode mode) {
 							arr[idx], idx + 1,
 							c->assembleItemName(idx, arr[idx], category),
 							calcItemCost(c, idx, mode,
-								mode == ITEMMODE_TO_GOLD ? 1 : c->_skills[MERCHANT],
+								mode == ITEMMODE_TO_GOLD ? 1 : startingChar->_skills[MERCHANT],
 								category)
 						));
 					}
 
 					DrawStruct &ds = _itemsDrawList[idx];
 					ds._sprites = &_equipSprites;
-					if (passRestrictions(c->_class, c->_weapons[idx]._id, true, CATEGORY_WEAPON))
-						ds._frame = c->_weapons[idx]._frame;
+					if (passRestrictions(c->_class, i._id, true, CATEGORY_WEAPON))
+						ds._frame = i._frame;
 					else
 						ds._frame = 14;
 				} else if (_itemsDrawList[idx]._sprites == nullptr) {
 					lines.push_back(NO_ITEMS_AVAILABLE);
 				}
 				break;
-				// TODO
+			}
+
+			case CATEGORY_MISC: {
+				XeenItem &i = c->_misc[idx];
+				_itemsDrawList[idx]._sprites = nullptr;
+
+				if (i._material == 0) {
+					// No item
+					if (idx == 0) {
+						lines.push_back(NO_ITEMS_AVAILABLE);
+					}
+				} else {
+					ItemsMode tempMode = mode;
+					int skill = startingChar->_skills[MERCHANT];
+
+					if (mode == ITEMMODE_CHAR_INFO || mode == ITEMMODE_8
+							|| mode == ITEMMODE_6 || mode == ITEMMODE_4) {
+						tempMode = ITEMMODE_6;
+					} else if (mode == ITEMMODE_TO_GOLD) {
+						skill = 1;
+					}
+
+					lines.push_back(Common::String::format(ITEMS_DIALOG_LINE2,
+						arr[idx], idx + 1,
+						c->assembleItemName(idx, arr[idx], category),
+						calcItemCost(c, idx, tempMode, skill, category)
+					));
+				}
+				break;
+			}
+
+			default:
+				break;
+			}
+		}
+		while (lines.size() < INV_ITEMS_TOTAL)
+			lines.push_back("");
+
+		// Draw out overall text and the list of items
+		switch (mode) {
+		case ITEMMODE_CHAR_INFO:
+		case ITEMMODE_8:
+			screen._windows[30].writeString(Common::String::format(X_FOR_THE_Y,
+				category == CATEGORY_MISC ? "\x3l" : "\x3c",
+				CATEGORY_NAMES[category], c->_name.c_str(), CLASS_NAMES[c->_class],
+				category == CATEGORY_MISC ? FMT_CHARGES : " ",
+				lines[0].c_str(), lines[1].c_str(), lines[2].c_str(), lines[3].c_str(),
+				lines[4].c_str(), lines[5].c_str(), lines[6].c_str(), lines[7].c_str(),
+				lines[8].c_str()
+			));
+
+		case ITEMMODE_BLACKSMITH: {
+			// Original uses var in this block that's never set?!
+			const int v1 = 0;
+			screen._windows[30].writeString(Common::String::format(AVAILABLE_GOLD_COST,
+				CATEGORY_NAMES[category], 
+				v1 ? "" : "s", party._gold,
+				lines[0].c_str(), lines[1].c_str(), lines[2].c_str(), lines[3].c_str(),
+				lines[4].c_str(), lines[5].c_str(), lines[6].c_str(), lines[7].c_str(),
+				lines[8].c_str()
+			));
+			break;
+		}
+
+		case ITEMMODE_2:
+		case ITEMMODE_4:
+		case ITEMMODE_6:
+		case ITEMMODE_9:
+		case ITEMMODE_10:
+		case ITEMMODE_TO_GOLD:
+			screen._windows[30].writeString(Common::String::format(X_FOR_Y,
+				CATEGORY_NAMES[category], startingChar->_name.c_str(),
+				(mode == ITEMMODE_4 || mode == ITEMMODE_6) ? CHARGES : COST,
+				lines[0].c_str(), lines[1].c_str(), lines[2].c_str(), lines[3].c_str(),
+				lines[4].c_str(), lines[5].c_str(), lines[6].c_str(), lines[7].c_str(),
+				lines[8].c_str()
+			));
+			break;
+
+		case ITEMMODE_3:
+		case ITEMMODE_5:
+			screen._windows[30].writeString(Common::String::format(X_FOR_Y_GOLD,
+				CATEGORY_NAMES[category], c->_name.c_str(), party._gold, CHARGES,
+				lines[0].c_str(), lines[1].c_str(), lines[2].c_str(), lines[3].c_str(),
+				lines[4].c_str(), lines[5].c_str(), lines[6].c_str(), lines[7].c_str(),
+				lines[8].c_str()
+				));
+			break;
+
+		default:
+			break;
+		}
+
+		// Draw the glyphs for the items
+		screen._windows[0].drawList(_itemsDrawList, INV_ITEMS_TOTAL);
+		screen._windows[0].update();
+
+		if (var2 != -1) {
+			int actionIndex = -1;
+			switch (mode) {
+			case ITEMMODE_BLACKSMITH:
+				actionIndex = 0;
+				break;
+			case ITEMMODE_2:
+				actionIndex = 1;
+				break;
+			case ITEMMODE_9:
+				actionIndex = 3;
+				break;
+			case ITEMMODE_10:
+				actionIndex = 2;
+				break;
 			default:
 				break;
 			}
+
+			if (actionIndex >= 0) {
+				doItemOptions(*c, actionIndex, var2, category, mode);
+			}
 		}
+
+		// TODO
 	}
 
 	return c;
@@ -311,7 +433,7 @@ void ItemsDialog::setEquipmentIcons() {
 /**
  * Calculate the cost of an item
  */
-int ItemsDialog::calcItemCost(Character *c, int itemIndex, int mode,
+int ItemsDialog::calcItemCost(Character *c, int itemIndex, ItemsMode mode,
 		int skillLevel, ItemCategory category) {
 	int amount1 = 0, amount2 = 0, amount3 = 0, amount4 = 0;
 	int result = 0;
@@ -468,4 +590,131 @@ bool ItemsDialog::passRestrictions(CharacterClass charClass, int itemId,
 	return false;
 }
 
+bool ItemsDialog::doItemOptions(Character &c, int actionIndex, int itemIndex, ItemCategory category,
+		ItemsMode mode) {
+	Combat &combat = *_vm->_combat;
+	EventsManager &events = *_vm->_events;
+	Interface &intf = *_vm->_interface;
+	Party &party = *_vm->_party;
+	Screen &screen = *_vm->_screen;
+	Spells &spells = *_vm->_spells;
+
+	XeenItem *itemCategories[4] = { &c._weapons[0], &c._armor[0], &c._accessories[0], &c._misc[0] };
+	XeenItem *items = itemCategories[category];
+	if (!items[0]._id)
+		return false;
+
+	Window &w = screen._windows[11];
+	SpriteResource escSprites;
+	if (itemIndex < 0 || itemIndex > 8) {
+		saveButtons();
+
+		escSprites.load("esc.icn");
+		addButton(Common::Rect(235, 111, 259, 131), Common::KEYCODE_ESCAPE, &escSprites);
+		addButton(Common::Rect(8, 20, 263, 28), Common::KEYCODE_1, &escSprites, false);
+		addButton(Common::Rect(8, 29, 263, 37), Common::KEYCODE_2, &escSprites, false);
+		addButton(Common::Rect(8, 38, 263, 46), Common::KEYCODE_3, &escSprites, false);
+		addButton(Common::Rect(8, 47, 263, 55), Common::KEYCODE_4, &escSprites, false);
+		addButton(Common::Rect(8, 56, 263, 64), Common::KEYCODE_5, &escSprites, false);
+		addButton(Common::Rect(8, 65, 263, 73), Common::KEYCODE_6, &escSprites, false);
+		addButton(Common::Rect(8, 74, 263, 82), Common::KEYCODE_7, &escSprites, false);
+		addButton(Common::Rect(8, 83, 263, 91), Common::KEYCODE_8, &escSprites, false);
+		addButton(Common::Rect(8, 92, 263, 100), Common::KEYCODE_9, &escSprites, false);
+
+		w.open();
+		w.writeString(Common::String::format(WHICH_ITEM, ITEM_ACTIONS[actionIndex]));
+		_iconSprites.draw(screen, 0, Common::Point(235, 111));
+		w.update();
+
+		while (!_vm->shouldQuit()) {
+			while (!_buttonValue) {
+				events.pollEventsAndWait();
+				checkEvents(_vm);
+				if (_vm->shouldQuit())
+					return false;
+			}
+
+			if (_buttonValue == Common::KEYCODE_ESCAPE) {
+				itemIndex = -1;
+				break;
+			} else if (_buttonValue >= Common::KEYCODE_1 && _buttonValue <= Common::KEYCODE_9) {
+				// Check whether there's an item at the selected index
+				int selectedIndex = _buttonValue - Common::KEYCODE_1;
+				if (!items[selectedIndex]._id)
+					continue;
+
+				itemIndex = selectedIndex;
+				break;
+			}
+		}
+
+		w.close();
+		restoreButtons();
+	}
+
+	if (itemIndex != -1) {
+		switch (mode) {
+		case ITEMMODE_CHAR_INFO:
+		case ITEMMODE_8:
+			switch (actionIndex) {
+			case 0:
+				c._items[category].equipItem(itemIndex);
+				break;
+			case 1:
+				c._items[category].removeItem(itemIndex);
+				break;
+			case 2:
+				if (!party._mazeId) {
+					ErrorScroll::show(_vm, WHATS_YOUR_HURRY);
+				} else {
+					XeenItem &i = c._misc[itemIndex];
+
+					Condition condition = c.worstCondition();
+					switch (condition) {
+					case SLEEP:
+					case PARALYZED:
+					case UNCONSCIOUS:
+					case DEAD:
+					case STONED:
+					case ERADICATED:
+						ErrorScroll::show(_vm, Common::String::format(IN_NO_CONDITION, c._name.c_str()));
+						break;
+					default:
+						if (combat._itemFlag) {
+							ErrorScroll::show(_vm, USE_ITEM_IN_COMBAT);
+						} else if (i._id && (i._bonusFlags & ITEMFLAG_BONUS_MASK)
+								&& !(i._bonusFlags & (ITEMFLAG_BROKEN | ITEMFLAG_CURSED))) {
+							int bonus = (i._bonusFlags & ITEMFLAG_BONUS_MASK) - 1;
+							i._bonusFlags = bonus;
+							_oldCharacter = &c;
+
+							screen._windows[30].close();
+							screen._windows[29].close();
+							screen._windows[24].close();
+							spells.doSpell(i._id);
+
+							if (!bonus) {
+								c._items[category].discardItem(itemIndex);
+							}
+						} else {
+							ErrorScroll::show(_vm, Common::String::format(NO_SPECIAL_ABILITIES,
+								c.assembleItemName(itemIndex, 15, category).c_str()
+							));
+						}
+					}
+				}
+			case 3:
+				// TODO: Remaining switches
+			default:
+				break;
+			}
+		}
+	}
+
+	intf._charsShooting = false;
+	intf.moveMonsters();
+	combat._whosTurn = -1;
+	return true;
+}
+
 } // End of namespace Xeen
diff --git a/engines/xeen/dialogs_items.h b/engines/xeen/dialogs_items.h
index 74be921..c30eaa9 100644
--- a/engines/xeen/dialogs_items.h
+++ b/engines/xeen/dialogs_items.h
@@ -30,8 +30,8 @@
 namespace Xeen {
 
 enum ItemsMode {
-	ITEMMODE_CHAR_INFO = 0, ITEMMODE_BLACKSMITH = 1, ITEMMODE_2 = 2,
-	ITEMMODE_4 = 4, ITEMMODE_6 = 6, ITEMMODE_COMBAT = 7, ITEMMODE_8 = 8, 
+	ITEMMODE_CHAR_INFO = 0, ITEMMODE_BLACKSMITH = 1, ITEMMODE_2 = 2, ITEMMODE_3 = 3,
+	ITEMMODE_4 = 4, ITEMMODE_5 = 5, ITEMMODE_6 = 6, ITEMMODE_COMBAT = 7, ITEMMODE_8 = 8, 
 	ITEMMODE_9 = 9, ITEMMODE_10 = 10, ITEMMODE_TO_GOLD = 11
 };
 
@@ -42,7 +42,7 @@ private:
 	SpriteResource _equipSprites;
 	Character _itemsCharacter;
 	Character *_oldCharacter;
-	DrawStruct _itemsDrawList[9];
+	DrawStruct _itemsDrawList[INV_ITEMS_TOTAL];
 
 	ItemsDialog(XeenEngine *vm) : ButtonContainer(), 
 		_vm(vm), _oldCharacter(nullptr) {}
@@ -55,11 +55,14 @@ private:
 
 	void setEquipmentIcons();
 
-	int calcItemCost(Character *c, int itemIndex, int mode, int skillLevel, 
+	int calcItemCost(Character *c, int itemIndex, ItemsMode mode, int skillLevel, 
 		ItemCategory category);
 
 	bool passRestrictions(CharacterClass charClass, int itemId,
 		bool showError, ItemCategory category) const;
+
+	bool doItemOptions(Character &c, int actionIndex, int itemIndex, 
+		ItemCategory category, ItemsMode mode);
 public:
 	static Character *show(XeenEngine *vm, Character *c, ItemsMode mode);
 };
diff --git a/engines/xeen/interface_map.h b/engines/xeen/interface_map.h
index fb448e1..197f239 100644
--- a/engines/xeen/interface_map.h
+++ b/engines/xeen/interface_map.h
@@ -111,7 +111,6 @@ protected:
 	bool _flipSky;
 	bool _flipDefaultGround;
 	bool _isShooting;
-	bool _charsShooting;
 	bool _thinWall;
 	bool _isAnimReset;
 	int _blessedUIFrame;
@@ -125,8 +124,6 @@ protected:
 
 	void animate3d();
 
-	void moveMonsters();
-
 	void drawMiniMap();
 
 	virtual void setup();
@@ -144,6 +141,7 @@ public:
 	int _objNumber;
 	int _overallFrame;
 	int _batUIFrame;
+	bool _charsShooting;
 public:
 	InterfaceMap(XeenEngine *vm);
 
@@ -166,6 +164,9 @@ public:
 	void drawOutdoors();
 
 	void assembleBorder();
+
+	void moveMonsters();
+
 };
 
 } // End of namespace Xeen
diff --git a/engines/xeen/items.cpp b/engines/xeen/items.cpp
index 5881fb3..1341826 100644
--- a/engines/xeen/items.cpp
+++ b/engines/xeen/items.cpp
@@ -26,6 +26,10 @@
 namespace Xeen {
 
 XeenItem::XeenItem() {
+	clear();
+}
+
+void XeenItem::clear() {
 	_material = _id = _bonusFlags = 0;
 	_frame = 0;
 }
@@ -54,9 +58,61 @@ int XeenItem::getAttributeCategory() const {
 	return idx;
 }
 
+/*------------------------------------------------------------------------*/
+
+InventoryItems::InventoryItems() : Common::Array<XeenItem>((XeenItem *)nullptr, INV_ITEMS_TOTAL) {
+}
+
+void InventoryItems::discardItem(int itemIndex) {
+	operator[](itemIndex).clear();
+	sort();
+}
+
+void InventoryItems::sort() {
+	for (uint idx = 0; idx < size(); ++idx) {
+		if (operator[](idx)._id == 0) {
+			// Found empty slot
+			operator[](idx).clear();
+
+			// Scan through the rest of the list to find any item
+			for (uint idx2 = idx + 1; idx2 < size(); ++idx2) {
+				if (operator[](idx2)._id) {
+					// Found an item, so move it into the blank slot
+					operator[](idx) = operator[](idx2);
+					operator[](idx2).clear();
+					break;
+				}
+			}
+		}
+	}
+}
+
+void InventoryItems::equipItem(int itemIndex) {
+	error("TODO");
+}
+
+void InventoryItems::removeItem(int itemIndex) {
+	error("TODO");
+}
+
+/*------------------------------------------------------------------------*/
+
+InventoryItemsGroup::InventoryItemsGroup(InventoryItems &weapons, InventoryItems &armor,
+		InventoryItems &accessories, InventoryItems &misc) {
+	_itemSets[0] = &weapons;
+	_itemSets[1] = &armor;
+	_itemSets[2] = &accessories;
+	_itemSets[3] = &misc;
+}
+
+InventoryItems &InventoryItemsGroup::operator[](ItemCategory category) {
+	return *_itemSets[category];
+}
+
+/*------------------------------------------------------------------------*/
+
 Treasure::Treasure() {
 	_hasItems = false;
-	_v1 = false;
 }
 
 } // End of namespace Xeen
diff --git a/engines/xeen/items.h b/engines/xeen/items.h
index 5a8c4d7..c0b82b9 100644
--- a/engines/xeen/items.h
+++ b/engines/xeen/items.h
@@ -24,11 +24,13 @@
 #define XEEN_ITEMS_H
 
 #include "common/scummsys.h"
+#include "common/array.h"
 #include "common/serializer.h"
 
 namespace Xeen {
 
 #define TOTAL_ITEMS 10
+#define INV_ITEMS_TOTAL 9
 
 enum BonusFlags { 
 	ITEMFLAG_BONUS_MASK = 0xBF,  ITEMFLAG_CURSED = 0x40, ITEMFLAG_BROKEN = 0x80 
@@ -47,6 +49,8 @@ public:
 public:
 	XeenItem();
 
+	void clear();
+
 	void synchronize(Common::Serializer &s);
 
 	int getElementalCategory() const;
@@ -54,6 +58,29 @@ public:
 	int getAttributeCategory() const;
 };
 
+class InventoryItems : public Common::Array<XeenItem> {
+public:
+	InventoryItems();
+
+	void discardItem(int itemIndex);
+
+	void equipItem(int itemIndex);
+
+	void removeItem(int itemIndex);
+
+	void sort();
+};
+
+class InventoryItemsGroup {
+private:
+	InventoryItems *_itemSets[4];
+public:
+	InventoryItemsGroup(InventoryItems &weapons, InventoryItems &armor,
+		InventoryItems &accessories, InventoryItems &misc);
+
+	InventoryItems &operator[](ItemCategory category);
+};
+
 class Treasure {
 public:
 	XeenItem _misc[TOTAL_ITEMS];
@@ -61,7 +88,6 @@ public:
 	XeenItem _armor[TOTAL_ITEMS];
 	XeenItem _weapons[TOTAL_ITEMS];
 	bool _hasItems;
-	bool _v1;
 public:
 	Treasure();
 };
diff --git a/engines/xeen/party.cpp b/engines/xeen/party.cpp
index 0a276b2..7d47eaf 100644
--- a/engines/xeen/party.cpp
+++ b/engines/xeen/party.cpp
@@ -43,7 +43,7 @@ void AttributePair::synchronize(Common::Serializer &s) {
 
 /*------------------------------------------------------------------------*/
 
-Character::Character() {
+Character::Character(): _items(_weapons, _armor, _accessories, _misc) {
 	_sex = MALE;
 	_race = HUMAN;
 	_xeenSide = 0;
diff --git a/engines/xeen/party.h b/engines/xeen/party.h
index 6f70c4b..73de706 100644
--- a/engines/xeen/party.h
+++ b/engines/xeen/party.h
@@ -74,7 +74,6 @@ enum Condition { CURSED = 0, HEART_BROKEN = 1, WEAK = 2, POISONED = 3,
 #define XEEN_TOTAL_CHARACTERS 24
 #define MAX_ACTIVE_PARTY 6
 #define TOTAL_STATS 7
-#define INV_ITEMS_TOTAL 9
 
 class XeenEngine;
 
@@ -115,10 +114,11 @@ public:
 	bool _hasSpells;
 	int _currentSpell;
 	int _quickOption;
-	XeenItem _weapons[INV_ITEMS_TOTAL];
-	XeenItem _armor[INV_ITEMS_TOTAL];
-	XeenItem _accessories[INV_ITEMS_TOTAL];
-	XeenItem _misc[INV_ITEMS_TOTAL];
+	InventoryItemsGroup _items;
+	InventoryItems _weapons;
+	InventoryItems _armor;
+	InventoryItems _accessories;
+	InventoryItems _misc;
 	int _lloydSide;
 	AttributePair _fireResistence;
 	AttributePair _coldResistence;
diff --git a/engines/xeen/resources.cpp b/engines/xeen/resources.cpp
index 8a23216..1f1c979 100644
--- a/engines/xeen/resources.cpp
+++ b/engines/xeen/resources.cpp
@@ -1088,4 +1088,41 @@ const char *const NOT_PROFICIENT =
 const char *const NO_ITEMS_AVAILABLE = "\x3""c\n"
 	"\t000No items available.";
 
+const char *const CATEGORY_NAMES[4] = { "Weapons", "Armor", "Accessories", "Miscellaneous" };
+
+const char *const X_FOR_THE_Y =
+	"\x1\fd\r%s\v000\t000%s for %s the %s%s\v011\x2%s%s%s%s%s%s%s%s%s\x1\fd";
+
+const char *const X_FOR_Y =
+	"\x1\xC""d\r\x3l\v000\t000%s for %s\x3r\t000%s\x3l\v011\x2%s%s%s%s%s%s%s%s%s\x1\xC""d";
+
+const char *const X_FOR_Y_GOLD =
+	"\x1\fd\r\x3l\v000\t000%s for %s\t150Gold - %lu%s\x3l\v011"
+	"\x2%s%s%s%s%s%s%s%s%s\x1\fd";
+
+const char *const FMT_CHARGES = "\x3rr\t000Charges\x3l";
+
+const char *const AVAILABLE_GOLD_COST =
+	"\x1\fd\r\x3l\v000\t000Available %s%s\t150Gold - %lu\x3r\t000Cost"
+	"\x3l\v011\x2%s%s%s%s%s%s%s%s%s\x1\xC""d";
+
+const char *const CHARGES = "Charges";
+
+const char *const COST = "Cost";
+
+const char *const ITEM_ACTIONS[7] = {
+	"Equip", "Remove", "Use", "Discard", "Enchant", "Recharge", "Gold"
+};
+const char *const WHICH_ITEM = "\t010\v005%s which item?";
+
+const char *const WHATS_YOUR_HURRY = "\v007What's your hurry?\n"
+	"Wait till you get out of here!";
+
+const char *const USE_ITEM_IN_COMBAT = 
+	"\v007To use an item in Combat, invoke the Use command on your turn!";
+
+const char *const NO_SPECIAL_ABILITIES = "\v005\x3""c%s\fdhas no special abilities!";
+
+const char *const CANT_CAST_WHILE_ENGAGED = "\x03c\v007Can't cast %s while engaged!";
+
 } // End of namespace Xeen
diff --git a/engines/xeen/resources.h b/engines/xeen/resources.h
index c851db7..88e01cd 100644
--- a/engines/xeen/resources.h
+++ b/engines/xeen/resources.h
@@ -371,6 +371,33 @@ extern const char *const NOT_PROFICIENT;
 
 extern const char *const NO_ITEMS_AVAILABLE;
 
+extern const char *const CATEGORY_NAMES[4];
+
+extern const char *const X_FOR_THE_Y;
+
+extern const char *const X_FOR_Y;
+
+extern const char *const X_FOR_Y_GOLD;
+
+extern const char *const FMT_CHARGES;
+
+extern const char *const AVAILABLE_GOLD_COST;
+
+extern const char *const CHARGES;
+
+extern const char *const COST;
+
+extern const char *const ITEM_ACTIONS[7];
+extern const char *const WHICH_ITEM;
+
+extern const char *const WHATS_YOUR_HURRY;
+
+extern const char *const USE_ITEM_IN_COMBAT;
+
+extern const char *const NO_SPECIAL_ABILITIES;
+
+extern const char *const CANT_CAST_WHILE_ENGAGED;
+
 } // End of namespace Xeen
 
 #endif	/* XEEN_RESOURCES_H */
diff --git a/engines/xeen/spells.cpp b/engines/xeen/spells.cpp
index 588fa1b..3492510 100644
--- a/engines/xeen/spells.cpp
+++ b/engines/xeen/spells.cpp
@@ -56,4 +56,138 @@ int Spells::calcSpellPoints(int spellId, int expenseFactor) const {
 	return (amount >= 0) ? amount : amount * -1 * expenseFactor;
 }
 
+typedef void(Spells::*SpellMethodPtr)();
+
+void Spells::doSpell(int spellId) {
+	static const SpellMethodPtr SPELL_LIST[73] = {
+		&Spells::light, &Spells::awaken, &Spells::magicArrow, &Spells::firstAid,
+		&Spells::flyingFist, &Spells::energyBlast, &Spells::sleep,
+		&Spells::revitalize, &Spells::cureWounds, &Spells::sparks,
+
+		&Spells::shrapMetal, &Spells::insectSpray, &Spells::toxicCloud,
+		&Spells::protectionFromElements, &Spells::pain, &Spells::jump,
+		&Spells::beastMaster, &Spells::clairvoyance, &Spells::turnUndead,
+		&Spells::levitate,
+
+		&Spells::wizardEye, &Spells::bless, &Spells::identifyMonster,
+		&Spells::lightningBolt, &Spells::holyBonus, &Spells::powerCure,
+		&Spells::naturesCure, &Spells::lloydsBeacon, &Spells::powerShield,
+		&Spells::heroism,
+
+		&Spells::hypnotize, &Spells::walkOnWater, &Spells::frostByte,
+		&Spells::detectMonster, &Spells::fireball, &Spells::coldRay,
+		&Spells::curePoison, &Spells::acidSpray, &Spells::timeDistortion,
+		&Spells::dragonSleep,
+
+		&Spells::cureDisease, &Spells::teleport, &Spells::fingerOfDeath,
+		&Spells::cureParalysis, &Spells::golemStopper, &Spells::poisonVolley,
+		&Spells::deadlySwarm, &Spells::superShelter, &Spells::dayOfProtection,
+		&Spells::dayOfSorcery,
+
+		&Spells::createFood, &Spells::fieryFlail, &Spells::rechargeItem,
+		&Spells::fantasticFreeze, &Spells::townPortal, &Spells::stoneToFlesh,
+		&Spells::raiseDead, &Spells::etherialize, &Spells::dancingSword,
+		&Spells::moonRay,
+
+		&Spells::massDistortion, &Spells::prismaticLight, &Spells::enchantItem,
+		&Spells::incinerate, &Spells::holyWord, &Spells::resurrection,
+		&Spells::elementalStorm, &Spells::megaVolts, &Spells::inferno,
+		&Spells::sunRay,
+
+		&Spells::implosion, &Spells::starBurst, &Spells::divineIntervention
+	};
+
+	if (_vm->_mode == MODE_InCombat) {
+		if (spellId == 15 || spellId == 20 || spellId == 27 || spellId == 41
+				|| spellId == 47 || spellId == 54 || spellId == 57) {
+			ErrorScroll::show(_vm, Common::String::format(CANT_CAST_WHILE_ENGAGED,
+				_spellNames[spellId].c_str()), WT_UNFORMATTED);
+			return;
+		}
+	}
+
+	(this->*SPELL_LIST[spellId])();
+}
+
+void Spells::light() { error("TODO: spell"); }
+void Spells::awaken() { error("TODO: spell"); }
+void Spells::magicArrow() { error("TODO: spell"); }
+void Spells::firstAid() { error("TODO: spell"); }
+void Spells::flyingFist() { error("TODO: spell"); }
+void Spells::energyBlast() { error("TODO: spell"); }
+void Spells::sleep() { error("TODO: spell"); }
+void Spells::revitalize() { error("TODO: spell"); }
+void Spells::cureWounds() { error("TODO: spell"); }
+void Spells::sparks() { error("TODO: spell"); }
+
+void Spells::shrapMetal() { error("TODO: spell"); }
+void Spells::insectSpray() { error("TODO: spell"); }
+void Spells::toxicCloud() { error("TODO: spell"); }
+void Spells::protectionFromElements() { error("TODO: spell"); }
+void Spells::pain() { error("TODO: spell"); }
+void Spells::jump() { error("TODO: spell"); }			// Not while engaged
+void Spells::beastMaster() { error("TODO: spell"); }
+void Spells::clairvoyance() { error("TODO: spell"); }
+void Spells::turnUndead() { error("TODO: spell"); }
+void Spells::levitate() { error("TODO: spell"); }
+
+void Spells::wizardEye() { error("TODO: spell"); }		// Not while engaged
+void Spells::bless() { error("TODO: spell"); }
+void Spells::identifyMonster() { error("TODO: spell"); }
+void Spells::lightningBolt() { error("TODO: spell"); }
+void Spells::holyBonus() { error("TODO: spell"); }
+void Spells::powerCure() { error("TODO: spell"); }
+void Spells::naturesCure() { error("TODO: spell"); }
+void Spells::lloydsBeacon() { error("TODO: spell"); }	// Not while engaged
+void Spells::powerShield() { error("TODO: spell"); }
+void Spells::heroism() { error("TODO: spell"); }
+
+void Spells::hypnotize() { error("TODO: spell"); }
+void Spells::walkOnWater() { error("TODO: spell"); }
+void Spells::frostByte() { error("TODO: spell"); }
+void Spells::detectMonster() { error("TODO: spell"); }
+void Spells::fireball() { error("TODO: spell"); }
+void Spells::coldRay() { error("TODO: spell"); }
+void Spells::curePoison() { error("TODO: spell"); }
+void Spells::acidSpray() { error("TODO: spell"); }
+void Spells::timeDistortion() { error("TODO: spell"); }
+void Spells::dragonSleep() { error("TODO: spell"); }
+
+void Spells::cureDisease() { error("TODO: spell"); }
+void Spells::teleport() { error("TODO: spell"); }		// Not while engaged
+void Spells:: fingerOfDeath() { error("TODO: spell"); }
+void Spells::cureParalysis() { error("TODO: spell"); }
+void Spells::golemStopper() { error("TODO: spell"); }
+void Spells::poisonVolley() { error("TODO: spell"); }
+void Spells::deadlySwarm() { error("TODO: spell"); }
+void Spells::superShelter() { error("TODO: spell"); }	// Not while engaged
+void Spells::dayOfProtection() { error("TODO: spell"); }
+void Spells::dayOfSorcery() { error("TODO: spell"); }
+
+void Spells::createFood() { error("TODO: spell"); }
+void Spells::fieryFlail() { error("TODO: spell"); }
+void Spells::rechargeItem() { error("TODO: spell"); }
+void Spells::fantasticFreeze() { error("TODO: spell"); }
+void Spells::townPortal() { error("TODO: spell"); }		// Not while engaged
+void Spells::stoneToFlesh() { error("TODO: spell"); }
+void Spells::raiseDead() { error("TODO: spell"); }
+void Spells::etherialize() { error("TODO: spell"); }		// Not while engaged
+void Spells::dancingSword() { error("TODO: spell"); }
+void Spells::moonRay() { error("TODO: spell"); }
+
+void Spells::massDistortion() { error("TODO: spell"); }
+void Spells::prismaticLight() { error("TODO: spell"); }
+void Spells::enchantItem() { error("TODO: spell"); }
+void Spells::incinerate() { error("TODO: spell"); }
+void Spells::holyWord() { error("TODO: spell"); }
+void Spells::resurrection() { error("TODO: spell"); }
+void Spells::elementalStorm() { error("TODO: spell"); }
+void Spells::megaVolts() { error("TODO: spell"); }
+void Spells::inferno() { error("TODO: spell"); }
+void Spells::sunRay() { error("TODO: spell"); }
+
+void Spells::implosion() { error("TODO: spell"); }
+void Spells::starBurst() { error("TODO: spell"); }
+void Spells::divineIntervention() { error("TODO: spell"); }
+
 } // End of namespace Xeen
diff --git a/engines/xeen/spells.h b/engines/xeen/spells.h
index 96f4916..241d35d 100644
--- a/engines/xeen/spells.h
+++ b/engines/xeen/spells.h
@@ -37,6 +37,88 @@ private:
 	XeenEngine *_vm;
 
 	void load();
+
+	// Spell list
+	void light();
+	void awaken();
+	void magicArrow();
+	void firstAid();
+	void flyingFist();
+	void energyBlast();
+	void sleep();
+	void revitalize();
+	void cureWounds();
+	void sparks();
+
+	void shrapMetal();
+	void insectSpray();
+	void toxicCloud();
+	void protectionFromElements();
+	void pain();
+	void jump();			// Not while engaged
+	void beastMaster();
+	void clairvoyance();
+	void turnUndead();
+	void levitate();
+
+	void wizardEye();		// Not while engaged
+	void bless();
+	void identifyMonster();
+	void lightningBolt();
+	void holyBonus();
+	void powerCure();
+	void naturesCure();
+	void lloydsBeacon();	// Not while engaged
+	void powerShield();
+	void heroism();
+
+	void hypnotize();
+	void walkOnWater();
+	void frostByte();
+	void detectMonster();
+	void fireball();
+	void coldRay();
+	void curePoison();
+	void acidSpray();
+	void timeDistortion();
+	void dragonSleep();
+
+	void cureDisease();
+	void teleport();		// Not while engaged
+	void  fingerOfDeath();
+	void cureParalysis();
+	void golemStopper();
+	void poisonVolley();
+	void deadlySwarm();
+	void superShelter();	// Not while engaged
+	void dayOfProtection();
+	void dayOfSorcery();
+
+	void createFood();
+	void fieryFlail();
+	void rechargeItem();
+	void fantasticFreeze();
+	void townPortal();		// Not while engaged
+	void stoneToFlesh();
+	void raiseDead();
+	void etherialize();		// Not while engaged
+	void dancingSword();
+	void moonRay();
+
+	void massDistortion();
+	void prismaticLight();
+	void enchantItem();
+	void incinerate();
+	void holyWord();
+	void resurrection();
+	void elementalStorm();
+	void megaVolts();
+	void inferno();
+	void sunRay();
+
+	void implosion();
+	void starBurst();
+	void divineIntervention();
 public:
 	Common::StringArray _spellNames;
 	Common::StringArray _maeNames;
@@ -48,6 +130,7 @@ public:
 
 	int calcSpellPoints(int spellId, int expenseFactor) const;
 
+	void doSpell(int spellId);
 };
 
 } // End of namespace Xeen


Commit: 8eb9ad50f8ddf23147b999fa40c6231a1a623d41
    https://github.com/scummvm/scummvm/commit/8eb9ad50f8ddf23147b999fa40c6231a1a623d41
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-02-04T20:22:59-05:00

Commit Message:
XEEN: Split Character class into it's own file

Changed paths:
  A engines/xeen/character.cpp
  A engines/xeen/character.h
    engines/xeen/items.cpp
    engines/xeen/items.h
    engines/xeen/module.mk
    engines/xeen/party.cpp
    engines/xeen/party.h



diff --git a/engines/xeen/character.cpp b/engines/xeen/character.cpp
new file mode 100644
index 0000000..f712e78
--- /dev/null
+++ b/engines/xeen/character.cpp
@@ -0,0 +1,1008 @@
+/* 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 "xeen/character.h"
+#include "xeen/resources.h"
+#include "xeen/xeen.h"
+
+namespace Xeen {
+
+XeenItem::XeenItem() {
+	clear();
+}
+
+void XeenItem::clear() {
+	_material = _id = _bonusFlags = 0;
+	_frame = 0;
+}
+
+void XeenItem::synchronize(Common::Serializer &s) {
+	s.syncAsByte(_material);
+	s.syncAsByte(_id);
+	s.syncAsByte(_bonusFlags);
+	s.syncAsByte(_frame);
+}
+
+int XeenItem::getElementalCategory() const {
+	int idx;
+	for (idx = 0; ELEMENTAL_CATEGORIES[idx] < _material; ++idx)
+		;
+
+	return idx;
+}
+
+int XeenItem::getAttributeCategory() const {
+	int m = _material - 59;
+	int idx;
+	for (idx = 0; ATTRIBUTE_CATEGORIES[idx] < m; ++idx)
+		;
+
+	return idx;
+}
+
+/*------------------------------------------------------------------------*/
+
+InventoryItems::InventoryItems() {
+	resize(INV_ITEMS_TOTAL);
+}
+
+void InventoryItems::discardItem(int itemIndex) {
+	operator[](itemIndex).clear();
+	sort();
+}
+
+void InventoryItems::sort() {
+	for (uint idx = 0; idx < size(); ++idx) {
+		if (operator[](idx)._id == 0) {
+			// Found empty slot
+			operator[](idx).clear();
+
+			// Scan through the rest of the list to find any item
+			for (uint idx2 = idx + 1; idx2 < size(); ++idx2) {
+				if (operator[](idx2)._id) {
+					// Found an item, so move it into the blank slot
+					operator[](idx) = operator[](idx2);
+					operator[](idx2).clear();
+					break;
+				}
+			}
+		}
+	}
+}
+
+void InventoryItems::equipItem(int itemIndex) {
+	error("TODO");
+}
+
+void InventoryItems::removeItem(int itemIndex) {
+	error("TODO");
+}
+
+/*------------------------------------------------------------------------*/
+
+InventoryItemsGroup::InventoryItemsGroup(InventoryItems &weapons, InventoryItems &armor,
+		InventoryItems &accessories, InventoryItems &misc) {
+	_itemSets[0] = &weapons;
+	_itemSets[1] = &armor;
+	_itemSets[2] = &accessories;
+	_itemSets[3] = &misc;
+}
+
+InventoryItems &InventoryItemsGroup::operator[](ItemCategory category) {
+	return *_itemSets[category];
+}
+
+/*------------------------------------------------------------------------*/
+
+
+void AttributePair::synchronize(Common::Serializer &s) {
+	s.syncAsByte(_permanent);
+	s.syncAsByte(_temporary);
+}
+
+/*------------------------------------------------------------------------*/
+
+AttributePair::AttributePair() {
+	_temporary = _permanent = 0;
+}
+
+/*------------------------------------------------------------------------*/
+
+Character::Character(): _items(_weapons, _armor, _accessories, _misc) {
+	_sex = MALE;
+	_race = HUMAN;
+	_xeenSide = 0;
+	_class = CLASS_KNIGHT;
+	_ACTemp = 0;
+	_birthDay = 0;
+	_tempAge = 0;
+	Common::fill(&_skills[0], &_skills[18], 0);
+	Common::fill(&_awards[0], &_awards[128], false);
+	Common::fill(&_spells[0], &_spells[39], 0);
+	_lloydMap = 0;
+	_hasSpells = false;
+	_currentSpell = 0;
+	_quickOption = 0;
+	_lloydSide = 0;
+	Common::fill(&_conditions[0], &_conditions[16], 0);
+	_townUnknown = 0;
+	_savedMazeId = 0;
+	_currentHp = 0;
+	_currentSp = 0;
+	_birthYear = 0;
+	_experience = 0;
+	_currentAdventuringSpell = 0;
+	_currentCombatSpell = 0;
+}
+
+void Character::synchronize(Common::Serializer &s) {
+	char name[16];
+	Common::fill(&name[0], &name[16], '\0');
+	strncpy(name, _name.c_str(), 16);
+	s.syncBytes((byte *)name, 16);
+
+	if (s.isLoading())
+		_name = Common::String(name);
+
+	s.syncAsByte(_sex);
+	s.syncAsByte(_race);
+	s.syncAsByte(_xeenSide);
+	s.syncAsByte(_class);
+
+	_might.synchronize(s);
+	_intellect.synchronize(s);
+	_personality.synchronize(s);
+	_endurance.synchronize(s);
+	_speed.synchronize(s);
+	_accuracy.synchronize(s);
+	_luck.synchronize(s);
+	s.syncAsByte(_ACTemp);
+	_level.synchronize(s);
+	s.syncAsByte(_birthDay);
+	s.syncAsByte(_tempAge);
+	
+	// Synchronize the skill list
+	for (int idx = 0; idx < 18; ++idx)
+		s.syncAsByte(_skills[idx]);
+
+	// Synchronize character awards
+	for (int idx = 0; idx < 64; ++idx) {
+		byte b = (_awards[idx] ? 1 : 0) | (_awards[idx + 64] ? 0x10 : 0);
+		s.syncAsByte(b);
+		if (s.isLoading()) {
+			_awards[idx] = (b & 0xF) != 0;
+			_awards[idx + 64] = (b & 0xF0) != 0;
+		}
+	}
+
+	// Synchronize spell list
+	for (int i = 0; i < MAX_SPELLS_PER_CLASS - 1; ++i)
+		s.syncAsByte(_spells[i]);	
+	s.syncAsByte(_lloydMap);
+	s.syncAsByte(_lloydPosition.x);
+	s.syncAsByte(_lloydPosition.y);
+	s.syncAsByte(_hasSpells);
+	s.syncAsByte(_currentSpell);
+	s.syncAsByte(_quickOption);
+
+	for (int i = 0; i < 9; ++i)
+		_weapons[i].synchronize(s);
+	for (int i = 0; i < 9; ++i)
+		_armor[i].synchronize(s);
+	for (int i = 0; i < 9; ++i)
+		_accessories[i].synchronize(s);
+	for (int i = 0; i < 9; ++i)
+		_misc[i].synchronize(s);
+
+	s.syncAsByte(_lloydSide);
+	_fireResistence.synchronize(s);
+	_coldResistence.synchronize(s);
+	_electricityResistence.synchronize(s);
+	_poisonResistence.synchronize(s);
+	_energyResistence.synchronize(s);
+	_magicResistence.synchronize(s);
+	
+	for (int i = 0; i < 16; ++i)
+		s.syncAsByte(_conditions[i]);
+
+	s.syncAsUint16LE(_townUnknown);
+	s.syncAsByte(_savedMazeId);
+	s.syncAsUint16LE(_currentHp);
+	s.syncAsUint16LE(_currentSp);
+	s.syncAsUint16LE(_birthYear);
+	s.syncAsUint32LE(_experience);
+	s.syncAsByte(_currentAdventuringSpell);
+	s.syncAsByte(_currentCombatSpell);
+}
+
+Condition Character::worstCondition() const {
+	for (int cond = ERADICATED; cond >= CURSED; --cond) {
+		if (_conditions[cond])
+			return (Condition)cond;
+	}
+
+	return NO_CONDITION;
+}
+
+int Character::getAge(bool ignoreTemp) const {
+	int year = MIN(Party::_vm->_party->_year - _birthYear, (uint)254);
+
+	return ignoreTemp ? year : year + _tempAge;
+}
+
+int Character::getMaxHP() const {
+	int hp = BASE_HP_BY_CLASS[_class];
+	hp += statBonus(getStat(ENDURANCE));
+	hp += RACE_HP_BONUSES[_race];
+	if (_skills[BODYBUILDER])
+		++hp;
+	if (hp < 1)
+		hp = 1;
+
+	hp *= getCurrentLevel();
+	hp += itemScan(7);
+
+	return MAX(hp, 0);
+}
+
+int Character::getMaxSP() const {
+	int result = 0;
+	bool flag = false;
+	int amount = 0;
+	Attribute attrib;
+	Skill skill;
+
+	if (!_hasSpells)
+		return 0;
+
+	if (_class == CLASS_SORCERER || _class == CLASS_ARCHER) {
+		attrib = INTELLECT;
+		skill = PRESTIDIGITATION;
+	} else {
+		attrib = PERSONALITY;
+		skill = PRAYER_MASTER;
+	}
+	if (_class == CLASS_DRUID || _class == CLASS_RANGER)
+		skill = ASTROLOGER;
+
+	for (;;) {
+		// Get the base number of spell points
+		result = statBonus(getStat(attrib)) + 3;
+		result += RACE_SP_BONUSES[_race][attrib - 1];
+
+		if (_skills[skill])
+			result += 2;
+		if (result < 1)
+			result = 1;
+
+		// Multiply it by the character's level
+		result *= getCurrentLevel();
+
+		// Classes other than sorcerer, clerics, and druids only get half the SP
+		if (_class != CLASS_SORCERER && _class != CLASS_CLERIC && _class != CLASS_DRUID)
+			result /= 2;
+
+		if (flag || (_class != CLASS_DRUID && _class != CLASS_RANGER))
+			break;
+
+		// Druids and rangers get bonuses averaged on both personality and intellect
+		attrib = INTELLECT;
+		flag = true;
+		amount = result;
+	}
+	if (flag)
+		result = (amount + result) / 2;
+
+	result += itemScan(8);
+	if (result < 0)
+		result = 0;
+
+	return result;
+}
+
+/**
+ * Get the effective value of a given stat for the character
+ */
+uint Character::getStat(Attribute attrib, bool baseOnly) const {
+	AttributePair attr;
+	int mode = 0;
+
+	switch (attrib) {
+	case MIGHT:
+		attr = _might;
+		break;
+	case INTELLECT:
+		attr = _intellect;
+		mode = 1;
+		break;
+	case PERSONALITY:
+		attr = _personality;
+		mode = 1;
+		break;
+	case ENDURANCE:
+		attr = _endurance;
+		break;
+	case SPEED:
+		attr = _speed;
+		break;
+	case ACCURACY:
+		attr = _accuracy;
+		break;
+	case LUCK:
+		attr = _luck;
+		mode = 2;
+		break;
+	default:
+		return 0;
+	}
+
+	// All the attributes except luck are affected by the character's age
+	if (mode < 2) {
+		int age = getAge(false);
+		int ageIndex = 0;
+		while (AGE_RANGES[ageIndex] <= age)
+			++ageIndex;
+
+		attr._permanent += AGE_RANGES_ADJUST[mode][ageIndex];
+	}
+
+
+	attr._permanent += itemScan((int)attrib);
+
+	if (!baseOnly) {
+		attr._permanent += conditionMod(attrib);
+		attr._permanent += attr._temporary;
+	}
+
+	return MAX(attr._permanent, (uint)0);
+}
+
+/**
+ * Return the color number to use for a given stat value in the character
+ * info or quick reference dialogs
+ */
+int Character::statColor(int amount, int threshold) {
+	if (amount < 1)
+		return 6;
+	else if (amount > threshold)
+		return 2;
+	else if (amount == threshold)
+		return 15;
+	else if (amount <= (threshold / 4))
+		return 9;
+	else
+		return 32;
+}
+
+int Character::statBonus(uint statValue) const {
+	int idx;
+	for (idx = 0; STAT_VALUES[idx] <= statValue; ++idx)
+		;
+
+	return STAT_BONUSES[idx];
+}
+
+bool Character::charSavingThrow(DamageType attackType) const {
+	int v, vMax;
+
+	if (attackType == DT_PHYSICAL) {
+		v = statBonus(getStat(LUCK)) + getCurrentLevel();
+		vMax = v + 20;
+	} else {
+		switch (attackType) {
+		case DT_MAGICAL:
+			v = _magicResistence._permanent + _magicResistence._temporary + itemScan(16);
+			break;
+		case DT_FIRE:
+			v = _fireResistence._permanent + _fireResistence._temporary + itemScan(11);
+			break;
+		case DT_ELECTRICAL:
+			v = _electricityResistence._permanent + _electricityResistence._temporary + itemScan(12);
+			break;
+		case DT_COLD:
+			v = _coldResistence._permanent + _coldResistence._temporary + itemScan(13);
+			break;
+		case DT_POISON:
+			v = _poisonResistence._permanent + _poisonResistence._temporary + itemScan(14);
+			break;
+		case DT_ENERGY:
+			v = _energyResistence._permanent + _energyResistence._temporary + itemScan(15);
+			break;
+		default:
+			v = 0;
+			break;
+		}
+
+		vMax = v + 40;
+	}
+
+	return Party::_vm->getRandomNumber(1, vMax) <= v;
+}
+
+bool Character::noActions() {
+	Condition condition = worstCondition();
+
+	switch (condition) {
+	case CURSED:
+	case POISONED:
+	case DISEASED:
+	case INSANE:
+	case IN_LOVE:
+	case DRUNK: {
+		Common::String msg = Common::String::format(IN_NO_CONDITION, _name.c_str());
+		ErrorScroll::show(Party::_vm, msg, 
+			Party::_vm->_mode == 17 ? WT_2 : WT_NONFREEZED_WAIT);
+		return true;
+	}
+	default:
+		return false;
+	}
+}
+
+void Character::setAward(int awardId, bool value) {
+	int v = awardId;
+	if (awardId == 73)
+		v = 126;
+	else if (awardId == 81)
+		v = 127;
+
+	_awards[v] = value;
+}
+
+bool Character::hasAward(int awardId) const {
+	int v = awardId;
+	if (awardId == 73)
+		v = 126;
+	else if (awardId == 81)
+		v = 127;
+
+	return _awards[v];
+}
+
+int Character::getArmorClass(bool baseOnly) const {
+	Party &party = *Party::_vm->_party;
+
+	int result = statBonus(getStat(SPEED)) + itemScan(9);
+	if (!baseOnly)
+		result += party._blessed + _ACTemp;
+
+	return MAX(result, 0);
+}
+
+/**
+ * Returns the thievery skill level, adjusted by class and race
+ */
+int Character::getThievery() const {
+	int result = getCurrentLevel() * 2;
+
+	if (_class == CLASS_NINJA)
+		result += 15;
+	else if (_class == CLASS_ROBBER)
+		result += 30;
+
+	switch (_race) {
+	case ELF:
+	case GNOME:
+		result += 10;
+		break;
+	case DWARF:
+		result += 5;
+		break;
+	case HALF_ORC:
+		result -= 10;
+		break;
+	default:
+		break;
+	}
+
+	result += itemScan(10);
+
+	// If the character doesn't have a thievery skill, then do'nt allow any result
+	if (!_skills[THIEVERY])
+		result = 0;
+
+	return MAX(result, 0);
+}
+
+uint Character::getCurrentLevel() const {
+	return MAX(_level._permanent + _level._temporary, (uint)0);
+}
+
+int Character::itemScan(int itemId) const {
+	int result = 0;
+
+	for (int accessIdx = 0; accessIdx < 3; ++accessIdx) {
+		switch (accessIdx) {
+		case 0:
+			for (int idx = 0; idx < INV_ITEMS_TOTAL; ++idx) {
+				const XeenItem &item = _weapons[idx];
+
+				if (item._frame && !(item._bonusFlags & 0xC0) && itemId < 11
+						&& itemId != 3 && item._material >= 59 && item._material <= 130) {
+					int mIndex = item.getAttributeCategory();
+					if (mIndex > 2)
+						++mIndex;
+
+					if (mIndex == itemId)
+						result += ATTRIBUTE_BONUSES[item._material - 59];
+				}
+			}
+			break;
+
+		case 1:
+			for (int idx = 0; idx < INV_ITEMS_TOTAL; ++idx) {
+				const XeenItem &item = _armor[idx];
+
+				if (item._frame && !(item._bonusFlags & 0xC0)) {
+					if (itemId < 11 && itemId != 3 && item._material >= 59 && item._material <= 130) {
+						int mIndex = item.getAttributeCategory();
+						if (mIndex > 2)
+							++mIndex;
+
+						if (mIndex == itemId)
+							result += ATTRIBUTE_BONUSES[item._material - 59];
+					}
+
+					if (itemId > 10 && item._material < 37) {
+						int mIndex = item.getElementalCategory() + 11;
+
+						if (mIndex == itemId) {
+							result += ELEMENTAL_RESISTENCES[item._material];
+						}
+					}
+
+					if (itemId == 9) {
+						result += ARMOR_STRENGTHS[item._id];
+
+						if (item._material >= 37 && item._material <= 58)
+							result += METAL_LAC[item._material - 37];
+					}
+				}
+			}
+			break;
+
+		case 2:
+			for (int idx = 0; idx < INV_ITEMS_TOTAL; ++idx) {
+				const XeenItem &item = _accessories[idx];
+
+				if (item._frame && !(item._bonusFlags & 0xC0) && itemId < 11 && itemId != 3) {
+					if (item._material >= 59 && item._material <= 130) {
+						int mIndex = item.getAttributeCategory();
+						if (mIndex > 2)
+							++mIndex;
+
+						if (mIndex == itemId) {
+							result += ATTRIBUTE_BONUSES[item._material - 59];
+						}
+					}
+
+					if (itemId > 10 && item._material < 37) {
+						int mIndex = item.getElementalCategory() + 11;
+						
+						if (mIndex == itemId)
+							result += ELEMENTAL_RESISTENCES[item._material];
+					}
+				}
+			}
+			break;
+		}
+	};
+
+	return result;
+}
+
+/**
+ * Modifies a passed attribute value based on player's condition
+ */
+int Character::conditionMod(Attribute attrib) const {
+	if (_conditions[DEAD] || _conditions[STONED] || _conditions[ERADICATED])
+		return 0;
+
+	int v[7];
+	Common::fill(&v[0], &v[7], 0);
+	if (_conditions[CURSED])
+		v[6] -= _conditions[CURSED];
+
+	if (_conditions[INSANE]) {
+		v[2] -= _conditions[INSANE];
+		v[1] -= _conditions[INSANE];
+		v[5] -= _conditions[INSANE];
+		v[0] -= _conditions[INSANE];
+		v[4] -= _conditions[INSANE];
+	}
+
+	if (_conditions[POISONED]) {
+		v[0] -= _conditions[POISONED];
+		v[4] -= _conditions[POISONED];
+		v[5] -= _conditions[POISONED];
+	}
+
+	if (_conditions[DISEASED]) {
+		v[3] -= _conditions[DISEASED];
+		v[2] -= _conditions[DISEASED];
+		v[1] -= _conditions[DISEASED];
+	}
+
+	for (int idx = 0; idx < 7; ++idx) {
+		v[idx] -= _conditions[HEART_BROKEN];
+		v[idx] -= _conditions[IN_LOVE];
+		v[idx] -= _conditions[WEAK];
+		v[idx] -= _conditions[DRUNK];
+	}
+
+	return v[attrib];
+}
+
+void Character::setValue(int id, uint value) {
+	Party &party = *Party::_vm->_party;
+	Scripts &scripts = *Party::_vm->_scripts;
+
+	switch (id) {
+	case 3:
+		// Set character sex
+		_sex = (Sex)value;
+		break;
+	case 4:
+		// Set race
+		_race = (Race)value;
+		break;
+	case 5:
+		// Set class
+		_class = (CharacterClass)value;
+		break;
+	case 8:
+		// Set the current Hp
+		_currentHp = value;
+		break;
+	case 9:
+		// Set the current Sp
+		_currentSp = value;
+		break;
+	case 10:
+	case 77:
+		// Set temporary armor class
+		_ACTemp = value;
+		break;
+	case 11:
+		// Set temporary level
+		_level._temporary = value;
+		break;
+	case 12:
+		// Set the character's temporary age
+		_tempAge = value;
+		break;
+	case 16:
+		// Set character experience
+		_experience = value;
+		break;
+	case 17:
+		// Set party poison resistence
+		party._poisonResistence = value;
+		break;
+	case 18:
+		// Set condition
+		if (value == 16) {
+			// Clear all the conditions
+			Common::fill(&_conditions[CURSED], &_conditions[NO_CONDITION], false);
+		} else if (value == 6) {
+			_conditions[value] = 1;
+		} else {
+			++_conditions[value];
+		}
+
+		if (value >= DEAD && value <= ERADICATED && _currentHp > 0)
+			_currentHp = 0;
+		break;
+	case 25:
+		// Set time of day in minutes (0-1440)
+		party._minutes = value;
+		break;
+	case 34:
+		// Set party gold
+		party._gold = value;
+		break;
+	case 35:
+		// Set party gems
+		party._gems = value;
+		break;
+	case 37:
+		_might._temporary = value;
+		break;
+	case 38:
+		_intellect._temporary = value;
+		break;
+	case 39:
+		_personality._temporary = value;
+		break;
+	case 40:
+		_endurance._temporary = value;
+		break;
+	case 41:
+		_speed._temporary = value;
+		break;
+	case 42:
+		_accuracy._temporary = value;
+		break;
+	case 43:
+		_luck._temporary = value;
+		break;
+	case 45:
+		_might._permanent = value;
+		break;
+	case 46:
+		_intellect._permanent = value;
+		break;
+	case 47:
+		_personality._permanent = value;
+		break;
+	case 48:
+		_endurance._permanent = value;
+		break;
+	case 49:
+		_speed._permanent = value;
+		break;
+	case 50:
+		_accuracy._permanent = value;
+		break;
+	case 51:
+		_luck._permanent = value;
+		break;
+	case 52:
+		_fireResistence._permanent = value;
+		break;
+	case 53:
+		_electricityResistence._permanent = value;
+		break;
+	case 54:
+		_coldResistence._permanent = value;
+		break;
+	case 55:
+		_poisonResistence._permanent = value;
+		break;
+	case 56:
+		_energyResistence._permanent = value;
+		break;
+	case 57:
+		_magicResistence._permanent = value;
+		break;
+	case 58:
+		_fireResistence._temporary = value;
+		break;
+	case 59:
+		_electricityResistence._temporary = value;
+		break;
+	case 60:
+		_coldResistence._temporary = value;
+		break;
+	case 61:
+		_poisonResistence._temporary = value;
+		break;
+	case 62:
+		_energyResistence._temporary = value;
+		break;
+	case 63:
+		_magicResistence._temporary = value;
+		break;
+	case 64:
+		_level._permanent = value;
+		break;
+	case 65:
+		// Set party food
+		party._food = value;
+		break;
+	case 69:
+		// Set levitate active
+		party._levitateActive = value != 0;
+		break;
+	case 70:
+		party._lightCount = value;
+		break;
+	case 71:
+		party._fireResistence = value;
+		break;
+	case 72:
+		party._electricityResistence = value;
+		break;
+	case 73:
+		party._coldResistence = value;
+		break;
+	case 74:
+		party._walkOnWaterActive = value != 0;
+		party._poisonResistence = value;
+		party._wizardEyeActive = value != 0;
+		party._coldResistence = value;
+		party._electricityResistence = value;
+		party._fireResistence = value;
+		party._lightCount = value;
+		party._levitateActive = value != 0;
+		break;
+	case 76:
+		// Set day of the year (0-99)
+		party._day = value;
+		break;
+	case 79:
+		party._wizardEyeActive = true;
+		break;
+	case 83:
+		scripts._nEdamageType = value;
+		break;
+	case 84:
+		party._mazeDirection = (Direction)value;
+		break;
+	case 85:
+		party._year = value;
+		break;
+	case 94:
+		party._walkOnWaterActive = value != 0;
+		break;
+	default:
+		break;
+	}
+}
+
+bool Character::guildMember() const {
+	Party &party = *Party::_vm->_party;
+
+	if (party._mazeId == 49 && !Party::_vm->_files->_isDarkCc) {
+		return hasAward(5);
+	}
+
+	switch (party._mazeId) {
+	case 29:
+		return hasAward(83);
+	case 31:
+		return hasAward(84);
+	case 33:
+		return hasAward(85);
+	case 35:
+		return hasAward(86);
+	default:
+		return hasAward(87);
+	}
+}
+
+uint Character::experienceToNextLevel() const {
+	uint next = nextExperienceLevel();
+	uint curr = getCurrentExperience();
+	return (curr >= next) ? 0 : next - curr;
+}
+
+uint Character::nextExperienceLevel() const {
+	int shift, base;
+	if (_level._permanent >= 12) {
+		base = _level._permanent - 12;
+		shift = 10;
+	} else {
+		base = 0;
+		shift = _level._permanent - 1;
+	}
+
+	return (base * 1024000) + (CLASS_EXP_LEVELS[_class] << shift);
+}
+
+uint Character::getCurrentExperience() const {
+	int lev = _level._permanent - 1;
+	int shift, base;
+
+	if (lev > 0 && lev < 12)
+		return _experience;
+
+	if (lev >= 12) {
+		base = lev - 12;
+		shift = 10;
+	} else {
+		base = 0;
+		shift = lev - 1;
+	}
+
+	return (base * 1024000) + (CLASS_EXP_LEVELS[_class] << shift) +
+		_experience;
+}
+
+
+int Character::getNumSkills() const {
+	int total = 0;
+	for (int idx = THIEVERY; idx <= DANGER_SENSE; ++idx) {
+		if (_skills[idx])
+			++total;
+	}
+
+	return total;
+}
+
+int Character::getNumAwards() const {
+	int total = 0;
+	for (int idx = 0; idx < 88; ++idx) {
+		if (hasAward(idx))
+			++total;
+	}
+
+	return total;
+}
+
+/**
+ * Assembles a full lines description for a specified item for use in
+ * the Items dialog
+ */
+Common::String Character::assembleItemName(int itemIndex, int displayNum, 
+		ItemCategory category) {
+	Spells &spells = *Party::_vm->_spells;
+
+	switch (category) {
+	case CATEGORY_WEAPON: {
+		// Weapons
+		XeenItem &i = _weapons[itemIndex];
+		return Common::String::format("\f%02u%s%s%s\f%02u%s%s%s", displayNum,
+			!i._bonusFlags ? spells._maeNames[i._material] : "",
+			(i._bonusFlags & ITEMFLAG_BROKEN) ? ITEM_BROKEN : "",
+			(i._bonusFlags & ITEMFLAG_CURSED) ? ITEM_CURSED : "",
+			WEAPON_NAMES[i._id],
+			!i._bonusFlags ? "" : BONUS_NAMES[i._bonusFlags & ITEMFLAG_BONUS_MASK],
+			(i._bonusFlags & (ITEMFLAG_BROKEN | ITEMFLAG_CURSED)) || 
+				!i._bonusFlags ? "\b " : ""
+		);
+	}
+
+	case CATEGORY_ARMOR: {
+		// Armor
+		XeenItem &i = _armor[itemIndex];
+		return Common::String::format("\f%02u%s%s%s\f%02u%s%s", displayNum,
+			!i._bonusFlags ? "" : spells._maeNames[i._material],
+			(i._bonusFlags & ITEMFLAG_BROKEN) ? ITEM_BROKEN : "",
+			(i._bonusFlags & ITEMFLAG_CURSED) ? ITEM_CURSED : "",
+			ARMOR_NAMES[i._id],
+			(i._bonusFlags & (ITEMFLAG_BROKEN | ITEMFLAG_CURSED)) ||
+				!i._bonusFlags ? "\b " : ""
+		);
+	}
+		
+	case CATEGORY_ACCESSORY: {
+		// Accessories
+		XeenItem &i = _accessories[itemIndex];
+		return Common::String::format("\f%02u%s%s%s\f%02u%s%s", displayNum,
+			!i._bonusFlags ? "" : spells._maeNames[i._material],
+			(i._bonusFlags & ITEMFLAG_BROKEN) ? ITEM_BROKEN : "",
+			(i._bonusFlags & ITEMFLAG_CURSED) ? ITEM_CURSED : "",
+			ARMOR_NAMES[i._id],
+			(i._bonusFlags & (ITEMFLAG_BROKEN | ITEMFLAG_CURSED)) ||
+				!i._bonusFlags ? "\b " : ""
+		);
+	}
+
+	case CATEGORY_MISC: {
+		// Misc
+		XeenItem &i = _misc[itemIndex];
+		return Common::String::format("\f%02u%s%s%s\f%02u%s%s", displayNum,
+			!i._bonusFlags ? "" : spells._maeNames[i._material],
+			(i._bonusFlags & ITEMFLAG_BROKEN) ? ITEM_BROKEN : "",
+			(i._bonusFlags & ITEMFLAG_CURSED) ? ITEM_CURSED : "",
+			ARMOR_NAMES[i._id],
+			(i._bonusFlags & (ITEMFLAG_BROKEN | ITEMFLAG_CURSED)) ||
+				!i._id ? "\b " : ""
+		);
+	}
+	default:
+		return "";
+	}
+}
+
+} // End of namespace Xeen
diff --git a/engines/xeen/character.h b/engines/xeen/character.h
new file mode 100644
index 0000000..54da44a
--- /dev/null
+++ b/engines/xeen/character.h
@@ -0,0 +1,231 @@
+/* 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_CHARACTER_H
+#define XEEN_CHARACTER_H
+
+#include "common/scummsys.h"
+#include "common/array.h"
+#include "common/rect.h"
+#include "common/serializer.h"
+#include "xeen/combat.h"
+
+namespace Xeen {
+
+#define INV_ITEMS_TOTAL 9
+
+enum BonusFlags {
+	ITEMFLAG_BONUS_MASK = 0xBF, ITEMFLAG_CURSED = 0x40, ITEMFLAG_BROKEN = 0x80
+};
+
+enum ItemCategory {
+	CATEGORY_WEAPON = 0, CATEGORY_ARMOR = 1, CATEGORY_ACCESSORY = 2, CATEGORY_MISC = 3
+};
+
+enum Sex { MALE = 0, FEMALE = 1, YES_PLEASE = 2 };
+
+enum Race { HUMAN = 0, ELF = 1, DWARF = 2, GNOME = 3, HALF_ORC = 4 };
+
+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 Attribute {
+	MIGHT = 0, INTELLECT = 1, PERSONALITY = 2, ENDURANCE = 3, SPEED = 4,
+	ACCURACY = 5, LUCK = 6
+};
+
+enum Skill {
+	THIEVERY = 0, ARMS_MASTER = 1, ASTROLOGER = 2, BODYBUILDER = 3,
+	CARTOGRAPHER = 4, CRUSADER = 5, DIRECTION_SENSE = 6, LINGUIST = 7,
+	MERCHANT = 8, MOUNTAINEER = 9, NAVIGATOR = 10, PATHFINDER = 11,
+	PRAYER_MASTER = 12, PRESTIDIGITATION = 13, SWIMMING = 14, TRACKING = 15,
+	SPOT_DOORS = 16, DANGER_SENSE = 17
+};
+
+enum Condition {
+	CURSED = 0, HEART_BROKEN = 1, WEAK = 2, POISONED = 3,
+	DISEASED = 4, INSANE = 5, IN_LOVE = 6, DRUNK = 7, SLEEP = 8,
+	DEPRESSED = 9, CONFUSED = 10, PARALYZED = 11, UNCONSCIOUS = 12,
+	DEAD = 13, STONED = 14, ERADICATED = 15,
+	NO_CONDITION = 16
+};
+
+class XeenEngine;
+
+class XeenItem {
+public:
+	int _material;
+	uint _id;
+	int _bonusFlags;
+	int _frame;
+public:
+	XeenItem();
+
+	void clear();
+
+	void synchronize(Common::Serializer &s);
+
+	int getElementalCategory() const;
+
+	int getAttributeCategory() const;
+};
+
+class InventoryItems : public Common::Array<XeenItem> {
+public:
+	InventoryItems();
+
+	void discardItem(int itemIndex);
+
+	void equipItem(int itemIndex);
+
+	void removeItem(int itemIndex);
+
+	void sort();
+};
+
+class InventoryItemsGroup {
+private:
+	InventoryItems *_itemSets[4];
+public:
+	InventoryItemsGroup(InventoryItems &weapons, InventoryItems &armor,
+		InventoryItems &accessories, InventoryItems &misc);
+
+	InventoryItems &operator[](ItemCategory category);
+};
+
+
+class AttributePair {
+public:
+	uint _permanent;
+	uint _temporary;
+public:
+	AttributePair();
+	void synchronize(Common::Serializer &s);
+};
+
+class Character {
+private:
+	int conditionMod(Attribute attrib) const;
+public:
+	Common::String _name;
+	Sex _sex;
+	Race _race;
+	int _xeenSide;
+	CharacterClass _class;
+	AttributePair _might;
+	AttributePair _intellect;
+	AttributePair _personality;
+	AttributePair _endurance;
+	AttributePair _speed;
+	AttributePair _accuracy;
+	AttributePair _luck;
+	int _ACTemp;
+	AttributePair _level;
+	uint _birthDay;
+	int _tempAge;
+	int _skills[18];
+	bool _awards[128];
+	int _spells[39];
+	int _lloydMap;
+	Common::Point _lloydPosition;
+	bool _hasSpells;
+	int _currentSpell;
+	int _quickOption;
+	InventoryItemsGroup _items;
+	InventoryItems _weapons;
+	InventoryItems _armor;
+	InventoryItems _accessories;
+	InventoryItems _misc;
+	int _lloydSide;
+	AttributePair _fireResistence;
+	AttributePair _coldResistence;
+	AttributePair _electricityResistence;
+	AttributePair _poisonResistence;
+	AttributePair _energyResistence;
+	AttributePair _magicResistence;
+	int _conditions[16];
+	int _townUnknown;
+	int _savedMazeId;
+	int _currentHp;
+	int _currentSp;
+	uint _birthYear;
+	uint32 _experience;
+	int _currentAdventuringSpell;
+	int _currentCombatSpell;
+public:
+	Character();
+	void synchronize(Common::Serializer &s);
+
+	Condition worstCondition() const;
+
+	int getAge(bool ignoreTemp = false) const;
+
+	int getMaxHP() const;
+
+	int getMaxSP() const;
+
+	uint getStat(Attribute attrib, bool baseOnly = false) const;
+
+	static int statColor(int amount, int threshold);
+
+	int statBonus(uint statValue) const;
+
+	bool charSavingThrow(DamageType attackType) const;
+
+	bool noActions();
+
+	void setAward(int awardId, bool value);
+
+	bool hasAward(int awardId) const;
+
+	int getArmorClass(bool baseOnly = false) const;
+
+	int getThievery() const;
+
+	uint getCurrentLevel() const;
+
+	int itemScan(int itemId) const;
+
+	void setValue(int id, uint value);
+
+	bool guildMember() const;
+
+	uint experienceToNextLevel() const;
+
+	uint nextExperienceLevel() const;
+
+	uint getCurrentExperience() const;
+
+	int getNumSkills() const;
+
+	int getNumAwards() const;
+
+	Common::String assembleItemName(int itemIndex, int displayNum, ItemCategory category);
+};
+
+} // End of namespace Xeen
+
+#endif /* XEEN_CHARACTER_H */
diff --git a/engines/xeen/items.cpp b/engines/xeen/items.cpp
index 1341826..b9b531d 100644
--- a/engines/xeen/items.cpp
+++ b/engines/xeen/items.cpp
@@ -25,92 +25,6 @@
 
 namespace Xeen {
 
-XeenItem::XeenItem() {
-	clear();
-}
-
-void XeenItem::clear() {
-	_material = _id = _bonusFlags = 0;
-	_frame = 0;
-}
-
-void XeenItem::synchronize(Common::Serializer &s) {
-	s.syncAsByte(_material);
-	s.syncAsByte(_id);
-	s.syncAsByte(_bonusFlags);
-	s.syncAsByte(_frame);
-}
-
-int XeenItem::getElementalCategory() const {
-	int idx;
-	for (idx = 0; ELEMENTAL_CATEGORIES[idx] < _material; ++idx)
-		;
-
-	return idx;
-}
-
-int XeenItem::getAttributeCategory() const {
-	int m = _material - 59;
-	int idx;
-	for (idx = 0; ATTRIBUTE_CATEGORIES[idx] < m; ++idx)
-		;
-
-	return idx;
-}
-
-/*------------------------------------------------------------------------*/
-
-InventoryItems::InventoryItems() : Common::Array<XeenItem>((XeenItem *)nullptr, INV_ITEMS_TOTAL) {
-}
-
-void InventoryItems::discardItem(int itemIndex) {
-	operator[](itemIndex).clear();
-	sort();
-}
-
-void InventoryItems::sort() {
-	for (uint idx = 0; idx < size(); ++idx) {
-		if (operator[](idx)._id == 0) {
-			// Found empty slot
-			operator[](idx).clear();
-
-			// Scan through the rest of the list to find any item
-			for (uint idx2 = idx + 1; idx2 < size(); ++idx2) {
-				if (operator[](idx2)._id) {
-					// Found an item, so move it into the blank slot
-					operator[](idx) = operator[](idx2);
-					operator[](idx2).clear();
-					break;
-				}
-			}
-		}
-	}
-}
-
-void InventoryItems::equipItem(int itemIndex) {
-	error("TODO");
-}
-
-void InventoryItems::removeItem(int itemIndex) {
-	error("TODO");
-}
-
-/*------------------------------------------------------------------------*/
-
-InventoryItemsGroup::InventoryItemsGroup(InventoryItems &weapons, InventoryItems &armor,
-		InventoryItems &accessories, InventoryItems &misc) {
-	_itemSets[0] = &weapons;
-	_itemSets[1] = &armor;
-	_itemSets[2] = &accessories;
-	_itemSets[3] = &misc;
-}
-
-InventoryItems &InventoryItemsGroup::operator[](ItemCategory category) {
-	return *_itemSets[category];
-}
-
-/*------------------------------------------------------------------------*/
-
 Treasure::Treasure() {
 	_hasItems = false;
 }
diff --git a/engines/xeen/items.h b/engines/xeen/items.h
index c0b82b9..1e20861 100644
--- a/engines/xeen/items.h
+++ b/engines/xeen/items.h
@@ -23,63 +23,11 @@
 #ifndef XEEN_ITEMS_H
 #define XEEN_ITEMS_H
 
-#include "common/scummsys.h"
-#include "common/array.h"
-#include "common/serializer.h"
+#include "xeen/character.h"
 
 namespace Xeen {
 
 #define TOTAL_ITEMS 10
-#define INV_ITEMS_TOTAL 9
-
-enum BonusFlags { 
-	ITEMFLAG_BONUS_MASK = 0xBF,  ITEMFLAG_CURSED = 0x40, ITEMFLAG_BROKEN = 0x80 
-};
-
-enum ItemCategory {
-	CATEGORY_WEAPON = 0, CATEGORY_ARMOR = 1, CATEGORY_ACCESSORY = 2, CATEGORY_MISC = 3
-};
-
-class XeenItem {
-public:
-	int _material;
-	uint _id;
-	int _bonusFlags;
-	int _frame;
-public:
-	XeenItem();
-
-	void clear();
-
-	void synchronize(Common::Serializer &s);
-
-	int getElementalCategory() const;
-
-	int getAttributeCategory() const;
-};
-
-class InventoryItems : public Common::Array<XeenItem> {
-public:
-	InventoryItems();
-
-	void discardItem(int itemIndex);
-
-	void equipItem(int itemIndex);
-
-	void removeItem(int itemIndex);
-
-	void sort();
-};
-
-class InventoryItemsGroup {
-private:
-	InventoryItems *_itemSets[4];
-public:
-	InventoryItemsGroup(InventoryItems &weapons, InventoryItems &armor,
-		InventoryItems &accessories, InventoryItems &misc);
-
-	InventoryItems &operator[](ItemCategory category);
-};
 
 class Treasure {
 public:
diff --git a/engines/xeen/module.mk b/engines/xeen/module.mk
index c1cdd05..2556852 100644
--- a/engines/xeen/module.mk
+++ b/engines/xeen/module.mk
@@ -4,6 +4,7 @@ MODULE_OBJS := \
 	clouds\clouds_game.o \
 	darkside\darkside_game.o \
 	worldofxeen\worldofxeen_game.o \
+	character.o \
 	combat.o \
 	debugger.o \
 	detection.o \
diff --git a/engines/xeen/party.cpp b/engines/xeen/party.cpp
index 7d47eaf..be8f4e6 100644
--- a/engines/xeen/party.cpp
+++ b/engines/xeen/party.cpp
@@ -32,897 +32,6 @@
 
 namespace Xeen {
 
-AttributePair::AttributePair() {
-	_temporary = _permanent = 0;
-}
-
-void AttributePair::synchronize(Common::Serializer &s) {
-	s.syncAsByte(_permanent);
-	s.syncAsByte(_temporary);
-}
-
-/*------------------------------------------------------------------------*/
-
-Character::Character(): _items(_weapons, _armor, _accessories, _misc) {
-	_sex = MALE;
-	_race = HUMAN;
-	_xeenSide = 0;
-	_class = CLASS_KNIGHT;
-	_ACTemp = 0;
-	_birthDay = 0;
-	_tempAge = 0;
-	Common::fill(&_skills[0], &_skills[18], 0);
-	Common::fill(&_awards[0], &_awards[128], false);
-	Common::fill(&_spells[0], &_spells[39], 0);
-	_lloydMap = 0;
-	_hasSpells = false;
-	_currentSpell = 0;
-	_quickOption = 0;
-	_lloydSide = 0;
-	Common::fill(&_conditions[0], &_conditions[16], 0);
-	_townUnknown = 0;
-	_savedMazeId = 0;
-	_currentHp = 0;
-	_currentSp = 0;
-	_birthYear = 0;
-	_experience = 0;
-	_currentAdventuringSpell = 0;
-	_currentCombatSpell = 0;
-}
-
-void Character::synchronize(Common::Serializer &s) {
-	char name[16];
-	Common::fill(&name[0], &name[16], '\0');
-	strncpy(name, _name.c_str(), 16);
-	s.syncBytes((byte *)name, 16);
-
-	if (s.isLoading())
-		_name = Common::String(name);
-
-	s.syncAsByte(_sex);
-	s.syncAsByte(_race);
-	s.syncAsByte(_xeenSide);
-	s.syncAsByte(_class);
-
-	_might.synchronize(s);
-	_intellect.synchronize(s);
-	_personality.synchronize(s);
-	_endurance.synchronize(s);
-	_speed.synchronize(s);
-	_accuracy.synchronize(s);
-	_luck.synchronize(s);
-	s.syncAsByte(_ACTemp);
-	_level.synchronize(s);
-	s.syncAsByte(_birthDay);
-	s.syncAsByte(_tempAge);
-	
-	// Synchronize the skill list
-	for (int idx = 0; idx < 18; ++idx)
-		s.syncAsByte(_skills[idx]);
-
-	// Synchronize character awards
-	for (int idx = 0; idx < 64; ++idx) {
-		byte b = (_awards[idx] ? 1 : 0) | (_awards[idx + 64] ? 0x10 : 0);
-		s.syncAsByte(b);
-		if (s.isLoading()) {
-			_awards[idx] = (b & 0xF) != 0;
-			_awards[idx + 64] = (b & 0xF0) != 0;
-		}
-	}
-
-	// Synchronize spell list
-	for (int i = 0; i < MAX_SPELLS_PER_CLASS - 1; ++i)
-		s.syncAsByte(_spells[i]);	
-	s.syncAsByte(_lloydMap);
-	s.syncAsByte(_lloydPosition.x);
-	s.syncAsByte(_lloydPosition.y);
-	s.syncAsByte(_hasSpells);
-	s.syncAsByte(_currentSpell);
-	s.syncAsByte(_quickOption);
-
-	for (int i = 0; i < 9; ++i)
-		_weapons[i].synchronize(s);
-	for (int i = 0; i < 9; ++i)
-		_armor[i].synchronize(s);
-	for (int i = 0; i < 9; ++i)
-		_accessories[i].synchronize(s);
-	for (int i = 0; i < 9; ++i)
-		_misc[i].synchronize(s);
-
-	s.syncAsByte(_lloydSide);
-	_fireResistence.synchronize(s);
-	_coldResistence.synchronize(s);
-	_electricityResistence.synchronize(s);
-	_poisonResistence.synchronize(s);
-	_energyResistence.synchronize(s);
-	_magicResistence.synchronize(s);
-	
-	for (int i = 0; i < 16; ++i)
-		s.syncAsByte(_conditions[i]);
-
-	s.syncAsUint16LE(_townUnknown);
-	s.syncAsByte(_savedMazeId);
-	s.syncAsUint16LE(_currentHp);
-	s.syncAsUint16LE(_currentSp);
-	s.syncAsUint16LE(_birthYear);
-	s.syncAsUint32LE(_experience);
-	s.syncAsByte(_currentAdventuringSpell);
-	s.syncAsByte(_currentCombatSpell);
-}
-
-Condition Character::worstCondition() const {
-	for (int cond = ERADICATED; cond >= CURSED; --cond) {
-		if (_conditions[cond])
-			return (Condition)cond;
-	}
-
-	return NO_CONDITION;
-}
-
-int Character::getAge(bool ignoreTemp) const {
-	int year = MIN(Party::_vm->_party->_year - _birthYear, (uint)254);
-
-	return ignoreTemp ? year : year + _tempAge;
-}
-
-int Character::getMaxHP() const {
-	int hp = BASE_HP_BY_CLASS[_class];
-	hp += statBonus(getStat(ENDURANCE));
-	hp += RACE_HP_BONUSES[_race];
-	if (_skills[BODYBUILDER])
-		++hp;
-	if (hp < 1)
-		hp = 1;
-
-	hp *= getCurrentLevel();
-	hp += itemScan(7);
-
-	return MAX(hp, 0);
-}
-
-int Character::getMaxSP() const {
-	int result = 0;
-	bool flag = false;
-	int amount = 0;
-	Attribute attrib;
-	Skill skill;
-
-	if (!_hasSpells)
-		return 0;
-
-	if (_class == CLASS_SORCERER || _class == CLASS_ARCHER) {
-		attrib = INTELLECT;
-		skill = PRESTIDIGITATION;
-	} else {
-		attrib = PERSONALITY;
-		skill = PRAYER_MASTER;
-	}
-	if (_class == CLASS_DRUID || _class == CLASS_RANGER)
-		skill = ASTROLOGER;
-
-	for (;;) {
-		// Get the base number of spell points
-		result = statBonus(getStat(attrib)) + 3;
-		result += RACE_SP_BONUSES[_race][attrib - 1];
-
-		if (_skills[skill])
-			result += 2;
-		if (result < 1)
-			result = 1;
-
-		// Multiply it by the character's level
-		result *= getCurrentLevel();
-
-		// Classes other than sorcerer, clerics, and druids only get half the SP
-		if (_class != CLASS_SORCERER && _class != CLASS_CLERIC && _class != CLASS_DRUID)
-			result /= 2;
-
-		if (flag || (_class != CLASS_DRUID && _class != CLASS_RANGER))
-			break;
-
-		// Druids and rangers get bonuses averaged on both personality and intellect
-		attrib = INTELLECT;
-		flag = true;
-		amount = result;
-	}
-	if (flag)
-		result = (amount + result) / 2;
-
-	result += itemScan(8);
-	if (result < 0)
-		result = 0;
-
-	return result;
-}
-
-/**
- * Get the effective value of a given stat for the character
- */
-uint Character::getStat(Attribute attrib, bool baseOnly) const {
-	AttributePair attr;
-	int mode = 0;
-
-	switch (attrib) {
-	case MIGHT:
-		attr = _might;
-		break;
-	case INTELLECT:
-		attr = _intellect;
-		mode = 1;
-		break;
-	case PERSONALITY:
-		attr = _personality;
-		mode = 1;
-		break;
-	case ENDURANCE:
-		attr = _endurance;
-		break;
-	case SPEED:
-		attr = _speed;
-		break;
-	case ACCURACY:
-		attr = _accuracy;
-		break;
-	case LUCK:
-		attr = _luck;
-		mode = 2;
-		break;
-	default:
-		return 0;
-	}
-
-	// All the attributes except luck are affected by the character's age
-	if (mode < 2) {
-		int age = getAge(false);
-		int ageIndex = 0;
-		while (AGE_RANGES[ageIndex] <= age)
-			++ageIndex;
-
-		attr._permanent += AGE_RANGES_ADJUST[mode][ageIndex];
-	}
-
-
-	attr._permanent += itemScan((int)attrib);
-
-	if (!baseOnly) {
-		attr._permanent += conditionMod(attrib);
-		attr._permanent += attr._temporary;
-	}
-
-	return MAX(attr._permanent, (uint)0);
-}
-
-/**
- * Return the color number to use for a given stat value in the character
- * info or quick reference dialogs
- */
-int Character::statColor(int amount, int threshold) {
-	if (amount < 1)
-		return 6;
-	else if (amount > threshold)
-		return 2;
-	else if (amount == threshold)
-		return 15;
-	else if (amount <= (threshold / 4))
-		return 9;
-	else
-		return 32;
-}
-
-int Character::statBonus(uint statValue) const {
-	int idx;
-	for (idx = 0; STAT_VALUES[idx] <= statValue; ++idx)
-		;
-
-	return STAT_BONUSES[idx];
-}
-
-bool Character::charSavingThrow(DamageType attackType) const {
-	int v, vMax;
-
-	if (attackType == DT_PHYSICAL) {
-		v = statBonus(getStat(LUCK)) + getCurrentLevel();
-		vMax = v + 20;
-	} else {
-		switch (attackType) {
-		case DT_MAGICAL:
-			v = _magicResistence._permanent + _magicResistence._temporary + itemScan(16);
-			break;
-		case DT_FIRE:
-			v = _fireResistence._permanent + _fireResistence._temporary + itemScan(11);
-			break;
-		case DT_ELECTRICAL:
-			v = _electricityResistence._permanent + _electricityResistence._temporary + itemScan(12);
-			break;
-		case DT_COLD:
-			v = _coldResistence._permanent + _coldResistence._temporary + itemScan(13);
-			break;
-		case DT_POISON:
-			v = _poisonResistence._permanent + _poisonResistence._temporary + itemScan(14);
-			break;
-		case DT_ENERGY:
-			v = _energyResistence._permanent + _energyResistence._temporary + itemScan(15);
-			break;
-		default:
-			v = 0;
-			break;
-		}
-
-		vMax = v + 40;
-	}
-
-	return Party::_vm->getRandomNumber(1, vMax) <= v;
-}
-
-bool Character::noActions() {
-	Condition condition = worstCondition();
-
-	switch (condition) {
-	case CURSED:
-	case POISONED:
-	case DISEASED:
-	case INSANE:
-	case IN_LOVE:
-	case DRUNK: {
-		Common::String msg = Common::String::format(IN_NO_CONDITION, _name.c_str());
-		ErrorScroll::show(Party::_vm, msg, 
-			Party::_vm->_mode == 17 ? WT_2 : WT_NONFREEZED_WAIT);
-		return true;
-	}
-	default:
-		return false;
-	}
-}
-
-void Character::setAward(int awardId, bool value) {
-	int v = awardId;
-	if (awardId == 73)
-		v = 126;
-	else if (awardId == 81)
-		v = 127;
-
-	_awards[v] = value;
-}
-
-bool Character::hasAward(int awardId) const {
-	int v = awardId;
-	if (awardId == 73)
-		v = 126;
-	else if (awardId == 81)
-		v = 127;
-
-	return _awards[v];
-}
-
-int Character::getArmorClass(bool baseOnly) const {
-	Party &party = *Party::_vm->_party;
-
-	int result = statBonus(getStat(SPEED)) + itemScan(9);
-	if (!baseOnly)
-		result += party._blessed + _ACTemp;
-
-	return MAX(result, 0);
-}
-
-/**
- * Returns the thievery skill level, adjusted by class and race
- */
-int Character::getThievery() const {
-	int result = getCurrentLevel() * 2;
-
-	if (_class == CLASS_NINJA)
-		result += 15;
-	else if (_class == CLASS_ROBBER)
-		result += 30;
-
-	switch (_race) {
-	case ELF:
-	case GNOME:
-		result += 10;
-		break;
-	case DWARF:
-		result += 5;
-		break;
-	case HALF_ORC:
-		result -= 10;
-		break;
-	default:
-		break;
-	}
-
-	result += itemScan(10);
-
-	// If the character doesn't have a thievery skill, then do'nt allow any result
-	if (!_skills[THIEVERY])
-		result = 0;
-
-	return MAX(result, 0);
-}
-
-uint Character::getCurrentLevel() const {
-	return MAX(_level._permanent + _level._temporary, (uint)0);
-}
-
-int Character::itemScan(int itemId) const {
-	int result = 0;
-
-	for (int accessIdx = 0; accessIdx < 3; ++accessIdx) {
-		switch (accessIdx) {
-		case 0:
-			for (int idx = 0; idx < INV_ITEMS_TOTAL; ++idx) {
-				const XeenItem &item = _weapons[idx];
-
-				if (item._frame && !(item._bonusFlags & 0xC0) && itemId < 11
-						&& itemId != 3 && item._material >= 59 && item._material <= 130) {
-					int mIndex = item.getAttributeCategory();
-					if (mIndex > 2)
-						++mIndex;
-
-					if (mIndex == itemId)
-						result += ATTRIBUTE_BONUSES[item._material - 59];
-				}
-			}
-			break;
-
-		case 1:
-			for (int idx = 0; idx < INV_ITEMS_TOTAL; ++idx) {
-				const XeenItem &item = _armor[idx];
-
-				if (item._frame && !(item._bonusFlags & 0xC0)) {
-					if (itemId < 11 && itemId != 3 && item._material >= 59 && item._material <= 130) {
-						int mIndex = item.getAttributeCategory();
-						if (mIndex > 2)
-							++mIndex;
-
-						if (mIndex == itemId)
-							result += ATTRIBUTE_BONUSES[item._material - 59];
-					}
-
-					if (itemId > 10 && item._material < 37) {
-						int mIndex = item.getElementalCategory() + 11;
-
-						if (mIndex == itemId) {
-							result += ELEMENTAL_RESISTENCES[item._material];
-						}
-					}
-
-					if (itemId == 9) {
-						result += ARMOR_STRENGTHS[item._id];
-
-						if (item._material >= 37 && item._material <= 58)
-							result += METAL_LAC[item._material - 37];
-					}
-				}
-			}
-			break;
-
-		case 2:
-			for (int idx = 0; idx < INV_ITEMS_TOTAL; ++idx) {
-				const XeenItem &item = _accessories[idx];
-
-				if (item._frame && !(item._bonusFlags & 0xC0) && itemId < 11 && itemId != 3) {
-					if (item._material >= 59 && item._material <= 130) {
-						int mIndex = item.getAttributeCategory();
-						if (mIndex > 2)
-							++mIndex;
-
-						if (mIndex == itemId) {
-							result += ATTRIBUTE_BONUSES[item._material - 59];
-						}
-					}
-
-					if (itemId > 10 && item._material < 37) {
-						int mIndex = item.getElementalCategory() + 11;
-						
-						if (mIndex == itemId)
-							result += ELEMENTAL_RESISTENCES[item._material];
-					}
-				}
-			}
-			break;
-		}
-	};
-
-	return result;
-}
-
-/**
- * Modifies a passed attribute value based on player's condition
- */
-int Character::conditionMod(Attribute attrib) const {
-	if (_conditions[DEAD] || _conditions[STONED] || _conditions[ERADICATED])
-		return 0;
-
-	int v[7];
-	Common::fill(&v[0], &v[7], 0);
-	if (_conditions[CURSED])
-		v[6] -= _conditions[CURSED];
-
-	if (_conditions[INSANE]) {
-		v[2] -= _conditions[INSANE];
-		v[1] -= _conditions[INSANE];
-		v[5] -= _conditions[INSANE];
-		v[0] -= _conditions[INSANE];
-		v[4] -= _conditions[INSANE];
-	}
-
-	if (_conditions[POISONED]) {
-		v[0] -= _conditions[POISONED];
-		v[4] -= _conditions[POISONED];
-		v[5] -= _conditions[POISONED];
-	}
-
-	if (_conditions[DISEASED]) {
-		v[3] -= _conditions[DISEASED];
-		v[2] -= _conditions[DISEASED];
-		v[1] -= _conditions[DISEASED];
-	}
-
-	for (int idx = 0; idx < 7; ++idx) {
-		v[idx] -= _conditions[HEART_BROKEN];
-		v[idx] -= _conditions[IN_LOVE];
-		v[idx] -= _conditions[WEAK];
-		v[idx] -= _conditions[DRUNK];
-	}
-
-	return v[attrib];
-}
-
-void Character::setValue(int id, uint value) {
-	Party &party = *Party::_vm->_party;
-	Scripts &scripts = *Party::_vm->_scripts;
-
-	switch (id) {
-	case 3:
-		// Set character sex
-		_sex = (Sex)value;
-		break;
-	case 4:
-		// Set race
-		_race = (Race)value;
-		break;
-	case 5:
-		// Set class
-		_class = (CharacterClass)value;
-		break;
-	case 8:
-		// Set the current Hp
-		_currentHp = value;
-		break;
-	case 9:
-		// Set the current Sp
-		_currentSp = value;
-		break;
-	case 10:
-	case 77:
-		// Set temporary armor class
-		_ACTemp = value;
-		break;
-	case 11:
-		// Set temporary level
-		_level._temporary = value;
-		break;
-	case 12:
-		// Set the character's temporary age
-		_tempAge = value;
-		break;
-	case 16:
-		// Set character experience
-		_experience = value;
-		break;
-	case 17:
-		// Set party poison resistence
-		party._poisonResistence = value;
-		break;
-	case 18:
-		// Set condition
-		if (value == 16) {
-			// Clear all the conditions
-			Common::fill(&_conditions[CURSED], &_conditions[NO_CONDITION], false);
-		} else if (value == 6) {
-			_conditions[value] = 1;
-		} else {
-			++_conditions[value];
-		}
-
-		if (value >= DEAD && value <= ERADICATED && _currentHp > 0)
-			_currentHp = 0;
-		break;
-	case 25:
-		// Set time of day in minutes (0-1440)
-		party._minutes = value;
-		break;
-	case 34:
-		// Set party gold
-		party._gold = value;
-		break;
-	case 35:
-		// Set party gems
-		party._gems = value;
-		break;
-	case 37:
-		_might._temporary = value;
-		break;
-	case 38:
-		_intellect._temporary = value;
-		break;
-	case 39:
-		_personality._temporary = value;
-		break;
-	case 40:
-		_endurance._temporary = value;
-		break;
-	case 41:
-		_speed._temporary = value;
-		break;
-	case 42:
-		_accuracy._temporary = value;
-		break;
-	case 43:
-		_luck._temporary = value;
-		break;
-	case 45:
-		_might._permanent = value;
-		break;
-	case 46:
-		_intellect._permanent = value;
-		break;
-	case 47:
-		_personality._permanent = value;
-		break;
-	case 48:
-		_endurance._permanent = value;
-		break;
-	case 49:
-		_speed._permanent = value;
-		break;
-	case 50:
-		_accuracy._permanent = value;
-		break;
-	case 51:
-		_luck._permanent = value;
-		break;
-	case 52:
-		_fireResistence._permanent = value;
-		break;
-	case 53:
-		_electricityResistence._permanent = value;
-		break;
-	case 54:
-		_coldResistence._permanent = value;
-		break;
-	case 55:
-		_poisonResistence._permanent = value;
-		break;
-	case 56:
-		_energyResistence._permanent = value;
-		break;
-	case 57:
-		_magicResistence._permanent = value;
-		break;
-	case 58:
-		_fireResistence._temporary = value;
-		break;
-	case 59:
-		_electricityResistence._temporary = value;
-		break;
-	case 60:
-		_coldResistence._temporary = value;
-		break;
-	case 61:
-		_poisonResistence._temporary = value;
-		break;
-	case 62:
-		_energyResistence._temporary = value;
-		break;
-	case 63:
-		_magicResistence._temporary = value;
-		break;
-	case 64:
-		_level._permanent = value;
-		break;
-	case 65:
-		// Set party food
-		party._food = value;
-		break;
-	case 69:
-		// Set levitate active
-		party._levitateActive = value != 0;
-		break;
-	case 70:
-		party._lightCount = value;
-		break;
-	case 71:
-		party._fireResistence = value;
-		break;
-	case 72:
-		party._electricityResistence = value;
-		break;
-	case 73:
-		party._coldResistence = value;
-		break;
-	case 74:
-		party._walkOnWaterActive = value != 0;
-		party._poisonResistence = value;
-		party._wizardEyeActive = value != 0;
-		party._coldResistence = value;
-		party._electricityResistence = value;
-		party._fireResistence = value;
-		party._lightCount = value;
-		party._levitateActive = value != 0;
-		break;
-	case 76:
-		// Set day of the year (0-99)
-		party._day = value;
-		break;
-	case 79:
-		party._wizardEyeActive = true;
-		break;
-	case 83:
-		scripts._nEdamageType = value;
-		break;
-	case 84:
-		party._mazeDirection = (Direction)value;
-		break;
-	case 85:
-		party._year = value;
-		break;
-	case 94:
-		party._walkOnWaterActive = value != 0;
-		break;
-	default:
-		break;
-	}
-}
-
-bool Character::guildMember() const {
-	Party &party = *Party::_vm->_party;
-
-	if (party._mazeId == 49 && !Party::_vm->_files->_isDarkCc) {
-		return hasAward(5);
-	}
-
-	switch (party._mazeId) {
-	case 29:
-		return hasAward(83);
-	case 31:
-		return hasAward(84);
-	case 33:
-		return hasAward(85);
-	case 35:
-		return hasAward(86);
-	default:
-		return hasAward(87);
-	}
-}
-
-uint Character::experienceToNextLevel() const {
-	uint next = nextExperienceLevel();
-	uint curr = getCurrentExperience();
-	return (curr >= next) ? 0 : next - curr;
-}
-
-uint Character::nextExperienceLevel() const {
-	int shift, base;
-	if (_level._permanent >= 12) {
-		base = _level._permanent - 12;
-		shift = 10;
-	} else {
-		base = 0;
-		shift = _level._permanent - 1;
-	}
-
-	return (base * 1024000) + (CLASS_EXP_LEVELS[_class] << shift);
-}
-
-uint Character::getCurrentExperience() const {
-	int lev = _level._permanent - 1;
-	int shift, base;
-
-	if (lev > 0 && lev < 12)
-		return _experience;
-
-	if (lev >= 12) {
-		base = lev - 12;
-		shift = 10;
-	} else {
-		base = 0;
-		shift = lev - 1;
-	}
-
-	return (base * 1024000) + (CLASS_EXP_LEVELS[_class] << shift) +
-		_experience;
-}
-
-
-int Character::getNumSkills() const {
-	int total = 0;
-	for (int idx = THIEVERY; idx <= DANGER_SENSE; ++idx) {
-		if (_skills[idx])
-			++total;
-	}
-
-	return total;
-}
-
-int Character::getNumAwards() const {
-	int total = 0;
-	for (int idx = 0; idx < 88; ++idx) {
-		if (hasAward(idx))
-			++total;
-	}
-
-	return total;
-}
-
-/**
- * Assembles a full lines description for a specified item for use in
- * the Items dialog
- */
-Common::String Character::assembleItemName(int itemIndex, int displayNum, 
-		ItemCategory category) {
-	Spells &spells = *Party::_vm->_spells;
-
-	switch (category) {
-	case CATEGORY_WEAPON: {
-		// Weapons
-		XeenItem &i = _weapons[itemIndex];
-		return Common::String::format("\f%02u%s%s%s\f%02u%s%s%s", displayNum,
-			!i._bonusFlags ? spells._maeNames[i._material] : "",
-			(i._bonusFlags & ITEMFLAG_BROKEN) ? ITEM_BROKEN : "",
-			(i._bonusFlags & ITEMFLAG_CURSED) ? ITEM_CURSED : "",
-			WEAPON_NAMES[i._id],
-			!i._bonusFlags ? "" : BONUS_NAMES[i._bonusFlags & ITEMFLAG_BONUS_MASK],
-			(i._bonusFlags & (ITEMFLAG_BROKEN | ITEMFLAG_CURSED)) || 
-				!i._bonusFlags ? "\b " : ""
-		);
-	}
-
-	case CATEGORY_ARMOR: {
-		// Armor
-		XeenItem &i = _armor[itemIndex];
-		return Common::String::format("\f%02u%s%s%s\f%02u%s%s", displayNum,
-			!i._bonusFlags ? "" : spells._maeNames[i._material],
-			(i._bonusFlags & ITEMFLAG_BROKEN) ? ITEM_BROKEN : "",
-			(i._bonusFlags & ITEMFLAG_CURSED) ? ITEM_CURSED : "",
-			ARMOR_NAMES[i._id],
-			(i._bonusFlags & (ITEMFLAG_BROKEN | ITEMFLAG_CURSED)) ||
-				!i._bonusFlags ? "\b " : ""
-		);
-	}
-		
-	case CATEGORY_ACCESSORY: {
-		// Accessories
-		XeenItem &i = _accessories[itemIndex];
-		return Common::String::format("\f%02u%s%s%s\f%02u%s%s", displayNum,
-			!i._bonusFlags ? "" : spells._maeNames[i._material],
-			(i._bonusFlags & ITEMFLAG_BROKEN) ? ITEM_BROKEN : "",
-			(i._bonusFlags & ITEMFLAG_CURSED) ? ITEM_CURSED : "",
-			ARMOR_NAMES[i._id],
-			(i._bonusFlags & (ITEMFLAG_BROKEN | ITEMFLAG_CURSED)) ||
-				!i._bonusFlags ? "\b " : ""
-		);
-	}
-
-	case CATEGORY_MISC: {
-		// Misc
-		XeenItem &i = _misc[itemIndex];
-		return Common::String::format("\f%02u%s%s%s\f%02u%s%s", displayNum,
-			!i._bonusFlags ? "" : spells._maeNames[i._material],
-			(i._bonusFlags & ITEMFLAG_BROKEN) ? ITEM_BROKEN : "",
-			(i._bonusFlags & ITEMFLAG_CURSED) ? ITEM_CURSED : "",
-			ARMOR_NAMES[i._id],
-			(i._bonusFlags & (ITEMFLAG_BROKEN | ITEMFLAG_CURSED)) ||
-				!i._id ? "\b " : ""
-		);
-	}
-	default:
-		return "";
-	}
-}
-
-/*------------------------------------------------------------------------*/
-
 void Roster::synchronize(Common::Serializer &s) {
 	if (s.isLoading())
 		resize(30);
diff --git a/engines/xeen/party.h b/engines/xeen/party.h
index 73de706..138ecba 100644
--- a/engines/xeen/party.h
+++ b/engines/xeen/party.h
@@ -39,153 +39,12 @@ enum Direction {
 
 enum Difficulty { ADVENTURER = 0, WARRIOR = 1 };
 
-enum Sex { MALE = 0, FEMALE = 1, YES_PLEASE = 2 };
-
-enum Race { HUMAN = 0, ELF = 1, DWARF = 2, GNOME = 3, HALF_ORC = 4 };
-
-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 Attribute{
-	MIGHT = 0, INTELLECT = 1, PERSONALITY = 2, ENDURANCE = 3, SPEED = 4,
-	ACCURACY = 5, LUCK = 6
-};
-
-enum Skill { THIEVERY = 0, ARMS_MASTER = 1, ASTROLOGER = 2, BODYBUILDER = 3,
-	CARTOGRAPHER = 4, CRUSADER = 5, DIRECTION_SENSE = 6, LINGUIST = 7, 
-	MERCHANT = 8, MOUNTAINEER = 9, NAVIGATOR = 10, PATHFINDER = 11,
-	PRAYER_MASTER = 12, PRESTIDIGITATION = 13, SWIMMING = 14, TRACKING = 15,
-	SPOT_DOORS = 16, DANGER_SENSE = 17
-};
-
-enum Condition { CURSED = 0, HEART_BROKEN = 1, WEAK = 2, POISONED = 3,
-	DISEASED = 4, INSANE = 5, IN_LOVE = 6, DRUNK = 7, SLEEP = 8, 
-	DEPRESSED = 9, CONFUSED = 10, PARALYZED = 11, UNCONSCIOUS = 12,
-	DEAD = 13, STONED = 14, ERADICATED = 15,
-	NO_CONDITION = 16
-};
-
 #define ITEMS_COUNT 36
 #define TOTAL_CHARACTERS 30
 #define XEEN_TOTAL_CHARACTERS 24
 #define MAX_ACTIVE_PARTY 6
 #define TOTAL_STATS 7
 
-class XeenEngine;
-
-class AttributePair {
-public:	
-	uint _permanent;
-	uint _temporary;
-public:
-	AttributePair();
-	void synchronize(Common::Serializer &s);
-};
-
-class Character {
-private:
-	int conditionMod(Attribute attrib) const;
-public:
-	Common::String _name;
-	Sex _sex;
-	Race _race;
-	int _xeenSide;
-	CharacterClass _class;
-	AttributePair _might;
-	AttributePair _intellect;
-	AttributePair _personality;
-	AttributePair _endurance;
-	AttributePair _speed;
-	AttributePair _accuracy;
-	AttributePair _luck;
-	int _ACTemp;
-	AttributePair _level;
-	uint _birthDay;
-	int _tempAge;
-	int _skills[18];
-	bool _awards[128];
-	int _spells[39];
-	int _lloydMap;
-	Common::Point _lloydPosition;
-	bool _hasSpells;
-	int _currentSpell;
-	int _quickOption;
-	InventoryItemsGroup _items;
-	InventoryItems _weapons;
-	InventoryItems _armor;
-	InventoryItems _accessories;
-	InventoryItems _misc;
-	int _lloydSide;
-	AttributePair _fireResistence;
-	AttributePair _coldResistence;
-	AttributePair _electricityResistence;
-	AttributePair _poisonResistence;
-	AttributePair _energyResistence;
-	AttributePair _magicResistence;
-	int _conditions[16];
-	int _townUnknown;
-	int _savedMazeId;
-	int _currentHp;
-	int _currentSp;
-	uint _birthYear;
-	uint32 _experience;
-	int _currentAdventuringSpell;
-	int _currentCombatSpell;
-public:
-	Character();
-	void synchronize(Common::Serializer &s);
-
-	Condition worstCondition() const;
-
-	int getAge(bool ignoreTemp = false) const;
-
-	int getMaxHP() const;
-
-	int getMaxSP() const;
-
-	uint getStat(Attribute attrib, bool baseOnly = false) const;
-
-	static int statColor(int amount, int threshold);
-
-	int statBonus(uint statValue) const;
-
-	bool charSavingThrow(DamageType attackType) const;
-
-	bool noActions();
-
-	void setAward(int awardId, bool value);
-
-	bool hasAward(int awardId) const;
-
-	int getArmorClass(bool baseOnly = false) const;
-
-	int getThievery() const;
-
-	uint getCurrentLevel() const;
-
-	int itemScan(int itemId) const;
-
-	void setValue(int id, uint value);
-
-	bool guildMember() const;
-
-	uint experienceToNextLevel() const;
-
-	uint nextExperienceLevel() const;
-
-	uint getCurrentExperience() const;
-
-	int getNumSkills() const;
-
-	int getNumAwards() const;
-	
-	Common::String assembleItemName(int itemIndex, int displayNum, ItemCategory category);
-};
-
 class Roster: public Common::Array<Character> {
 public:
 	Roster() {}


Commit: 7ea32f3333cb2123675f6dbdfae3ed232347d1a5
    https://github.com/scummvm/scummvm/commit/7ea32f3333cb2123675f6dbdfae3ed232347d1a5
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-02-04T20:41:17-05:00

Commit Message:
XEEN: Moved passRestrictions to the InventoryItems class

Changed paths:
    engines/xeen/character.cpp
    engines/xeen/character.h
    engines/xeen/dialogs_items.cpp
    engines/xeen/dialogs_items.h
    engines/xeen/party.h



diff --git a/engines/xeen/character.cpp b/engines/xeen/character.cpp
index f712e78..02c578a 100644
--- a/engines/xeen/character.cpp
+++ b/engines/xeen/character.cpp
@@ -61,10 +61,56 @@ int XeenItem::getAttributeCategory() const {
 
 /*------------------------------------------------------------------------*/
 
-InventoryItems::InventoryItems() {
+InventoryItems::InventoryItems(Character *character, ItemCategory category):
+		_character(character), _category(category) {
 	resize(INV_ITEMS_TOTAL);
+
+	static const char *const *NAMES[4] = { 
+		WEAPON_NAMES, ARMOR_NAMES, ACCESSORY_NAMES, MISC_NAMES 
+	};
+	_names = NAMES[category];
 }
 
+/**
+* Return whether a given item passes class-based usage restrictions
+*/
+bool InventoryItems::passRestrictions(int itemId, bool showError) const {
+	CharacterClass charClass = _character->_class;
+
+	switch (charClass) {
+	case CLASS_KNIGHT:
+	case CLASS_PALADIN:
+		return true;
+
+	case CLASS_ARCHER:
+	case CLASS_CLERIC:
+	case CLASS_SORCERER:
+	case CLASS_ROBBER:
+	case CLASS_NINJA:
+	case CLASS_BARBARIAN:
+	case CLASS_DRUID:
+	case CLASS_RANGER: {
+		if (!(ITEM_RESTRICTIONS[itemId + RESTRICTION_OFFSETS[_category]] &
+			(1 << (charClass - CLASS_ARCHER))))
+			return true;
+		break;
+	}
+
+	default:
+		break;
+	}
+
+	Common::String name = _names[itemId];
+	if (showError) {
+		Common::String msg = Common::String::format(NOT_PROFICIENT,
+			CLASS_NAMES[charClass], name.c_str());
+		ErrorScroll::show(Party::_vm, msg, WT_FREEZE_WAIT);
+	}
+
+	return false;
+}
+
+
 void InventoryItems::discardItem(int itemIndex) {
 	operator[](itemIndex).clear();
 	sort();
@@ -127,7 +173,10 @@ AttributePair::AttributePair() {
 
 /*------------------------------------------------------------------------*/
 
-Character::Character(): _items(_weapons, _armor, _accessories, _misc) {
+Character::Character():
+		_weapons(this, CATEGORY_WEAPON), _armor(this, CATEGORY_ARMOR),
+		_accessories(this, CATEGORY_ACCESSORY), _misc(this, CATEGORY_MISC),
+		_items(_weapons, _armor, _accessories, _misc) {
 	_sex = MALE;
 	_race = HUMAN;
 	_xeenSide = 0;
diff --git a/engines/xeen/character.h b/engines/xeen/character.h
index 54da44a..b3c9965 100644
--- a/engines/xeen/character.h
+++ b/engines/xeen/character.h
@@ -74,6 +74,7 @@ enum Condition {
 };
 
 class XeenEngine;
+class Character;
 
 class XeenItem {
 public:
@@ -94,8 +95,14 @@ public:
 };
 
 class InventoryItems : public Common::Array<XeenItem> {
+private:
+	Character *_character;
+	ItemCategory _category;
+	const char *const *_names;
 public:
-	InventoryItems();
+	InventoryItems(Character *character, ItemCategory category);
+
+	bool passRestrictions(int itemId, bool showError) const;
 
 	void discardItem(int itemIndex);
 
diff --git a/engines/xeen/dialogs_items.cpp b/engines/xeen/dialogs_items.cpp
index 634fb2d..c28085c 100644
--- a/engines/xeen/dialogs_items.cpp
+++ b/engines/xeen/dialogs_items.cpp
@@ -154,7 +154,7 @@ Character *ItemsDialog::execute(Character *c, ItemsMode mode) {
 
 					DrawStruct &ds = _itemsDrawList[idx];
 					ds._sprites = &_equipSprites;
-					if (passRestrictions(c->_class, i._id, true, CATEGORY_WEAPON))
+					if (c->_weapons.passRestrictions(i._id, true))
 						ds._frame = i._frame;
 					else
 						ds._frame = 14;
@@ -537,59 +537,6 @@ int ItemsDialog::calcItemCost(Character *c, int itemIndex, ItemsMode mode,
 	return (mode == ITEMMODE_CHAR_INFO) ? 0 : result;
 }
 
-/**
- * Return whether a given item passes class-based usage restrictions
- */
-bool ItemsDialog::passRestrictions(CharacterClass charClass, int itemId, 
-		bool showError, ItemCategory category) const {
-	switch (charClass) {
-	case CLASS_KNIGHT:
-	case CLASS_PALADIN:
-		return true;
-
-	case CLASS_ARCHER:
-	case CLASS_CLERIC:
-	case CLASS_SORCERER:
-	case CLASS_ROBBER:
-	case CLASS_NINJA:
-	case CLASS_BARBARIAN:
-	case CLASS_DRUID:
-	case CLASS_RANGER: {
-		if (!(ITEM_RESTRICTIONS[itemId + RESTRICTION_OFFSETS[category]] &
-				(1 << (charClass - CLASS_ARCHER))))
-			return true;
-		break;
-	}
-
-	default:
-		break;
-	}
-	
-	Common::String name;
-	switch (category) {
-	case CATEGORY_WEAPON:
-		name = WEAPON_NAMES[itemId];
-		break;
-	case CATEGORY_ARMOR:
-		name = ARMOR_NAMES[itemId];
-		break;
-	case CATEGORY_ACCESSORY:
-		name = ACCESSORY_NAMES[itemId];
-		break;
-	case CATEGORY_MISC:
-		name = MISC_NAMES[itemId];
-		break;
-	}
-
-	if (showError) {
-		Common::String msg = Common::String::format(NOT_PROFICIENT, 
-			CLASS_NAMES[charClass], name.c_str());
-		ErrorScroll::show(_vm, msg, WT_FREEZE_WAIT);
-	}
-
-	return false;
-}
-
 bool ItemsDialog::doItemOptions(Character &c, int actionIndex, int itemIndex, ItemCategory category,
 		ItemsMode mode) {
 	Combat &combat = *_vm->_combat;
diff --git a/engines/xeen/dialogs_items.h b/engines/xeen/dialogs_items.h
index c30eaa9..aff43f6 100644
--- a/engines/xeen/dialogs_items.h
+++ b/engines/xeen/dialogs_items.h
@@ -58,9 +58,6 @@ private:
 	int calcItemCost(Character *c, int itemIndex, ItemsMode mode, int skillLevel, 
 		ItemCategory category);
 
-	bool passRestrictions(CharacterClass charClass, int itemId,
-		bool showError, ItemCategory category) const;
-
 	bool doItemOptions(Character &c, int actionIndex, int itemIndex, 
 		ItemCategory category, ItemsMode mode);
 public:
diff --git a/engines/xeen/party.h b/engines/xeen/party.h
index 138ecba..8da1163 100644
--- a/engines/xeen/party.h
+++ b/engines/xeen/party.h
@@ -27,6 +27,7 @@
 #include "common/array.h"
 #include "common/rect.h"
 #include "common/serializer.h"
+#include "xeen/character.h"
 #include "xeen/combat.h"
 #include "xeen/dialogs_error.h"
 #include "xeen/items.h"
@@ -54,6 +55,7 @@ public:
 
 class Party {
 	friend class Character;
+	friend class InventoryItems;
 private:
 	static XeenEngine *_vm;
 public:


Commit: a983d9abcea603a3857c1c250f398e6b2fae29a0
    https://github.com/scummvm/scummvm/commit/a983d9abcea603a3857c1c250f398e6b2fae29a0
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-02-04T22:24:45-05:00

Commit Message:
XEEN: Implemented weapon variation of equipItem

Changed paths:
    engines/xeen/character.cpp
    engines/xeen/character.h
    engines/xeen/dialogs_error.cpp
    engines/xeen/dialogs_error.h
    engines/xeen/resources.cpp
    engines/xeen/resources.h
    engines/xeen/spells.cpp



diff --git a/engines/xeen/character.cpp b/engines/xeen/character.cpp
index 02c578a..00b7e43 100644
--- a/engines/xeen/character.cpp
+++ b/engines/xeen/character.cpp
@@ -21,6 +21,7 @@
  */
 
 #include "xeen/character.h"
+#include "xeen/dialogs_error.h"
 #include "xeen/resources.h"
 #include "xeen/xeen.h"
 
@@ -110,12 +111,25 @@ bool InventoryItems::passRestrictions(int itemId, bool showError) const {
 	return false;
 }
 
+/**
+ * Return the bare name of a given inventory item
+ */
+Common::String InventoryItems::getName(int itemIndex) {
+	int id = operator[](itemIndex)._id;
+	return _names[id];
+}
 
+/**
+ * Discard an item from the inventory
+ */
 void InventoryItems::discardItem(int itemIndex) {
 	operator[](itemIndex).clear();
 	sort();
 }
 
+/**
+ * Sorts the items list, removing any empty item slots to the end of the array
+ */
 void InventoryItems::sort() {
 	for (uint idx = 0; idx < size(); ++idx) {
 		if (operator[](idx)._id == 0) {
@@ -135,16 +149,91 @@ void InventoryItems::sort() {
 	}
 }
 
-void InventoryItems::equipItem(int itemIndex) {
+void InventoryItems::removeItem(int itemIndex) {
 	error("TODO");
 }
 
-void InventoryItems::removeItem(int itemIndex) {
+void InventoryItems::equipError(int itemIndex1, ItemCategory category1, int itemIndex2,
+		ItemCategory category2) {
+	XeenEngine *vm = Party::_vm;
+
+	if (itemIndex1 >= 0) {
+		Common::String itemName1 = _character->_items[category1].getName(itemIndex1);
+		Common::String itemName2 = _character->_items[category2].getName(itemIndex2);
+
+		ErrorDialog::show(vm, Common::String::format(REMOVE_X_TO_EQUIP_Y,
+			itemName1.c_str(), itemName2.c_str()));
+	} else {
+		ErrorDialog::show(vm, Common::String::format(EQUIPPED_ALL_YOU_CAN,
+			(itemIndex1 == -1) ? RING : MEDAL));
+	}
+}
+
+/*------------------------------------------------------------------------*/
+
+void WeaponItems::equipItem(int itemIndex) {
+	XeenItem &item = operator[](itemIndex);
+
+	if (item._id <= 17) {
+		if (passRestrictions(item._id, false)) {
+			for (uint idx = 0; idx < size(); ++idx) {
+				XeenItem &i = operator[](idx);
+				if (i._frame == 13 || i._frame == 1) {
+					equipError(itemIndex, CATEGORY_WEAPON, idx, CATEGORY_WEAPON);
+					return;
+				}
+			}
+
+			item._frame = 1;
+		}
+	} else if (item._id >= 30 && item._id <= 33) {
+		if (passRestrictions(item._id, false)) {
+			for (uint idx = 0; idx < size(); ++idx) {
+				XeenItem &i = operator[](idx);
+				if (i._frame == 4) {
+					equipError(itemIndex, CATEGORY_WEAPON, idx, CATEGORY_WEAPON);
+					return;
+				}
+			}
+
+			item._frame = 4;
+		}
+	} else {
+		if (passRestrictions(item._id, false)) {
+			for (uint idx = 0; idx < size(); ++idx) {
+				XeenItem &i = operator[](idx);
+				if (i._frame == 13 || i._frame == 1) {
+					equipError(itemIndex, CATEGORY_WEAPON, idx, CATEGORY_WEAPON);
+					return;
+				}
+			}
+
+			for (uint idx = 0; idx < size(); ++idx) {
+				XeenItem &i = _character->_armor[idx];
+				if (i._frame == 2) {
+					equipError(itemIndex, CATEGORY_ARMOR, idx, CATEGORY_WEAPON);
+					return;
+				}
+			}
+
+			item._frame = 13;
+		}
+	}
+}
+
+/*------------------------------------------------------------------------*/
+
+void ArmorItems::equipItem(int itemIndex) {
 	error("TODO");
 }
 
 /*------------------------------------------------------------------------*/
 
+void AccessoryItems::equipItem(int itemIndex) {
+	error("TODO");
+}
+/*------------------------------------------------------------------------*/
+
 InventoryItemsGroup::InventoryItemsGroup(InventoryItems &weapons, InventoryItems &armor,
 		InventoryItems &accessories, InventoryItems &misc) {
 	_itemSets[0] = &weapons;
@@ -174,8 +263,7 @@ AttributePair::AttributePair() {
 /*------------------------------------------------------------------------*/
 
 Character::Character():
-		_weapons(this, CATEGORY_WEAPON), _armor(this, CATEGORY_ARMOR),
-		_accessories(this, CATEGORY_ACCESSORY), _misc(this, CATEGORY_MISC),
+		_weapons(this), _armor(this), _accessories(this), _misc(this),
 		_items(_weapons, _armor, _accessories, _misc) {
 	_sex = MALE;
 	_race = HUMAN;
diff --git a/engines/xeen/character.h b/engines/xeen/character.h
index b3c9965..c4eae0e 100644
--- a/engines/xeen/character.h
+++ b/engines/xeen/character.h
@@ -95,24 +95,52 @@ public:
 };
 
 class InventoryItems : public Common::Array<XeenItem> {
-private:
+protected:
 	Character *_character;
 	ItemCategory _category;
 	const char *const *_names;
+
+	void equipError(int itemIndex1, ItemCategory category1, int itemIndex2,
+		ItemCategory category2);
 public:
 	InventoryItems(Character *character, ItemCategory category);
 
 	bool passRestrictions(int itemId, bool showError) const;
 
+	Common::String getName(int itemIndex);
+
 	void discardItem(int itemIndex);
 
-	void equipItem(int itemIndex);
+	virtual void equipItem(int itemIndex) {}
 
 	void removeItem(int itemIndex);
 
 	void sort();
 };
 
+class WeaponItems: public InventoryItems {
+public:
+	WeaponItems(Character *character) : InventoryItems(character, CATEGORY_WEAPON) {}
+	virtual void equipItem(int itemIndex);
+};
+
+class ArmorItems : public InventoryItems {
+public:
+	ArmorItems(Character *character) : InventoryItems(character, CATEGORY_ARMOR) {}
+	virtual void equipItem(int itemIndex);
+};
+
+class AccessoryItems : public InventoryItems {
+public:
+	AccessoryItems(Character *character) : InventoryItems(character, CATEGORY_ACCESSORY) {}
+	virtual void equipItem(int itemIndex);
+};
+
+class MiscItems : public InventoryItems {
+public:
+	MiscItems(Character *character) : InventoryItems(character, CATEGORY_MISC) {}
+};
+
 class InventoryItemsGroup {
 private:
 	InventoryItems *_itemSets[4];
@@ -162,10 +190,10 @@ public:
 	int _currentSpell;
 	int _quickOption;
 	InventoryItemsGroup _items;
-	InventoryItems _weapons;
-	InventoryItems _armor;
-	InventoryItems _accessories;
-	InventoryItems _misc;
+	WeaponItems _weapons;
+	ArmorItems _armor;
+	AccessoryItems _accessories;
+	MiscItems _misc;
 	int _lloydSide;
 	AttributePair _fireResistence;
 	AttributePair _coldResistence;
diff --git a/engines/xeen/dialogs_error.cpp b/engines/xeen/dialogs_error.cpp
index a58e0e9..598af1e 100644
--- a/engines/xeen/dialogs_error.cpp
+++ b/engines/xeen/dialogs_error.cpp
@@ -27,29 +27,19 @@
 
 namespace Xeen {
 
-void ErrorScroll::show(XeenEngine *vm, const Common::String &msg, ErrorWaitType waitType) {
-	ErrorScroll *dlg = new ErrorScroll(vm);
+void ErrorDialog::show(XeenEngine *vm, const Common::String &msg, ErrorWaitType waitType) {
+	ErrorDialog *dlg = new ErrorDialog(vm);
 	dlg->execute(msg, waitType);
 	delete dlg;
 }
 
-void ErrorScroll::execute(const Common::String &msg, ErrorWaitType waitType) {
+void ErrorDialog::execute(const Common::String &msg, ErrorWaitType waitType) {
 	Screen &screen = *_vm->_screen;
 	EventsManager &events = *_vm->_events;
 	Window &w = screen._windows[6];
 
-	Common::String s;
-	if (waitType == WT_UNFORMATTED) {
-		// This type isn't technically a waiting type, but it saved on adding 
-		// yet another parameter
-		waitType = WT_FREEZE_WAIT;
-		s = msg;
-	} else {
-		s = Common::String::format("\x03c\v010\t000%s", msg.c_str());
-	}
-
 	w.open();
-	w.writeString(s);
+	w.writeString(msg);
 	w.update();
 
 	switch (waitType) {
@@ -83,4 +73,11 @@ void ErrorScroll::execute(const Common::String &msg, ErrorWaitType waitType) {
 	}
 }
 
+/*------------------------------------------------------------------------*/
+
+void ErrorScroll::show(XeenEngine *vm, const Common::String &msg, ErrorWaitType waitType) {
+	Common::String s = Common::String::format("\x03c\v010\t000%s", msg.c_str());
+	ErrorDialog::show(vm, s, waitType);
+}
+
 } // End of namespace Xeen
diff --git a/engines/xeen/dialogs_error.h b/engines/xeen/dialogs_error.h
index 1a86afc..644b7e3 100644
--- a/engines/xeen/dialogs_error.h
+++ b/engines/xeen/dialogs_error.h
@@ -24,20 +24,27 @@
 #define XEEN_DIALOGS_ERROR_H
 
 #include "xeen/dialogs.h"
+#include "xeen/character.h"
 
 namespace Xeen {
 
 enum ErrorWaitType { WT_FREEZE_WAIT = 0, WT_NONFREEZED_WAIT = 1, 
-	WT_2 = 2, WT_3 = 3, WT_UNFORMATTED = 9 };
+	WT_2 = 2, WT_3 = 3 };
 
-class ErrorScroll: public ButtonContainer {
+class ErrorDialog : public ButtonContainer {
 private:
 	XeenEngine *_vm;
 
-	ErrorScroll(XeenEngine *vm) : ButtonContainer(), _vm(vm) {}
+	ErrorDialog(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);
+};
+
+class ErrorScroll {
+public:
 	static void show(XeenEngine *vm, const Common::String &msg, 
 		ErrorWaitType waitType = WT_FREEZE_WAIT);
 };
diff --git a/engines/xeen/resources.cpp b/engines/xeen/resources.cpp
index 1f1c979..c643152 100644
--- a/engines/xeen/resources.cpp
+++ b/engines/xeen/resources.cpp
@@ -1125,4 +1125,9 @@ const char *const NO_SPECIAL_ABILITIES = "\v005\x3""c%s\fdhas no special abiliti
 
 const char *const CANT_CAST_WHILE_ENGAGED = "\x03c\v007Can't cast %s while engaged!";
 
+const char *const EQUIPPED_ALL_YOU_CAN = "\x3""c\v007You have equipped all the %ss you can!";
+const char *const REMOVE_X_TO_EQUIP_Y = "\x3""c\v007You must remove %sto equip %s\x8!";
+const char *const RING = "ring";
+const char *const MEDAL = "medal";
+
 } // End of namespace Xeen
diff --git a/engines/xeen/resources.h b/engines/xeen/resources.h
index 88e01cd..c6d2bde 100644
--- a/engines/xeen/resources.h
+++ b/engines/xeen/resources.h
@@ -398,6 +398,11 @@ extern const char *const NO_SPECIAL_ABILITIES;
 
 extern const char *const CANT_CAST_WHILE_ENGAGED;
 
+extern const char *const EQUIPPED_ALL_YOU_CAN;
+extern const char *const REMOVE_X_TO_EQUIP_Y;
+extern const char *const RING;
+extern const char *const MEDAL;
+
 } // End of namespace Xeen
 
 #endif	/* XEEN_RESOURCES_H */
diff --git a/engines/xeen/spells.cpp b/engines/xeen/spells.cpp
index 3492510..5f1df6a 100644
--- a/engines/xeen/spells.cpp
+++ b/engines/xeen/spells.cpp
@@ -100,8 +100,8 @@ void Spells::doSpell(int spellId) {
 	if (_vm->_mode == MODE_InCombat) {
 		if (spellId == 15 || spellId == 20 || spellId == 27 || spellId == 41
 				|| spellId == 47 || spellId == 54 || spellId == 57) {
-			ErrorScroll::show(_vm, Common::String::format(CANT_CAST_WHILE_ENGAGED,
-				_spellNames[spellId].c_str()), WT_UNFORMATTED);
+			ErrorDialog::show(_vm, Common::String::format(CANT_CAST_WHILE_ENGAGED,
+				_spellNames[spellId].c_str()));
 			return;
 		}
 	}


Commit: fc04fe6da8b490cceef6ee167775a65fe2e1b607
    https://github.com/scummvm/scummvm/commit/fc04fe6da8b490cceef6ee167775a65fe2e1b607
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-02-05T08:00:28-05:00

Commit Message:
XEEN: equipItem methods for armor and accessories

Changed paths:
    engines/xeen/character.cpp



diff --git a/engines/xeen/character.cpp b/engines/xeen/character.cpp
index 00b7e43..b8dd53d 100644
--- a/engines/xeen/character.cpp
+++ b/engines/xeen/character.cpp
@@ -171,6 +171,9 @@ void InventoryItems::equipError(int itemIndex1, ItemCategory category1, int item
 
 /*------------------------------------------------------------------------*/
 
+/**
+ * Equip a given weapon
+ */
 void WeaponItems::equipItem(int itemIndex) {
 	XeenItem &item = operator[](itemIndex);
 
@@ -208,10 +211,10 @@ void WeaponItems::equipItem(int itemIndex) {
 				}
 			}
 
-			for (uint idx = 0; idx < size(); ++idx) {
+			for (uint idx = 0; idx < _character->_armor.size(); ++idx) {
 				XeenItem &i = _character->_armor[idx];
 				if (i._frame == 2) {
-					equipError(itemIndex, CATEGORY_ARMOR, idx, CATEGORY_WEAPON);
+					equipError(itemIndex, CATEGORY_WEAPON, idx, CATEGORY_ARMOR);
 					return;
 				}
 			}
@@ -223,14 +226,138 @@ void WeaponItems::equipItem(int itemIndex) {
 
 /*------------------------------------------------------------------------*/
 
+/**
+ * Equip a given piece of armor
+ */
 void ArmorItems::equipItem(int itemIndex) {
-	error("TODO");
+	XeenItem &item = operator[](itemIndex);
+
+	if (item._id <= 7) {
+		if (passRestrictions(item._id, false)) {
+			for (uint idx = 0; idx < size(); ++idx) {
+				XeenItem &i = operator[](idx);
+				if (i._frame == 9) {
+					equipError(itemIndex, CATEGORY_ARMOR, idx, CATEGORY_ARMOR);
+					return;
+				}
+			}
+
+			item._frame = 3;
+		}
+	} else if (item._id == 8) {
+		if (passRestrictions(item._id, false)) {
+			for (uint idx = 0; idx < size(); ++idx) {
+				XeenItem &i = operator[](idx);
+				if (i._frame == 2) {
+					equipError(itemIndex, CATEGORY_ARMOR, idx, CATEGORY_ARMOR);
+					return;
+				}
+			}
+
+			for (uint idx = 0; idx < _character->_weapons.size(); ++idx) {
+				XeenItem &i = _character->_weapons[idx];
+				if (i._frame == 13) {
+					equipError(itemIndex, CATEGORY_ARMOR, idx, CATEGORY_WEAPON);
+					return;
+				}
+			}
+
+			item._frame = 2;
+		}
+	} else if (item._id == 9) {
+		for (uint idx = 0; idx < size(); ++idx) {
+			XeenItem &i = operator[](idx);
+			if (i._frame == 5) {
+				equipError(itemIndex, CATEGORY_ARMOR, idx, CATEGORY_ARMOR);
+				return;
+			}
+		}
+
+		item._frame = 5;
+	} else if (item._id == 10) {
+		for (uint idx = 0; idx < size(); ++idx) {
+			XeenItem &i = operator[](idx);
+			if (i._frame == 9) {
+				equipError(itemIndex, CATEGORY_ARMOR, idx, CATEGORY_ARMOR);
+				return;
+			}
+		}
+
+		item._frame = 9;
+	} else if (item._id <= 12) {
+		for (uint idx = 0; idx < size(); ++idx) {
+			XeenItem &i = operator[](idx);
+			if (i._frame == 10) {
+				equipError(itemIndex, CATEGORY_ARMOR, idx, CATEGORY_ARMOR);
+				return;
+			}
+		}
+
+		item._frame = 10;
+	} else {
+		for (uint idx = 0; idx < size(); ++idx) {
+			XeenItem &i = operator[](idx);
+			if (i._frame == 6) {
+				equipError(itemIndex, CATEGORY_ARMOR, idx, CATEGORY_ARMOR);
+				return;
+			}
+		}
+
+		item._frame = 6;
+	}
 }
 
 /*------------------------------------------------------------------------*/
 
+/**
+ * Equip a given accessory
+ */
 void AccessoryItems::equipItem(int itemIndex) {
-	error("TODO");
+	XeenItem &item = operator[](itemIndex);
+
+	if (item._id == 1) {
+		int count = 0;
+		for (uint idx = 0; idx < size(); ++idx) {
+			XeenItem &i = operator[](idx);
+			if (i._frame == 8)
+				++count;
+		}
+
+		if (count <= 1)
+			item._frame = 8;
+		else
+			equipError(-1, CATEGORY_ACCESSORY, itemIndex, CATEGORY_ACCESSORY);
+	} else if (item._id == 2) {
+		for (uint idx = 0; idx < size(); ++idx) {
+			XeenItem &i = operator[](idx);
+			if (i._frame == 12) {
+				equipError(itemIndex, CATEGORY_ACCESSORY, idx, CATEGORY_ACCESSORY);
+				return;
+			}
+		}
+	} else if (item._id <= 7) {
+		int count = 0;
+		for (uint idx = 0; idx < size(); ++idx) {
+			XeenItem &i = operator[](idx);
+			if (i._frame == 7)
+				++count;
+		}
+
+		if (count <= 1)
+			item._frame = 7;
+		else
+			equipError(-2, CATEGORY_ACCESSORY, itemIndex, CATEGORY_ACCESSORY);
+	} else {
+		for (uint idx = 0; idx < size(); ++idx) {
+			XeenItem &i = operator[](idx);
+			if (i._frame == 11) {
+				equipError(itemIndex, CATEGORY_ACCESSORY, idx, CATEGORY_ACCESSORY);
+				return;
+			}
+		}
+
+		item._frame = 11;
+	}
 }
 /*------------------------------------------------------------------------*/
 


Commit: 85c2dd5f6864540d66e0abfe74ec791bbde41c30
    https://github.com/scummvm/scummvm/commit/85c2dd5f6864540d66e0abfe74ec791bbde41c30
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-02-05T20:05:24-05:00

Commit Message:
XEEN: Split up assembleItemName and renamed to getFullDescription

Changed paths:
    engines/xeen/character.cpp
    engines/xeen/character.h
    engines/xeen/dialogs_items.cpp
    engines/xeen/resources.cpp
    engines/xeen/resources.h



diff --git a/engines/xeen/character.cpp b/engines/xeen/character.cpp
index b8dd53d..ff85c97 100644
--- a/engines/xeen/character.cpp
+++ b/engines/xeen/character.cpp
@@ -122,9 +122,19 @@ Common::String InventoryItems::getName(int itemIndex) {
 /**
  * Discard an item from the inventory
  */
-void InventoryItems::discardItem(int itemIndex) {
-	operator[](itemIndex).clear();
-	sort();
+bool InventoryItems::discardItem(int itemIndex) {
+	XeenItem &item = operator[](itemIndex);
+	XeenEngine *vm = Party::_vm;
+
+	if (item._bonusFlags & ITEMFLAG_CURSED) {
+		ErrorScroll::show(vm, CANNOT_DISCARD_CURSED_ITEM);
+		return false;
+	} else {
+		Common::String itemDesc = getFullDescription(itemIndex, 4);
+
+		error("TODO: discardItem - %s", itemDesc.c_str());
+	}
+	error("TODO");
 }
 
 /**
@@ -149,8 +159,21 @@ void InventoryItems::sort() {
 	}
 }
 
+/**
+ * Un-equips the given item
+ */
 void InventoryItems::removeItem(int itemIndex) {
-	error("TODO");
+	XeenItem &item = operator[](itemIndex);
+	XeenEngine *vm = Party::_vm;
+
+	if (item._bonusFlags & ITEMFLAG_CURSED)
+		ErrorScroll::show(vm, CANNOT_REMOVE_CURSED_ITEM);
+	else
+		item._frame = 0;
+}
+
+XeenEngine *InventoryItems::vm() {
+	return Party::_vm;
 }
 
 void InventoryItems::equipError(int itemIndex1, ItemCategory category1, int itemIndex2,
@@ -224,6 +247,25 @@ void WeaponItems::equipItem(int itemIndex) {
 	}
 }
 
+/**
+ * Assembles a full lines description for a specified item for use in
+ * the Items dialog
+ */
+Common::String WeaponItems::getFullDescription(int itemIndex, int displayNum) {
+	XeenItem &i = operator[](itemIndex);
+	Spells &spells = *vm()->_spells;
+
+	return Common::String::format("\f%02u%s%s%s\f%02u%s%s%s", displayNum,
+		!i._bonusFlags ? spells._maeNames[i._material] : "",
+		(i._bonusFlags & ITEMFLAG_BROKEN) ? ITEM_BROKEN : "",
+		(i._bonusFlags & ITEMFLAG_CURSED) ? ITEM_CURSED : "",
+		WEAPON_NAMES[i._id],
+		!i._bonusFlags ? "" : BONUS_NAMES[i._bonusFlags & ITEMFLAG_BONUS_MASK],
+		(i._bonusFlags & (ITEMFLAG_BROKEN | ITEMFLAG_CURSED)) || 
+			!i._bonusFlags ? "\b " : ""
+	);
+}
+
 /*------------------------------------------------------------------------*/
 
 /**
@@ -307,6 +349,24 @@ void ArmorItems::equipItem(int itemIndex) {
 	}
 }
 
+/**
+ * Assembles a full lines description for a specified item for use in
+ * the Items dialog
+ */
+Common::String ArmorItems::getFullDescription(int itemIndex, int displayNum) {
+	XeenItem &i = operator[](itemIndex);
+	Spells &spells = *vm()->_spells;
+
+	return Common::String::format("\f%02u%s%s%s\f%02u%s%s", displayNum,
+		!i._bonusFlags ? "" : spells._maeNames[i._material],
+		(i._bonusFlags & ITEMFLAG_BROKEN) ? ITEM_BROKEN : "",
+		(i._bonusFlags & ITEMFLAG_CURSED) ? ITEM_CURSED : "",
+		ARMOR_NAMES[i._id],
+		(i._bonusFlags & (ITEMFLAG_BROKEN | ITEMFLAG_CURSED)) ||
+			!i._bonusFlags ? "\b " : ""
+	);
+}
+
 /*------------------------------------------------------------------------*/
 
 /**
@@ -359,6 +419,46 @@ void AccessoryItems::equipItem(int itemIndex) {
 		item._frame = 11;
 	}
 }
+
+/**
+ * Assembles a full lines description for a specified item for use in
+ * the Items dialog
+ */
+Common::String AccessoryItems::getFullDescription(int itemIndex, int displayNum) {
+	Spells &spells = *vm()->_spells;
+	XeenItem &i = operator[](itemIndex);
+
+	return Common::String::format("\f%02u%s%s%s\f%02u%s%s", displayNum,
+		!i._bonusFlags ? "" : spells._maeNames[i._material],
+		(i._bonusFlags & ITEMFLAG_BROKEN) ? ITEM_BROKEN : "",
+		(i._bonusFlags & ITEMFLAG_CURSED) ? ITEM_CURSED : "",
+		ARMOR_NAMES[i._id],
+		(i._bonusFlags & (ITEMFLAG_BROKEN | ITEMFLAG_CURSED)) ||
+			!i._bonusFlags ? "\b " : ""
+	);
+}
+
+/*------------------------------------------------------------------------*/
+
+/**
+ * Assembles a full lines description for a specified item for use in
+ * the Items dialog
+ */
+Common::String MiscItems::getFullDescription(int itemIndex, int displayNum) {
+	XeenItem &i = operator[](itemIndex);
+	Spells &spells = *vm()->_spells;
+
+	return Common::String::format("\f%02u%s%s%s\f%02u%s%s", displayNum,
+		!i._bonusFlags ? "" : spells._maeNames[i._material],
+		(i._bonusFlags & ITEMFLAG_BROKEN) ? ITEM_BROKEN : "",
+		(i._bonusFlags & ITEMFLAG_CURSED) ? ITEM_CURSED : "",
+		ARMOR_NAMES[i._id],
+		(i._bonusFlags & (ITEMFLAG_BROKEN | ITEMFLAG_CURSED)) ||
+			!i._id ? "\b " : ""
+	);
+}
+
+
 /*------------------------------------------------------------------------*/
 
 InventoryItemsGroup::InventoryItemsGroup(InventoryItems &weapons, InventoryItems &armor,
@@ -1203,70 +1303,4 @@ int Character::getNumAwards() const {
 	return total;
 }
 
-/**
- * Assembles a full lines description for a specified item for use in
- * the Items dialog
- */
-Common::String Character::assembleItemName(int itemIndex, int displayNum, 
-		ItemCategory category) {
-	Spells &spells = *Party::_vm->_spells;
-
-	switch (category) {
-	case CATEGORY_WEAPON: {
-		// Weapons
-		XeenItem &i = _weapons[itemIndex];
-		return Common::String::format("\f%02u%s%s%s\f%02u%s%s%s", displayNum,
-			!i._bonusFlags ? spells._maeNames[i._material] : "",
-			(i._bonusFlags & ITEMFLAG_BROKEN) ? ITEM_BROKEN : "",
-			(i._bonusFlags & ITEMFLAG_CURSED) ? ITEM_CURSED : "",
-			WEAPON_NAMES[i._id],
-			!i._bonusFlags ? "" : BONUS_NAMES[i._bonusFlags & ITEMFLAG_BONUS_MASK],
-			(i._bonusFlags & (ITEMFLAG_BROKEN | ITEMFLAG_CURSED)) || 
-				!i._bonusFlags ? "\b " : ""
-		);
-	}
-
-	case CATEGORY_ARMOR: {
-		// Armor
-		XeenItem &i = _armor[itemIndex];
-		return Common::String::format("\f%02u%s%s%s\f%02u%s%s", displayNum,
-			!i._bonusFlags ? "" : spells._maeNames[i._material],
-			(i._bonusFlags & ITEMFLAG_BROKEN) ? ITEM_BROKEN : "",
-			(i._bonusFlags & ITEMFLAG_CURSED) ? ITEM_CURSED : "",
-			ARMOR_NAMES[i._id],
-			(i._bonusFlags & (ITEMFLAG_BROKEN | ITEMFLAG_CURSED)) ||
-				!i._bonusFlags ? "\b " : ""
-		);
-	}
-		
-	case CATEGORY_ACCESSORY: {
-		// Accessories
-		XeenItem &i = _accessories[itemIndex];
-		return Common::String::format("\f%02u%s%s%s\f%02u%s%s", displayNum,
-			!i._bonusFlags ? "" : spells._maeNames[i._material],
-			(i._bonusFlags & ITEMFLAG_BROKEN) ? ITEM_BROKEN : "",
-			(i._bonusFlags & ITEMFLAG_CURSED) ? ITEM_CURSED : "",
-			ARMOR_NAMES[i._id],
-			(i._bonusFlags & (ITEMFLAG_BROKEN | ITEMFLAG_CURSED)) ||
-				!i._bonusFlags ? "\b " : ""
-		);
-	}
-
-	case CATEGORY_MISC: {
-		// Misc
-		XeenItem &i = _misc[itemIndex];
-		return Common::String::format("\f%02u%s%s%s\f%02u%s%s", displayNum,
-			!i._bonusFlags ? "" : spells._maeNames[i._material],
-			(i._bonusFlags & ITEMFLAG_BROKEN) ? ITEM_BROKEN : "",
-			(i._bonusFlags & ITEMFLAG_CURSED) ? ITEM_CURSED : "",
-			ARMOR_NAMES[i._id],
-			(i._bonusFlags & (ITEMFLAG_BROKEN | ITEMFLAG_CURSED)) ||
-				!i._id ? "\b " : ""
-		);
-	}
-	default:
-		return "";
-	}
-}
-
 } // End of namespace Xeen
diff --git a/engines/xeen/character.h b/engines/xeen/character.h
index c4eae0e..6514cae 100644
--- a/engines/xeen/character.h
+++ b/engines/xeen/character.h
@@ -100,6 +100,7 @@ protected:
 	ItemCategory _category;
 	const char *const *_names;
 
+	XeenEngine *vm();
 	void equipError(int itemIndex1, ItemCategory category1, int itemIndex2,
 		ItemCategory category2);
 public:
@@ -109,7 +110,9 @@ public:
 
 	Common::String getName(int itemIndex);
 
-	void discardItem(int itemIndex);
+	virtual Common::String getFullDescription(int itemIndex, int displayNum) = 0;
+
+	bool discardItem(int itemIndex);
 
 	virtual void equipItem(int itemIndex) {}
 
@@ -121,24 +124,35 @@ public:
 class WeaponItems: public InventoryItems {
 public:
 	WeaponItems(Character *character) : InventoryItems(character, CATEGORY_WEAPON) {}
+
 	virtual void equipItem(int itemIndex);
+
+	virtual Common::String getFullDescription(int itemIndex, int displayNum);
 };
 
 class ArmorItems : public InventoryItems {
 public:
 	ArmorItems(Character *character) : InventoryItems(character, CATEGORY_ARMOR) {}
+
 	virtual void equipItem(int itemIndex);
+
+	virtual Common::String getFullDescription(int itemIndex, int displayNum);
 };
 
 class AccessoryItems : public InventoryItems {
 public:
 	AccessoryItems(Character *character) : InventoryItems(character, CATEGORY_ACCESSORY) {}
+
 	virtual void equipItem(int itemIndex);
+
+	virtual Common::String getFullDescription(int itemIndex, int displayNum);
 };
 
 class MiscItems : public InventoryItems {
 public:
 	MiscItems(Character *character) : InventoryItems(character, CATEGORY_MISC) {}
+
+	virtual Common::String getFullDescription(int itemIndex, int displayNum);
 };
 
 class InventoryItemsGroup {
@@ -257,8 +271,6 @@ public:
 	int getNumSkills() const;
 
 	int getNumAwards() const;
-
-	Common::String assembleItemName(int itemIndex, int displayNum, ItemCategory category);
 };
 
 } // End of namespace Xeen
diff --git a/engines/xeen/dialogs_items.cpp b/engines/xeen/dialogs_items.cpp
index c28085c..beaf565 100644
--- a/engines/xeen/dialogs_items.cpp
+++ b/engines/xeen/dialogs_items.cpp
@@ -141,11 +141,11 @@ Character *ItemsDialog::execute(Character *c, ItemsMode mode) {
 							|| mode == ITEMMODE_6 || mode == ITEMMODE_4) {
 						lines.push_back(Common::String::format(ITEMS_DIALOG_LINE1, 
 							arr[idx], idx + 1,
-							c->assembleItemName(idx, arr[idx], category)));
+							c->_items[category].getFullDescription(idx, arr[idx])));
 					} else {
 						lines.push_back(Common::String::format(ITEMS_DIALOG_LINE2,
 							arr[idx], idx + 1,
-							c->assembleItemName(idx, arr[idx], category),
+							c->_items[category].getFullDescription(idx, arr[idx]),
 							calcItemCost(c, idx, mode,
 								mode == ITEMMODE_TO_GOLD ? 1 : startingChar->_skills[MERCHANT],
 								category)
@@ -186,7 +186,7 @@ Character *ItemsDialog::execute(Character *c, ItemsMode mode) {
 
 					lines.push_back(Common::String::format(ITEMS_DIALOG_LINE2,
 						arr[idx], idx + 1,
-						c->assembleItemName(idx, arr[idx], category),
+						c->_items[category].getFullDescription(idx, arr[idx]),
 						calcItemCost(c, idx, tempMode, skill, category)
 					));
 				}
@@ -631,8 +631,8 @@ bool ItemsDialog::doItemOptions(Character &c, int actionIndex, int itemIndex, It
 							ErrorScroll::show(_vm, USE_ITEM_IN_COMBAT);
 						} else if (i._id && (i._bonusFlags & ITEMFLAG_BONUS_MASK)
 								&& !(i._bonusFlags & (ITEMFLAG_BROKEN | ITEMFLAG_CURSED))) {
-							int bonus = (i._bonusFlags & ITEMFLAG_BONUS_MASK) - 1;
-							i._bonusFlags = bonus;
+							int charges = (i._bonusFlags & ITEMFLAG_BONUS_MASK) - 1;
+							i._bonusFlags = charges;
 							_oldCharacter = &c;
 
 							screen._windows[30].close();
@@ -640,16 +640,19 @@ bool ItemsDialog::doItemOptions(Character &c, int actionIndex, int itemIndex, It
 							screen._windows[24].close();
 							spells.doSpell(i._id);
 
-							if (!bonus) {
-								c._items[category].discardItem(itemIndex);
+							if (!charges) {
+								// Ran out of charges, so make item disappear
+								c._items[category][itemIndex].clear();
+								c._items[category].sort();
 							}
 						} else {
 							ErrorScroll::show(_vm, Common::String::format(NO_SPECIAL_ABILITIES,
-								c.assembleItemName(itemIndex, 15, category).c_str()
+								c._items[category].getFullDescription(itemIndex, 15).c_str()
 							));
 						}
 					}
 				}
+				break;
 			case 3:
 				// TODO: Remaining switches
 			default:
diff --git a/engines/xeen/resources.cpp b/engines/xeen/resources.cpp
index c643152..b38868f 100644
--- a/engines/xeen/resources.cpp
+++ b/engines/xeen/resources.cpp
@@ -1130,4 +1130,8 @@ const char *const REMOVE_X_TO_EQUIP_Y = "\x3""c\v007You must remove %sto equip %
 const char *const RING = "ring";
 const char *const MEDAL = "medal";
 
+const char *const CANNOT_REMOVE_CURSED_ITEM = "\x3""You cannot remove a cursed item!";
+
+const char *const CANNOT_DISCARD_CURSED_ITEM = "\3x""cYou cannot discard a cursed item!";
+
 } // End of namespace Xeen
diff --git a/engines/xeen/resources.h b/engines/xeen/resources.h
index c6d2bde..e1f276b 100644
--- a/engines/xeen/resources.h
+++ b/engines/xeen/resources.h
@@ -403,6 +403,10 @@ extern const char *const REMOVE_X_TO_EQUIP_Y;
 extern const char *const RING;
 extern const char *const MEDAL;
 
+extern const char *const CANNOT_REMOVE_CURSED_ITEM;
+
+extern const char *const CANNOT_DISCARD_CURSED_ITEM;
+
 } // End of namespace Xeen
 
 #endif	/* XEEN_RESOURCES_H */


Commit: 6595abcf144850cc23208db71ce0098d9921112e
    https://github.com/scummvm/scummvm/commit/6595abcf144850cc23208db71ce0098d9921112e
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-02-05T20:17:16-05:00

Commit Message:
XEEN: Moved _maeNames to a new Resources class

Changed paths:
    engines/xeen/character.cpp
    engines/xeen/resources.cpp
    engines/xeen/resources.h
    engines/xeen/spells.cpp
    engines/xeen/spells.h
    engines/xeen/xeen.cpp
    engines/xeen/xeen.h



diff --git a/engines/xeen/character.cpp b/engines/xeen/character.cpp
index ff85c97..20cbfbd 100644
--- a/engines/xeen/character.cpp
+++ b/engines/xeen/character.cpp
@@ -253,10 +253,10 @@ void WeaponItems::equipItem(int itemIndex) {
  */
 Common::String WeaponItems::getFullDescription(int itemIndex, int displayNum) {
 	XeenItem &i = operator[](itemIndex);
-	Spells &spells = *vm()->_spells;
+	Resources &res = *vm()->_resources;
 
 	return Common::String::format("\f%02u%s%s%s\f%02u%s%s%s", displayNum,
-		!i._bonusFlags ? spells._maeNames[i._material] : "",
+		!i._bonusFlags ? res._maeNames[i._material] : "",
 		(i._bonusFlags & ITEMFLAG_BROKEN) ? ITEM_BROKEN : "",
 		(i._bonusFlags & ITEMFLAG_CURSED) ? ITEM_CURSED : "",
 		WEAPON_NAMES[i._id],
@@ -355,10 +355,10 @@ void ArmorItems::equipItem(int itemIndex) {
  */
 Common::String ArmorItems::getFullDescription(int itemIndex, int displayNum) {
 	XeenItem &i = operator[](itemIndex);
-	Spells &spells = *vm()->_spells;
+	Resources &res = *vm()->_resources;
 
 	return Common::String::format("\f%02u%s%s%s\f%02u%s%s", displayNum,
-		!i._bonusFlags ? "" : spells._maeNames[i._material],
+		!i._bonusFlags ? "" : res._maeNames[i._material],
 		(i._bonusFlags & ITEMFLAG_BROKEN) ? ITEM_BROKEN : "",
 		(i._bonusFlags & ITEMFLAG_CURSED) ? ITEM_CURSED : "",
 		ARMOR_NAMES[i._id],
@@ -425,11 +425,11 @@ void AccessoryItems::equipItem(int itemIndex) {
  * the Items dialog
  */
 Common::String AccessoryItems::getFullDescription(int itemIndex, int displayNum) {
-	Spells &spells = *vm()->_spells;
 	XeenItem &i = operator[](itemIndex);
+	Resources &res = *vm()->_resources;
 
 	return Common::String::format("\f%02u%s%s%s\f%02u%s%s", displayNum,
-		!i._bonusFlags ? "" : spells._maeNames[i._material],
+		!i._bonusFlags ? "" : res._maeNames[i._material],
 		(i._bonusFlags & ITEMFLAG_BROKEN) ? ITEM_BROKEN : "",
 		(i._bonusFlags & ITEMFLAG_CURSED) ? ITEM_CURSED : "",
 		ARMOR_NAMES[i._id],
@@ -446,10 +446,10 @@ Common::String AccessoryItems::getFullDescription(int itemIndex, int displayNum)
  */
 Common::String MiscItems::getFullDescription(int itemIndex, int displayNum) {
 	XeenItem &i = operator[](itemIndex);
-	Spells &spells = *vm()->_spells;
+	Resources &res = *vm()->_resources;
 
 	return Common::String::format("\f%02u%s%s%s\f%02u%s%s", displayNum,
-		!i._bonusFlags ? "" : spells._maeNames[i._material],
+		!i._bonusFlags ? "" : res._maeNames[i._material],
 		(i._bonusFlags & ITEMFLAG_BROKEN) ? ITEM_BROKEN : "",
 		(i._bonusFlags & ITEMFLAG_CURSED) ? ITEM_CURSED : "",
 		ARMOR_NAMES[i._id],
@@ -458,7 +458,6 @@ Common::String MiscItems::getFullDescription(int itemIndex, int displayNum) {
 	);
 }
 
-
 /*------------------------------------------------------------------------*/
 
 InventoryItemsGroup::InventoryItemsGroup(InventoryItems &weapons, InventoryItems &armor,
diff --git a/engines/xeen/resources.cpp b/engines/xeen/resources.cpp
index b38868f..5cd09cf 100644
--- a/engines/xeen/resources.cpp
+++ b/engines/xeen/resources.cpp
@@ -22,9 +22,19 @@
 
 #include "common/scummsys.h"
 #include "xeen/resources.h"
+#include "xeen/files.h"
 
 namespace Xeen {
 
+Resources::Resources() {
+	File f("mae.xen");
+	while (f.pos() < f.size())
+		_maeNames.push_back(f.readString());
+	f.close();
+}
+
+/*------------------------------------------------------------------------*/
+
 const char *const CREDITS =
 	"\013""012\010""000\003""c\014""35Designed and Directed By:\n"
 	"\014""17Jon Van Caneghem\003""l\n"
diff --git a/engines/xeen/resources.h b/engines/xeen/resources.h
index e1f276b..8be195f 100644
--- a/engines/xeen/resources.h
+++ b/engines/xeen/resources.h
@@ -24,10 +24,21 @@
 #define XEEN_RESOURCES_H
 
 #include "common/scummsys.h"
+#include "common/str-array.h"
 #include "gui/debugger.h"
 
 namespace Xeen {
 
+class Resources {
+public:
+	// Magic and equipment names
+	Common::StringArray _maeNames;
+public:
+	Resources();
+};
+
+#define Res (*_vm->_resources)
+
 extern const char *const CREDITS;
 
 extern const char *const OPTIONS_TITLE;
diff --git a/engines/xeen/spells.cpp b/engines/xeen/spells.cpp
index 5f1df6a..50e7766 100644
--- a/engines/xeen/spells.cpp
+++ b/engines/xeen/spells.cpp
@@ -38,11 +38,6 @@ void Spells::load() {
 	while (f1.pos() < f1.size())
 		_spellNames.push_back(f1.readString());
 	f1.close();
-
-	File f2("mae.xen");
-	while (f2.pos() < f2.size())
-		_maeNames.push_back(f2.readString());
-	f2.close();
 }
 
 int Spells::calcSpellCost(int spellId, int expenseFactor) const {
diff --git a/engines/xeen/spells.h b/engines/xeen/spells.h
index 241d35d..c2f9737 100644
--- a/engines/xeen/spells.h
+++ b/engines/xeen/spells.h
@@ -121,7 +121,6 @@ private:
 	void divineIntervention();
 public:
 	Common::StringArray _spellNames;
-	Common::StringArray _maeNames;
 	int _lastCaster;
 public:
 	Spells(XeenEngine *vm);
diff --git a/engines/xeen/xeen.cpp b/engines/xeen/xeen.cpp
index d7a85fb..d34e8ed 100644
--- a/engines/xeen/xeen.cpp
+++ b/engines/xeen/xeen.cpp
@@ -43,6 +43,7 @@ XeenEngine::XeenEngine(OSystem *syst, const XeenGameDescription *gameDesc)
 	_interface = nullptr;
 	_map = nullptr;
 	_party = nullptr;
+	_resources = nullptr;
 	_saves = nullptr;
 	_screen = nullptr;
 	_scripts = nullptr;
@@ -72,6 +73,7 @@ XeenEngine::~XeenEngine() {
 	delete _spells;
 	delete _town;
 	delete _eventData;
+	delete _resources;
 	delete _files;
 }
 
@@ -84,6 +86,7 @@ void XeenEngine::initialize() {
 
 	// Create sub-objects of the engine
 	_files = new FileManager(this);
+	_resources = new Resources();
 	_combat = new Combat(this);
 	_debugger = new Debugger(this);
 	_events = new EventsManager(this);
diff --git a/engines/xeen/xeen.h b/engines/xeen/xeen.h
index 7f1a2cd..af2044b 100644
--- a/engines/xeen/xeen.h
+++ b/engines/xeen/xeen.h
@@ -39,6 +39,7 @@
 #include "xeen/interface.h"
 #include "xeen/map.h"
 #include "xeen/party.h"
+#include "xeen/resources.h"
 #include "xeen/saves.h"
 #include "xeen/screen.h"
 #include "xeen/scripts.h"
@@ -139,6 +140,7 @@ public:
 	Interface *_interface;
 	Map *_map;
 	Party *_party;
+	Resources *_resources;
 	SavesManager *_saves;
 	Screen *_screen;
 	Scripts *_scripts;


Commit: b39f4179ce53e9e98c4e3d80cc0f075dabd8d8f6
    https://github.com/scummvm/scummvm/commit/b39f4179ce53e9e98c4e3d80cc0f075dabd8d8f6
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-02-05T20:47:15-05:00

Commit Message:
XEEN: Merged confirmation and yes/no dialogs into single source file

Changed paths:
  A engines/xeen/dialogs_query.cpp
  A engines/xeen/dialogs_query.h
  R engines/xeen/dialogs_confirm.cpp
  R engines/xeen/dialogs_confirm.h
  R engines/xeen/dialogs_yesno.cpp
  R engines/xeen/dialogs_yesno.h
    engines/xeen/character.cpp
    engines/xeen/dialogs_spells.cpp
    engines/xeen/module.mk
    engines/xeen/resources.cpp
    engines/xeen/resources.h
    engines/xeen/scripts.cpp
    engines/xeen/town.cpp



diff --git a/engines/xeen/character.cpp b/engines/xeen/character.cpp
index 20cbfbd..8fd7a35 100644
--- a/engines/xeen/character.cpp
+++ b/engines/xeen/character.cpp
@@ -21,6 +21,7 @@
  */
 
 #include "xeen/character.h"
+#include "xeen/dialogs_query.h"
 #include "xeen/dialogs_error.h"
 #include "xeen/resources.h"
 #include "xeen/xeen.h"
@@ -128,13 +129,19 @@ bool InventoryItems::discardItem(int itemIndex) {
 
 	if (item._bonusFlags & ITEMFLAG_CURSED) {
 		ErrorScroll::show(vm, CANNOT_DISCARD_CURSED_ITEM);
-		return false;
 	} else {
 		Common::String itemDesc = getFullDescription(itemIndex, 4);
+		Common::String msg = Common::String::format(PERMANENTLY_DISCARD, itemDesc.c_str());
+
+		if (Confirm::show(vm, msg)) {
+			operator[](itemIndex).clear();
+			sort();
 
-		error("TODO: discardItem - %s", itemDesc.c_str());
+			return true;
+		}		
 	}
-	error("TODO");
+
+	return true;
 }
 
 /**
diff --git a/engines/xeen/dialogs_confirm.cpp b/engines/xeen/dialogs_confirm.cpp
deleted file mode 100644
index 13a41e7..0000000
--- a/engines/xeen/dialogs_confirm.cpp
+++ /dev/null
@@ -1,85 +0,0 @@
-/* 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 "xeen/dialogs_confirm.h"
-#include "xeen/xeen.h"
-
-namespace Xeen {
-
-bool ConfirmDialog::show(XeenEngine *vm, const Common::String &msg, int v2) {
-	ConfirmDialog *dlg = new ConfirmDialog(vm);
-	bool result = dlg->execute(msg, v2);
-	delete dlg;
-
-	return result;
-}
-
-bool ConfirmDialog::execute(const Common::String &msg, int v2) {
-	Screen &screen = *_vm->_screen;
-	EventsManager &events = *_vm->_events;
-	SpriteResource confirmSprites;
-	confirmSprites.load("confirm.icn");
-
-	addButton(Common::Rect(129, 112, 153, 132), Common::KEYCODE_y, &confirmSprites);
-	addButton(Common::Rect(185, 112, 209, 132), Common::KEYCODE_n, &confirmSprites);
-
-	Window &w = screen._windows[v2 ? 21 : 22];
-	w.open();
-
-	if (v2) {
-		confirmSprites.draw(screen._windows[21], 0, Common::Point(129, 112));
-		confirmSprites.draw(screen._windows[21], 2, Common::Point(185, 112));
-
-		_buttons[0]._bounds.moveTo(129, 112);
-		_buttons[1]._bounds.moveTo(185, 112);
-	} else if (v2 & 0x80) {
-		clearButtons();
-	} else {
-		confirmSprites.draw(screen._windows[22], 0, Common::Point(120, 133));
-		confirmSprites.draw(screen._windows[22], 2, Common::Point(176, 133));
-
-		_buttons[0]._bounds.moveTo(120, 133);
-		_buttons[1]._bounds.moveTo(176, 133);
-	}
-
-	w.writeString(msg);
-	w.update();
-
-	bool result = false;
-	while (!_vm->shouldQuit()) {
-		while (!events.isKeyMousePressed())
-			events.pollEventsAndWait();
-
-		if ((v2 & 0x80) || _buttonValue == Common::KEYCODE_ESCAPE ||
-			_buttonValue == Common::KEYCODE_y)
-			break;
-		else if (_buttonValue == Common::KEYCODE_y) {
-			result = true;
-			break;
-		}
-	}
-
-	w.close();
-	return result;
-}
-
-} // End of namespace Xeen
diff --git a/engines/xeen/dialogs_confirm.h b/engines/xeen/dialogs_confirm.h
deleted file mode 100644
index 825be5e..0000000
--- a/engines/xeen/dialogs_confirm.h
+++ /dev/null
@@ -1,43 +0,0 @@
-/* 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_CONFIRM_H
-#define XEEN_DIALOGS_CONFIRM_H
-
-#include "xeen/dialogs.h"
-
-namespace Xeen {
-
-class ConfirmDialog : public ButtonContainer {
-private:
-	XeenEngine *_vm;
-
-	ConfirmDialog(XeenEngine *vm) : ButtonContainer(), _vm(vm) {}
-
-	bool execute(const Common::String &msg, int v2);
-public:
-	static bool show(XeenEngine *vm, const Common::String &msg, int v2);
-};
-
-} // End of namespace Xeen
-
-#endif /* XEEN_DIALOGS_CONFIRM_H */
diff --git a/engines/xeen/dialogs_query.cpp b/engines/xeen/dialogs_query.cpp
new file mode 100644
index 0000000..f226521
--- /dev/null
+++ b/engines/xeen/dialogs_query.cpp
@@ -0,0 +1,159 @@
+/* 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 "xeen/dialogs_query.h"
+#include "xeen/xeen.h"
+
+namespace Xeen {
+
+bool Confirm::show(XeenEngine *vm, const Common::String &msg, int mode) {
+	Confirm *dlg = new Confirm(vm);
+	bool result = dlg->execute(msg, mode);
+	delete dlg;
+
+	return result;
+}
+
+bool Confirm::execute(const Common::String &msg, int mode) {
+	Screen &screen = *_vm->_screen;
+	EventsManager &events = *_vm->_events;
+	SpriteResource confirmSprites;
+	bool result = false;
+
+	confirmSprites.load("confirm.icn");
+	addButton(Common::Rect(129, 112, 153, 122), Common::KEYCODE_y, &confirmSprites);
+	addButton(Common::Rect(185, 112, 209, 122), Common::KEYCODE_n, &confirmSprites);
+
+	Window &w = screen._windows[mode ? 22 : 21];
+	w.open();
+
+	if (!mode) {
+		confirmSprites.draw(w, 0, Common::Point(129, 112));
+		confirmSprites.draw(w, 2, Common::Point(185, 112));
+		_buttons[0]._bounds.moveTo(129, 112);
+		_buttons[1]._bounds.moveTo(185, 112);
+	} else {
+		if (mode & 0x80) {
+			clearButtons();
+		} else {
+			confirmSprites.draw(w, 0, Common::Point(120, 133));
+			confirmSprites.draw(w, 2, Common::Point(176, 133));
+			_buttons[0]._bounds.moveTo(120, 133);
+			_buttons[1]._bounds.moveTo(176, 133);
+		}
+	}
+
+	w.writeString(msg);
+	w.update();
+
+	events.clearEvents();
+	while (!_vm->shouldQuit()) {
+		while (!_vm->shouldQuit() && !_buttonValue) {
+			events.pollEvents();
+			checkEvents(_vm);
+		}
+
+		if ((mode & 0x80) || _buttonValue == Common::KEYCODE_ESCAPE
+				|| _buttonValue == Common::KEYCODE_n)
+			break;
+
+		if (_buttonValue == Common::KEYCODE_y) {
+			result = true;
+			break;
+		}
+	}
+
+	w.close();
+	return result;
+}
+
+/*------------------------------------------------------------------------*/
+
+bool YesNo::show(XeenEngine *vm, bool type, bool townFlag) {
+	YesNo *dlg = new YesNo(vm);
+	bool result = dlg->execute(type, townFlag);
+	delete dlg;
+
+	return result;
+}
+
+bool YesNo::execute(bool type, bool townFlag) {
+	Screen &screen = *_vm->_screen;
+	EventsManager &events = *_vm->_events;
+	Interface &intf = *_vm->_interface;
+	Map &map = *_vm->_map;
+	Party &party = *_vm->_party;
+	Town &town = *_vm->_town;
+	SpriteResource confirmSprites;
+	int numFrames;
+	bool result = false;
+
+	Mode oldMode = _vm->_mode;
+	_vm->_mode = oldMode == MODE_7 ? MODE_8 : MODE_7;
+
+	if (!type) {
+		confirmSprites.load("confirm.icn");
+		intf._globalSprites.draw(screen, 7, Common::Point(232, 74));
+		confirmSprites.draw(screen, 0, Common::Point(235, 75));
+		confirmSprites.draw(screen, 2, Common::Point(260, 75));
+		screen._windows[34].update();
+
+		addButton(Common::Rect(235, 75, 259, 95), Common::KEYCODE_y, &confirmSprites);
+		addButton(Common::Rect(260, 75, 284, 95), Common::KEYCODE_n, &confirmSprites);
+
+		intf._face1State = map._headData[party._mazePosition.y][party._mazePosition.x]._left;
+		intf._face2State = map._headData[party._mazePosition.y][party._mazePosition.x]._right;
+	}
+
+	while (!_vm->shouldQuit()) {
+		events.updateGameCounter();
+		
+		if (town.isActive()) {
+			town.drawTownAnim(townFlag);
+			numFrames = 3;
+		} else {
+			intf.draw3d(true);
+			numFrames = 1;
+		}
+
+		events.wait(3, true);
+		checkEvents(_vm);
+		if (!_buttonValue)
+			continue;
+
+		if (type || _buttonValue == Common::KEYCODE_y) {
+			result = true;
+			break;
+		} else if (_buttonValue == Common::KEYCODE_n || _buttonValue == Common::KEYCODE_ESCAPE)
+			break;
+	}
+
+	intf._face1State = intf._face2State = 2;
+	_vm->_mode = oldMode;
+
+	if (!type)
+		intf.mainIconsPrint();
+
+	return result;
+}
+
+} // End of namespace Xeen
diff --git a/engines/xeen/dialogs_query.h b/engines/xeen/dialogs_query.h
new file mode 100644
index 0000000..96ae488
--- /dev/null
+++ b/engines/xeen/dialogs_query.h
@@ -0,0 +1,54 @@
+/* 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_QUERY_H
+#define XEEN_DIALOGS_QUERY_H
+
+#include "xeen/dialogs.h"
+
+namespace Xeen {
+
+class Confirm : public ButtonContainer {
+private:
+	XeenEngine *_vm;
+
+	Confirm(XeenEngine *vm) : ButtonContainer(), _vm(vm) {}
+
+	bool execute(const Common::String &msg, int mode);
+public:
+	static bool show(XeenEngine *vm, const Common::String &msg, int mode = 0);
+};
+
+class YesNo : public ButtonContainer {
+private:
+	XeenEngine *_vm;
+
+	YesNo(XeenEngine *vm) : ButtonContainer(), _vm(vm) {}
+
+	bool execute(bool type, bool townFlag);
+public:
+	static bool show(XeenEngine *vm, bool type, bool townFlag = false);
+};
+
+} // End of namespace Xeen
+
+#endif /* XEEN_DIALOGS_QUERY_H */
diff --git a/engines/xeen/dialogs_spells.cpp b/engines/xeen/dialogs_spells.cpp
index 714e881..4f86707 100644
--- a/engines/xeen/dialogs_spells.cpp
+++ b/engines/xeen/dialogs_spells.cpp
@@ -21,7 +21,7 @@
  */
 
 #include "xeen/dialogs_spells.h"
-#include "xeen/dialogs_confirm.h"
+#include "xeen/dialogs_query.h"
 #include "xeen/resources.h"
 #include "xeen/spells.h"
 #include "xeen/sprites.h"
@@ -216,7 +216,7 @@ Character *SpellsScroll::execute(Character *c, int v2) {
 						Common::String::format(SPELLS_PRESS_A_KEY, msg.c_str()) :
 						Common::String::format(SPELLS_PURCHASE, msg.c_str(), spellCost);
 
-					if (ConfirmDialog::show(_vm, msg, v2Copy + 1)) {
+					if (Confirm::show(_vm, msg, v2Copy + 1)) {
 						if (party.subtract(0, spellCost, 0, WT_FREEZE_WAIT)) {
 							++c->_spells[spellIndex];
 							sound.playSample(nullptr, 0);
diff --git a/engines/xeen/dialogs_yesno.cpp b/engines/xeen/dialogs_yesno.cpp
deleted file mode 100644
index 17ca9a0..0000000
--- a/engines/xeen/dialogs_yesno.cpp
+++ /dev/null
@@ -1,96 +0,0 @@
-/* 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 "xeen/dialogs_yesno.h"
-#include "xeen/xeen.h"
-
-namespace Xeen {
-
-bool YesNo::show(XeenEngine *vm, bool type, bool townFlag) {
-	YesNo *dlg = new YesNo(vm);
-	bool result = dlg->execute(type, townFlag);
-	delete dlg;
-
-	return result;
-}
-
-bool YesNo::execute(bool type, bool townFlag) {
-	Screen &screen = *_vm->_screen;
-	EventsManager &events = *_vm->_events;
-	Interface &intf = *_vm->_interface;
-	Map &map = *_vm->_map;
-	Party &party = *_vm->_party;
-	Town &town = *_vm->_town;
-	SpriteResource confirmSprites;
-	int numFrames;
-	bool result = false;
-
-	Mode oldMode = _vm->_mode;
-	_vm->_mode = oldMode == MODE_7 ? MODE_8 : MODE_7;
-
-	if (!type) {
-		confirmSprites.load("confirm.icn");
-		intf._globalSprites.draw(screen, 7, Common::Point(232, 74));
-		confirmSprites.draw(screen, 0, Common::Point(235, 75));
-		confirmSprites.draw(screen, 2, Common::Point(260, 75));
-		screen._windows[34].update();
-
-		addButton(Common::Rect(235, 75, 259, 95), Common::KEYCODE_y, &confirmSprites);
-		addButton(Common::Rect(260, 75, 284, 95), Common::KEYCODE_n, &confirmSprites);
-
-		intf._face1State = map._headData[party._mazePosition.y][party._mazePosition.x]._left;
-		intf._face2State = map._headData[party._mazePosition.y][party._mazePosition.x]._right;
-	}
-
-	while (!_vm->shouldQuit()) {
-		events.updateGameCounter();
-		
-		if (town.isActive()) {
-			town.drawTownAnim(townFlag);
-			numFrames = 3;
-		} else {
-			intf.draw3d(true);
-			numFrames = 1;
-		}
-
-		events.wait(3, true);
-		checkEvents(_vm);
-		if (!_buttonValue)
-			continue;
-
-		if (type || _buttonValue == Common::KEYCODE_y) {
-			result = true;
-			break;
-		} else if (_buttonValue == Common::KEYCODE_n || _buttonValue == Common::KEYCODE_ESCAPE)
-			break;
-	}
-
-	intf._face1State = intf._face2State = 2;
-	_vm->_mode = oldMode;
-
-	if (!type)
-		intf.mainIconsPrint();
-
-	return result;
-}
-
-} // End of namespace Xeen
diff --git a/engines/xeen/dialogs_yesno.h b/engines/xeen/dialogs_yesno.h
deleted file mode 100644
index 96c3592..0000000
--- a/engines/xeen/dialogs_yesno.h
+++ /dev/null
@@ -1,43 +0,0 @@
-/* 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_YESNO_H
-#define XEEN_DIALOGS_YESNO_H
-
-#include "xeen/dialogs.h"
-
-namespace Xeen {
-
-class YesNo : public ButtonContainer {
-private:
-	XeenEngine *_vm;
-
-	YesNo(XeenEngine *vm) : ButtonContainer(), _vm(vm) {}
-
-	bool execute(bool type, bool townFlag);
-public:
-	static bool show(XeenEngine *vm, bool type, bool townFlag = false);
-};
-
-} // End of namespace Xeen
-
-#endif /* XEEN_DIALOGS_YESNO_H */
diff --git a/engines/xeen/module.mk b/engines/xeen/module.mk
index 2556852..6a36f91 100644
--- a/engines/xeen/module.mk
+++ b/engines/xeen/module.mk
@@ -12,17 +12,16 @@ MODULE_OBJS := \
 	automap.o \
 	dialogs_automap.o \
 	dialogs_char_info.o \
-	dialogs_confirm.o \
 	dialogs_error.o \
 	dialogs_exchange.o \
 	dialogs_options.o \
 	dialogs_info.o \
 	dialogs_input.o \
 	dialogs_items.o \
+	dialogs_query.o \
 	dialogs_quick_ref.o \
 	dialogs_spells.o \
 	dialogs_whowill.o \
-	dialogs_yesno.o \
 	events.o \
 	files.o \
 	font.o \
diff --git a/engines/xeen/resources.cpp b/engines/xeen/resources.cpp
index 5cd09cf..0f6588a 100644
--- a/engines/xeen/resources.cpp
+++ b/engines/xeen/resources.cpp
@@ -1144,4 +1144,6 @@ const char *const CANNOT_REMOVE_CURSED_ITEM = "\x3""You cannot remove a cursed i
 
 const char *const CANNOT_DISCARD_CURSED_ITEM = "\3x""cYou cannot discard a cursed item!";
 
+const char *const PERMANENTLY_DISCARD = "\v000\t000\x03lPermanently discard %s\fd?";
+
 } // End of namespace Xeen
diff --git a/engines/xeen/resources.h b/engines/xeen/resources.h
index 8be195f..87b9468 100644
--- a/engines/xeen/resources.h
+++ b/engines/xeen/resources.h
@@ -418,6 +418,8 @@ extern const char *const CANNOT_REMOVE_CURSED_ITEM;
 
 extern const char *const CANNOT_DISCARD_CURSED_ITEM;
 
+extern const char *const PERMANENTLY_DISCARD;
+
 } // End of namespace Xeen
 
 #endif	/* XEEN_RESOURCES_H */
diff --git a/engines/xeen/scripts.cpp b/engines/xeen/scripts.cpp
index 12fe2f1..4859e93 100644
--- a/engines/xeen/scripts.cpp
+++ b/engines/xeen/scripts.cpp
@@ -23,7 +23,7 @@
 #include "xeen/scripts.h"
 #include "xeen/dialogs_input.h"
 #include "xeen/dialogs_whowill.h"
-#include "xeen/dialogs_yesno.h"
+#include "xeen/dialogs_query.h"
 #include "xeen/party.h"
 #include "xeen/resources.h"
 #include "xeen/xeen.h"
diff --git a/engines/xeen/town.cpp b/engines/xeen/town.cpp
index 3df2685..3a07d2a 100644
--- a/engines/xeen/town.cpp
+++ b/engines/xeen/town.cpp
@@ -23,7 +23,7 @@
 #include "xeen/town.h"
 #include "xeen/dialogs_input.h"
 #include "xeen/dialogs_items.h"
-#include "xeen/dialogs_yesno.h"
+#include "xeen/dialogs_query.h"
 #include "xeen/dialogs_spells.h"
 #include "xeen/resources.h"
 #include "xeen/xeen.h"


Commit: d40c62532abfeb0d7fdbc005a16698ce19afe43b
    https://github.com/scummvm/scummvm/commit/d40c62532abfeb0d7fdbc005a16698ce19afe43b
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-02-06T20:57:01-05:00

Commit Message:
XEEN: Implemented makeItem

Changed paths:
    engines/xeen/character.cpp
    engines/xeen/character.h
    engines/xeen/dialogs_items.cpp
    engines/xeen/dialogs_items.h
    engines/xeen/resources.cpp
    engines/xeen/resources.h
    engines/xeen/scripts.h



diff --git a/engines/xeen/character.cpp b/engines/xeen/character.cpp
index 8fd7a35..3489783 100644
--- a/engines/xeen/character.cpp
+++ b/engines/xeen/character.cpp
@@ -73,6 +73,11 @@ InventoryItems::InventoryItems(Character *character, ItemCategory category):
 	_names = NAMES[category];
 }
 
+void InventoryItems::clear() {
+	for (uint idx = 0; idx < size(); ++idx)
+		operator[](idx).clear();
+}
+
 /**
 * Return whether a given item passes class-based usage restrictions
 */
@@ -199,6 +204,12 @@ void InventoryItems::equipError(int itemIndex1, ItemCategory category1, int item
 	}
 }
 
+void InventoryItems::enchantItem(int itemIndex, int amount) {
+	XeenEngine *vm = Party::_vm;
+	vm->_sound->playFX(21);
+	ErrorScroll::show(vm, Common::String::format(NOT_ENCHANTABLE, SPELL_FAILED));
+}
+
 /*------------------------------------------------------------------------*/
 
 /**
@@ -273,6 +284,23 @@ Common::String WeaponItems::getFullDescription(int itemIndex, int displayNum) {
 	);
 }
 
+void WeaponItems::enchantItem(int itemIndex, int amount) {
+	SoundManager &sound = *vm()->_sound;
+	XeenItem &item = operator[](itemIndex);
+	Character tempCharacter;
+
+	if (item._material == 0 && item._bonusFlags == 0 && item._id != 34) {
+		tempCharacter.makeItem(amount, 0, 1);
+		XeenItem &tempItem = tempCharacter._weapons[0];
+
+		item._material = tempItem._material;
+		item._bonusFlags = tempItem._bonusFlags;
+		sound.playFX(19);
+	} else {
+		InventoryItems::enchantItem(itemIndex, amount);
+	}
+}
+
 /*------------------------------------------------------------------------*/
 
 /**
@@ -374,6 +402,23 @@ Common::String ArmorItems::getFullDescription(int itemIndex, int displayNum) {
 	);
 }
 
+void ArmorItems::enchantItem(int itemIndex, int amount) {
+	SoundManager &sound = *vm()->_sound;
+	XeenItem &item = operator[](itemIndex);
+	Character tempCharacter;
+
+	if (item._material == 0 && item._bonusFlags == 0) {
+		tempCharacter.makeItem(amount, 0, 2);
+		XeenItem &tempItem = tempCharacter._armor[0];
+
+		item._material = tempItem._material;
+		item._bonusFlags = tempItem._bonusFlags;
+		sound.playFX(19);
+	} else {
+		InventoryItems::enchantItem(itemIndex, amount);
+	}
+}
+
 /*------------------------------------------------------------------------*/
 
 /**
@@ -498,6 +543,10 @@ AttributePair::AttributePair() {
 Character::Character():
 		_weapons(this), _armor(this), _accessories(this), _misc(this),
 		_items(_weapons, _armor, _accessories, _misc) {
+	clear();
+}
+
+void Character::clear() {
 	_sex = MALE;
 	_race = HUMAN;
 	_xeenSide = 0;
@@ -522,6 +571,24 @@ Character::Character():
 	_experience = 0;
 	_currentAdventuringSpell = 0;
 	_currentCombatSpell = 0;
+
+	_might._permanent = _might._temporary = 0;
+	_intellect._permanent = _intellect._temporary = 0;
+	_personality._permanent = _personality._temporary = 0;
+	_endurance._permanent = _endurance._temporary = 0;
+	_speed._permanent = _speed._temporary = 0;
+	_accuracy._permanent = _accuracy._temporary = 0;
+	_luck._permanent = _luck._temporary = 0;
+	_fireResistence._permanent = _fireResistence._temporary = 0;
+	_coldResistence._permanent = _coldResistence._temporary = 0;
+	_electricityResistence._permanent = _electricityResistence._temporary = 0;
+	_poisonResistence._permanent = _poisonResistence._temporary = 0;
+	_energyResistence._permanent = _energyResistence._temporary = 0;
+	_magicResistence._permanent = _magicResistence._temporary = 0;
+	_weapons.clear();
+	_armor.clear();
+	_accessories.clear();
+	_misc.clear();
 }
 
 void Character::synchronize(Common::Serializer &s) {
@@ -1309,4 +1376,250 @@ int Character::getNumAwards() const {
 	return total;
 }
 
+int Character::makeItem(int p1, int itemIndex, int p3) {
+	XeenEngine *vm = Party::_vm;
+	Scripts &scripts = *vm->_scripts;
+
+	if (!p1)
+		return 0;
+
+	int itemId = 0;
+	int v4 = vm->getRandomNumber(100);
+	int v6 = vm->getRandomNumber(p1 < 6 ? 100 : 80);
+	ItemCategory category;
+	int v16 = 0, v14 = 0, miscBonus = 0, miscId = 0, v8 = 0, v12 = 0;
+
+	// Randomly pick a category and item Id
+	if (p3 == 12) {
+		if (scripts._itemType < 35) {
+			category = CATEGORY_WEAPON;
+			itemId = scripts._itemType;
+		} else if (scripts._itemType < 49) {
+			category = CATEGORY_ARMOR;
+			itemId = scripts._itemType - 35;
+		} else if (scripts._itemType < 60) {
+			category = CATEGORY_ACCESSORY;
+			itemId = scripts._itemType - 49;
+		} else {
+			category = CATEGORY_MISC;
+			itemId = scripts._itemType - 60;
+		}
+	} else {
+		switch (p3) {
+		case 1:
+			v4 = 35;
+			break;
+		case 2:
+			v4 = 60;
+			break;
+		case 3:
+			v4 = 100;
+			break;
+		default:
+			break;
+		}
+
+		if (p1 == 1) {
+			if (v4 <= 40) {
+				category = CATEGORY_WEAPON;
+				if (v6 <= 30) {
+					itemId = vm->getRandomNumber(1, 6);
+				} else if (v6 <= 60) {
+					itemId = vm->getRandomNumber(7, 17);
+				} else if (v6 <= 85) {
+					itemId = vm->getRandomNumber(18, 29);
+				} else {
+					itemId = vm->getRandomNumber(30, 33);
+				}
+			} else if (v4 <= 85) {
+				category = CATEGORY_ARMOR;
+				itemId = vm->getRandomNumber(1, 7);
+			} else {
+				category = CATEGORY_MISC;
+				itemId = vm->getRandomNumber(1, 9);
+			}
+		} else if (v4 <= 35) {
+			category = CATEGORY_WEAPON;
+			if (v6 <= 30) {
+				itemId = vm->getRandomNumber(1, 6);
+			} else if (v6 <= 60) {
+				itemId = vm->getRandomNumber(7, 17);
+			} else if (v6 <= 85) {
+				itemId = vm->getRandomNumber(18, 29);
+			} else {
+				itemId = vm->getRandomNumber(30, 33);
+			}
+		} else if (v4 <= 60) {
+			category = CATEGORY_ARMOR;
+			itemId = (v6 > 70) ? 8 : vm->getRandomNumber(1, 7);
+		} else if (v6 <= 10) {
+			category = CATEGORY_ARMOR;
+			itemId = 9;
+		} else if (v6 <= 20) {
+			category = CATEGORY_ARMOR;
+			itemId = 13;
+		} else if (v6 <= 35) {
+			category = CATEGORY_ACCESSORY;
+			itemId = 1;
+		} else if (v6 <= 45) {
+			category = CATEGORY_ARMOR;
+			itemId = 10;
+		} else if (v6 <= 55) {
+			category = CATEGORY_ARMOR;
+			itemId = vm->getRandomNumber(11, 12);
+		} else if (v6 <= 65) {
+			category = CATEGORY_ACCESSORY;
+			itemId = 2;
+		} else if (v6 <= 75) {
+			category = CATEGORY_ACCESSORY;
+			itemId = vm->getRandomNumber(3, 7);
+		} else if (v6 <= 80) {
+			category = CATEGORY_ACCESSORY;
+			itemId = vm->getRandomNumber(8, 10);
+		} else {
+			category = CATEGORY_MISC;
+			itemId = vm->getRandomNumber(1, 9);
+		}
+	}
+
+	XeenItem &newItem = _items[category][itemIndex];
+	newItem.clear();
+	newItem._id = itemId;
+
+	v4 = vm->getRandomNumber(1, 100);
+	switch (category) {
+	case CATEGORY_WEAPON:
+	case CATEGORY_ARMOR:
+		if (p1 != 1) {
+			if (v4 <= 70) {
+				v8 = 3;
+			} else if (v4 <= 98) {
+				v8 = 1;
+			} else {
+				v8 = 2;
+			}
+		}
+		break;
+
+	case CATEGORY_ACCESSORY:
+		if (v4 <= 20) {
+			v8 = 3;
+		} else if (v4 <= 60) {
+			v8 = 1;
+		} else {
+			v8 = 2;
+		}
+		break;
+
+	case CATEGORY_MISC:
+		v8 = 4;
+		break;
+	}
+
+	if (p1 != 1 || category == CATEGORY_MISC) {
+		int rval, mult;
+		switch (v8) {
+		case 1:
+			rval = vm->getRandomNumber(1, 100);
+			if (rval <= 25) {
+				mult = 0;
+			}
+			else if (rval <= 45) {
+				mult = 1;
+			}
+			else if (rval <= 60) {
+				mult = 2;
+			}
+			else if (rval <= 75) {
+				mult = 3;
+			}
+			else if (rval <= 95) {
+				mult = 4;
+			}
+			else {
+				mult = 5;
+			}
+
+			v12 = MAKE_ITEM_ARR1[vm->getRandomNumber(MAKE_ITEM_ARR2[mult][p1][0],
+				MAKE_ITEM_ARR2[mult][p1][1])];
+			break;
+
+		case 2:
+			rval = vm->getRandomNumber(1, 100);
+			if (rval <= 15) {
+				mult = 0;
+			}
+			else if (rval <= 25) {
+				mult = 1;
+			}
+			else if (rval <= 35) {
+				mult = 2;
+			}
+			else if (mult <= 50) {
+				mult = 3;
+			}
+			else if (mult <= 65) {
+				mult = 4;
+			}
+			else if (mult <= 80) {
+				mult = 5;
+			}
+			else if (mult <= 85) {
+				mult = 6;
+			}
+			else if (mult <= 90) {
+				mult = 7;
+			}
+			else if (mult <= 95) {
+				mult = 8;
+			}
+			else {
+				mult = 9;
+			}
+
+			v12 = MAKE_ITEM_ARR1[vm->getRandomNumber(MAKE_ITEM_ARR3[mult][p1][0],
+				MAKE_ITEM_ARR3[mult][p1][1])];
+			break;
+
+		case 3:
+			rval = p1 == 7 || vm->getRandomNumber(1, 100) > 70;
+			v16 = vm->getRandomNumber(MAKE_ITEM_ARR4[mult][p1][0],
+				MAKE_ITEM_ARR4[mult][p1][1]);
+			break;
+
+		case 4:
+			miscBonus = vm->getRandomNumber(MAKE_ITEM_ARR5[p1][0], MAKE_ITEM_ARR5[p1][1]);
+			break;
+
+		default:
+			break;
+		}
+	}
+
+	switch (category) {
+	case CATEGORY_WEAPON:
+		if (p1 != 1) {
+			newItem._material = (v14 ? v14 + 58 : 0) + (v16 ? v16 + 36 : 0) + v12;
+			if (vm->getRandomNumber(20) == 10)
+				newItem._bonusFlags = vm->getRandomNumber(1, 6);
+		}
+		break;
+
+	case CATEGORY_ARMOR:
+	case CATEGORY_ACCESSORY:
+		if (p1 != 1) {
+			newItem._material = (v14 ? v14 + 58 : 0) + (v16 ? v16 + 36 : 0) + v12;
+		}
+		break;
+
+	case CATEGORY_MISC:
+		newItem._id = miscId;
+		newItem._bonusFlags = miscBonus;
+		break;
+	}
+
+	return category;
+}
+
+
 } // End of namespace Xeen
diff --git a/engines/xeen/character.h b/engines/xeen/character.h
index 6514cae..af9f7c6 100644
--- a/engines/xeen/character.h
+++ b/engines/xeen/character.h
@@ -106,11 +106,13 @@ protected:
 public:
 	InventoryItems(Character *character, ItemCategory category);
 
+	void clear();
+
 	bool passRestrictions(int itemId, bool showError) const;
 
 	Common::String getName(int itemIndex);
 
-	virtual Common::String getFullDescription(int itemIndex, int displayNum) = 0;
+	virtual Common::String getFullDescription(int itemIndex, int displayNum = 15) = 0;
 
 	bool discardItem(int itemIndex);
 
@@ -119,6 +121,8 @@ public:
 	void removeItem(int itemIndex);
 
 	void sort();
+
+	virtual void enchantItem(int itemIndex, int amount);
 };
 
 class WeaponItems: public InventoryItems {
@@ -128,6 +132,8 @@ public:
 	virtual void equipItem(int itemIndex);
 
 	virtual Common::String getFullDescription(int itemIndex, int displayNum);
+
+	virtual void enchantItem(int itemIndex, int amount);
 };
 
 class ArmorItems : public InventoryItems {
@@ -137,6 +143,8 @@ public:
 	virtual void equipItem(int itemIndex);
 
 	virtual Common::String getFullDescription(int itemIndex, int displayNum);
+
+	virtual void enchantItem(int itemIndex, int amount);
 };
 
 class AccessoryItems : public InventoryItems {
@@ -226,6 +234,9 @@ public:
 	int _currentCombatSpell;
 public:
 	Character();
+
+	void clear();
+
 	void synchronize(Common::Serializer &s);
 
 	Condition worstCondition() const;
@@ -271,6 +282,8 @@ public:
 	int getNumSkills() const;
 
 	int getNumAwards() const;
+
+	int makeItem(int p1, int itemIndex, int p3);
 };
 
 } // End of namespace Xeen
diff --git a/engines/xeen/dialogs_items.cpp b/engines/xeen/dialogs_items.cpp
index beaf565..46f07d4 100644
--- a/engines/xeen/dialogs_items.cpp
+++ b/engines/xeen/dialogs_items.cpp
@@ -21,6 +21,7 @@
  */
 
 #include "xeen/dialogs_items.h"
+#include "xeen/dialogs_query.h"
 #include "xeen/resources.h"
 #include "xeen/xeen.h"
 
@@ -41,7 +42,7 @@ Character *ItemsDialog::execute(Character *c, ItemsMode mode) {
 	Screen &screen = *_vm->_screen;
 	
 	Character *startingChar = c;
-	ItemCategory category = mode == ITEMMODE_4 || mode == ITEMMODE_COMBAT ? 
+	ItemCategory category = mode == ITEMMODE_RECHARGE || mode == ITEMMODE_COMBAT ? 
 		CATEGORY_MISC : CATEGORY_WEAPON;
 	int varA = mode == ITEMMODE_COMBAT ? 1 : 0;
 	if (varA != 0)
@@ -57,13 +58,13 @@ Character *ItemsDialog::execute(Character *c, ItemsMode mode) {
 	bool redrawFlag = true;
 	while (!_vm->shouldQuit()) {
 		if (redrawFlag) {
-			if ((mode != ITEMMODE_CHAR_INFO || category != CATEGORY_MISC) && mode != ITEMMODE_6
-					&& mode != ITEMMODE_4 && mode != ITEMMODE_TO_GOLD) {
+			if ((mode != ITEMMODE_CHAR_INFO || category != CATEGORY_MISC) && mode != ITEMMODE_ENCHANT
+					&& mode != ITEMMODE_RECHARGE && mode != ITEMMODE_TO_GOLD) {
 				_buttons[8]._bounds.moveTo(148, _buttons[8]._bounds.top);
 				_buttons[9]._draw = false;
-			} else if (mode == ITEMMODE_4) {
+			} else if (mode == ITEMMODE_RECHARGE) {
 				_buttons[4]._value = Common::KEYCODE_r;
-			} else if (mode == ITEMMODE_6) {
+			} else if (mode == ITEMMODE_ENCHANT) {
 				_buttons[4]._value = Common::KEYCODE_e;
 			} else if (mode == ITEMMODE_TO_GOLD) {
 				_buttons[4]._value = Common::KEYCODE_g;
@@ -75,17 +76,17 @@ Character *ItemsDialog::execute(Character *c, ItemsMode mode) {
 
 			// Write text for the dialog
 			Common::String msg;
-			if (mode != ITEMMODE_CHAR_INFO && mode != ITEMMODE_8 && mode != ITEMMODE_6
-					&& mode != ITEMMODE_4 && mode != ITEMMODE_TO_GOLD) {
+			if (mode != ITEMMODE_CHAR_INFO && mode != ITEMMODE_8 && mode != ITEMMODE_ENCHANT
+					&& mode != ITEMMODE_RECHARGE && mode != ITEMMODE_TO_GOLD) {
 				msg = Common::String::format(ITEMS_DIALOG_TEXT1,
 					BTN_SELL, BTN_IDENTIFY, BTN_FIX);
-			} else if (mode != ITEMMODE_6  && mode != ITEMMODE_4 && mode != ITEMMODE_TO_GOLD) {
+			} else if (mode != ITEMMODE_ENCHANT  && mode != ITEMMODE_RECHARGE && mode != ITEMMODE_TO_GOLD) {
 				msg = Common::String::format(ITEMS_DIALOG_TEXT1,
 					category == 3 ? BTN_USE : BTN_EQUIP, 
 					BTN_REMOVE, BTN_DISCARD, BTN_QUEST);
-			} else if (mode == ITEMMODE_6) {
+			} else if (mode == ITEMMODE_ENCHANT) {
 				msg = Common::String::format(ITEMS_DIALOG_TEXT2, BTN_ENCHANT);
-			} else if (mode == ITEMMODE_4) {
+			} else if (mode == ITEMMODE_RECHARGE) {
 				msg = Common::String::format(ITEMS_DIALOG_TEXT2, BTN_RECHARGE);
 			} else {
 				msg = Common::String::format(ITEMS_DIALOG_TEXT2, BTN_GOLD);
@@ -103,7 +104,7 @@ Character *ItemsDialog::execute(Character *c, ItemsMode mode) {
 		if (mode == ITEMMODE_CHAR_INFO || category != 3) {
 			_iconSprites.draw(screen, 8, Common::Point(148, 109));
 		}
-		if (mode != ITEMMODE_6 && mode != ITEMMODE_4 && mode != ITEMMODE_TO_GOLD) {
+		if (mode != ITEMMODE_ENCHANT && mode != ITEMMODE_RECHARGE && mode != ITEMMODE_TO_GOLD) {
 			_iconSprites.draw(screen, 10, Common::Point(182, 109));
 			_iconSprites.draw(screen, 12, Common::Point(216, 109));
 			_iconSprites.draw(screen, 14, Common::Point(250, 109));
@@ -138,7 +139,7 @@ Character *ItemsDialog::execute(Character *c, ItemsMode mode) {
 
 				if (i._id) {
 					if (mode == ITEMMODE_CHAR_INFO || mode == ITEMMODE_8
-							|| mode == ITEMMODE_6 || mode == ITEMMODE_4) {
+							|| mode == ITEMMODE_ENCHANT || mode == ITEMMODE_RECHARGE) {
 						lines.push_back(Common::String::format(ITEMS_DIALOG_LINE1, 
 							arr[idx], idx + 1,
 							c->_items[category].getFullDescription(idx, arr[idx])));
@@ -178,8 +179,8 @@ Character *ItemsDialog::execute(Character *c, ItemsMode mode) {
 					int skill = startingChar->_skills[MERCHANT];
 
 					if (mode == ITEMMODE_CHAR_INFO || mode == ITEMMODE_8
-							|| mode == ITEMMODE_6 || mode == ITEMMODE_4) {
-						tempMode = ITEMMODE_6;
+							|| mode == ITEMMODE_ENCHANT || mode == ITEMMODE_RECHARGE) {
+						tempMode = ITEMMODE_ENCHANT;
 					} else if (mode == ITEMMODE_TO_GOLD) {
 						skill = 1;
 					}
@@ -227,14 +228,14 @@ Character *ItemsDialog::execute(Character *c, ItemsMode mode) {
 		}
 
 		case ITEMMODE_2:
-		case ITEMMODE_4:
-		case ITEMMODE_6:
+		case ITEMMODE_RECHARGE:
+		case ITEMMODE_ENCHANT:
 		case ITEMMODE_9:
 		case ITEMMODE_10:
 		case ITEMMODE_TO_GOLD:
 			screen._windows[30].writeString(Common::String::format(X_FOR_Y,
 				CATEGORY_NAMES[category], startingChar->_name.c_str(),
-				(mode == ITEMMODE_4 || mode == ITEMMODE_6) ? CHARGES : COST,
+				(mode == ITEMMODE_RECHARGE || mode == ITEMMODE_ENCHANT) ? CHARGES : COST,
 				lines[0].c_str(), lines[1].c_str(), lines[2].c_str(), lines[3].c_str(),
 				lines[4].c_str(), lines[5].c_str(), lines[6].c_str(), lines[7].c_str(),
 				lines[8].c_str()
@@ -297,7 +298,7 @@ void ItemsDialog::loadButtons(ItemsMode mode, Character *&c) {
 		(mode == ITEMMODE_CHAR_INFO) ? "items" : "buy"));
 	_equipSprites.load("equip.icn");
 
-	if (mode == ITEMMODE_6 || mode == ITEMMODE_4 || mode == ITEMMODE_TO_GOLD) {
+	if (mode == ITEMMODE_ENCHANT || mode == ITEMMODE_RECHARGE || mode == ITEMMODE_TO_GOLD) {
 		// Enchant button list
 		addButton(Common::Rect(12, 109, 36, 129), Common::KEYCODE_w, &_iconSprites);
 		addButton(Common::Rect(46, 109, 70, 129), Common::KEYCODE_a, &_iconSprites);
@@ -537,14 +538,16 @@ int ItemsDialog::calcItemCost(Character *c, int itemIndex, ItemsMode mode,
 	return (mode == ITEMMODE_CHAR_INFO) ? 0 : result;
 }
 
-bool ItemsDialog::doItemOptions(Character &c, int actionIndex, int itemIndex, ItemCategory category,
+int ItemsDialog::doItemOptions(Character &c, int actionIndex, int itemIndex, ItemCategory category,
 		ItemsMode mode) {
 	Combat &combat = *_vm->_combat;
 	EventsManager &events = *_vm->_events;
 	Interface &intf = *_vm->_interface;
 	Party &party = *_vm->_party;
 	Screen &screen = *_vm->_screen;
+	SoundManager &sound = *_vm->_sound;
 	Spells &spells = *_vm->_spells;
+	bool isDarkCc = _vm->_files->_isDarkCc;
 
 	XeenItem *itemCategories[4] = { &c._weapons[0], &c._armor[0], &c._accessories[0], &c._misc[0] };
 	XeenItem *items = itemCategories[category];
@@ -647,17 +650,116 @@ bool ItemsDialog::doItemOptions(Character &c, int actionIndex, int itemIndex, It
 							}
 						} else {
 							ErrorScroll::show(_vm, Common::String::format(NO_SPECIAL_ABILITIES,
-								c._items[category].getFullDescription(itemIndex, 15).c_str()
+								c._items[category].getFullDescription(itemIndex).c_str()
 							));
 						}
 					}
 				}
 				break;
 			case 3:
-				// TODO: Remaining switches
+				c._items[category].discardItem(itemIndex);
+				break;
 			default:
 				break;
 			}
+			break;
+
+		case ITEMMODE_BLACKSMITH: {
+			InventoryItems &items = _oldCharacter->_items[category];
+			if (items[INV_ITEMS_TOTAL - 1]._id) {
+				// If the last slot is in use, it means the list is full
+				ErrorScroll::show(_vm, Common::String::format(BACKPACK_IS_FULL,
+					_oldCharacter->_name.c_str()));
+			} else {
+				int cost = calcItemCost(_oldCharacter, itemIndex, mode, 0, category);
+				Common::String desc = c._items[category].getFullDescription(itemIndex);
+				if (Confirm::show(_vm, Common::String::format(BUY_X_FOR_Y_GOLD,
+						desc.c_str(), cost))) {
+					if (party.subtract(0, cost, 0, WT_FREEZE_WAIT)) {
+						if (isDarkCc) {
+							sound.playSample(0, 0);
+							File f("choice2.voc");
+							sound.playSample(&f, 0);
+						}
+
+						// Add entry to the end of the list
+						_oldCharacter->_items[category][8] = c._items[category][itemIndex];
+						_oldCharacter->_items[category][8]._frame = 0;
+						c._items[category].clear();
+						c._items[category].sort();
+						_oldCharacter->_items[category].sort();
+					}
+				}
+			}
+			return 0;
+		}
+
+		case ITEMMODE_2: {
+			XeenItem &item = c._items[category][itemIndex];
+			bool noNeed;
+			switch (category) {
+			case CATEGORY_WEAPON:
+				noNeed = (item._bonusFlags & ITEMFLAG_CURSED) || item._id == 34;
+				break;
+			default:
+				noNeed = item._bonusFlags & ITEMFLAG_CURSED;
+				break;
+			}
+
+			if (noNeed) {
+				ErrorScroll::show(_vm, Common::String::format(NO_NEED_OF_THIS,
+					c._items[category].getFullDescription(itemIndex).c_str()));
+			} else {
+				int cost = calcItemCost(&c, itemIndex, mode, c._skills[MERCHANT], category);
+				Common::String desc = c._items[category].getFullDescription(itemIndex);
+				Common::String msg = Common::String::format(SELL_X_FOR_Y_GOLD,
+					desc.c_str(), cost);
+
+				if (Confirm::show(_vm, msg)) {
+					// Remove the sold item and add gold to the party's total
+					item.clear();
+					c._items[category].sort();
+
+					party._gold += cost;
+				}
+			}
+			return 0;
+		}
+
+		case ITEMMODE_RECHARGE:
+			if (category != CATEGORY_MISC || c._misc[itemIndex]._material > 9
+					|| c._misc[itemIndex]._id == 53 || c._misc[itemIndex]._id == 0) {
+				sound.playFX(21);
+				ErrorScroll::show(_vm, Common::String::format(NOT_RECHARGABLE, SPELL_FAILED));
+			} else {
+				int charges = MIN(63, _vm->getRandomNumber(1, 6) +
+					(c._misc[itemIndex]._bonusFlags & ITEMFLAG_BONUS_MASK));
+				sound.playFX(20);
+
+				c._misc[itemIndex]._bonusFlags = (c._misc[itemIndex]._bonusFlags
+					& ~ITEMFLAG_BONUS_MASK) | charges;
+			}
+			return 2;
+
+		case ITEMMODE_ENCHANT: {
+			Character *ps = &_itemsCharacter;
+			ps->clear();
+			int charges = _vm->getRandomNumber(1, _oldCharacter->getCurrentLevel() / 5 + 1);
+			charges = MIN(charges, 5);
+
+			switch (category) {
+			case CATEGORY_WEAPON:
+
+			default:
+				break;
+			}
+
+			// TODO
+			return 2;
+		}
+
+		default:
+			break;
 		}
 	}
 
diff --git a/engines/xeen/dialogs_items.h b/engines/xeen/dialogs_items.h
index aff43f6..dab26e6 100644
--- a/engines/xeen/dialogs_items.h
+++ b/engines/xeen/dialogs_items.h
@@ -31,7 +31,7 @@ namespace Xeen {
 
 enum ItemsMode {
 	ITEMMODE_CHAR_INFO = 0, ITEMMODE_BLACKSMITH = 1, ITEMMODE_2 = 2, ITEMMODE_3 = 3,
-	ITEMMODE_4 = 4, ITEMMODE_5 = 5, ITEMMODE_6 = 6, ITEMMODE_COMBAT = 7, ITEMMODE_8 = 8, 
+	ITEMMODE_RECHARGE = 4, ITEMMODE_5 = 5, ITEMMODE_ENCHANT = 6, ITEMMODE_COMBAT = 7, ITEMMODE_8 = 8, 
 	ITEMMODE_9 = 9, ITEMMODE_10 = 10, ITEMMODE_TO_GOLD = 11
 };
 
@@ -58,7 +58,7 @@ private:
 	int calcItemCost(Character *c, int itemIndex, ItemsMode mode, int skillLevel, 
 		ItemCategory category);
 
-	bool doItemOptions(Character &c, int actionIndex, int itemIndex, 
+	int doItemOptions(Character &c, int actionIndex, int itemIndex, 
 		ItemCategory category, ItemsMode mode);
 public:
 	static Character *show(XeenEngine *vm, Character *c, ItemsMode mode);
diff --git a/engines/xeen/resources.cpp b/engines/xeen/resources.cpp
index 0f6588a..23eac4f 100644
--- a/engines/xeen/resources.cpp
+++ b/engines/xeen/resources.cpp
@@ -596,6 +596,41 @@ const int METAL_LAC[9] = { -3, 0, -2, -1, 1, 2, 4, 6, 8 };
 
 const int ARMOR_STRENGTHS[14] = { 0, 2, 4, 5, 6, 7, 8, 10, 4, 2, 1, 1, 1, 1 };
 
+const int MAKE_ITEM_ARR1[6] = { 0, 8, 15, 20, 25, 33 };
+
+const int MAKE_ITEM_ARR2[6][7][2] = {
+	{ { 0, 0 }, { 1, 3 }, { 2, 5 }, { 3, 6 }, { 4, 7 }, { 5, 8 }, { 8, 8 } },
+	{ { 0, 0 }, { 1, 3 }, { 2, 5 }, { 3, 6 }, { 4, 7 }, { 6, 7 }, { 7, 7 } },
+	{ { 0, 0 }, { 1, 2 }, { 1, 3 }, { 2, 4 }, { 3, 5 }, { 4, 5 }, { 5, 5 } },
+	{ { 0, 0 }, { 1, 2 }, { 1, 3 }, { 2, 4 }, { 3, 4 }, { 4, 5 }, { 5, 5 } },
+	{ { 0, 0 }, { 1, 3 }, { 2, 5 }, { 3, 6 }, { 4, 7 }, { 5, 8 }, { 8, 8 } },
+	{ { 0, 0 }, { 1, 1 }, { 1, 1 }, { 1, 2 }, { 2, 2 }, { 2, 3 }, { 3, 3 } }
+};
+
+const int MAKE_ITEM_ARR3[10][7][2] = {
+	{ { 0, 0 }, { 1, 4 }, { 2, 5 }, { 3, 6 }, { 4, 7 }, { 6, 10 }, { 10, 10 } },
+	{ { 0, 0 }, { 1, 3 }, { 2, 5 }, { 3, 6 }, { 4, 7 }, { 5, 8 }, { 8, 8 } },
+	{ { 0, 0 }, { 1, 3 }, { 2, 5 }, { 3, 6 }, { 4, 7 }, { 5, 8 }, { 8, 8 } },
+	{ { 0, 0 }, { 1, 3 }, { 2, 5 }, { 3, 6 }, { 4, 7 }, { 5, 8 }, { 8, 8 } },
+	{ { 0, 0 }, { 1, 2 }, { 1, 3 }, { 2, 4 }, { 3, 5 }, { 4, 6 }, { 6, 6 } },
+	{ { 0, 0 }, { 1, 2 }, { 2, 3 }, { 3, 4 }, { 4, 5 }, { 5, 6 }, { 6, 6 } },
+	{ { 0, 0 }, { 1, 2 }, { 1, 3 }, { 2, 4 }, { 3, 4 }, { 4, 5 }, { 5, 5 } },
+	{ { 0, 0 }, { 1, 2 }, { 1, 3 }, { 2, 4 }, { 3, 5 }, { 4, 6 }, { 6, 6 } },
+	{ { 0, 0 }, { 1, 2 }, { 1, 3 }, { 2, 4 }, { 3, 4 }, { 4, 5 }, { 5, 5 } },
+	{ { 0, 0 }, { 1, 2 }, { 1, 4 }, { 3, 6 }, { 5, 8 }, { 7, 10 }, { 10, 10 } }
+};
+
+const int MAKE_ITEM_ARR4[2][7][2] = {
+	{ { 0, 0 }, { 1, 4 }, { 3, 7 }, { 4, 8 }, { 5, 9 }, { 8, 9 }, { 9, 9 } },
+	{ { 0, 0 }, { 1, 4 }, { 2, 6 }, { 4, 7 }, { 6, 10 }, { 9, 13 }, { 13, 13 } }
+};
+
+
+const int MAKE_ITEM_ARR5[8][2] = {
+	{ 0, 0 }, { 1, 15 }, { 16, 30 }, { 31, 40 }, { 41, 50 },
+	{ 51, 60 }, { 61, 73 }, { 61, 73 }
+};
+
 const int OUTDOOR_DRAWSTRCT_INDEXES[44] = {
 	37, 38, 39, 40, 41, 44, 42, 43, 47, 45, 46,
 	48, 49, 52, 50, 51, 66, 67, 68, 69, 70, 71,
@@ -1146,4 +1181,18 @@ const char *const CANNOT_DISCARD_CURSED_ITEM = "\3x""cYou cannot discard a curse
 
 const char *const PERMANENTLY_DISCARD = "\v000\t000\x03lPermanently discard %s\fd?";
 
+const char *const BACKPACK_IS_FULL = "\v005\x03c\fd%s's backpack is full.";
+
+const char *const BUY_X_FOR_Y_GOLD = "\x3l\v000\t000\fdBuy %s\fd for %lu gold?";
+
+const char *const SELL_X_FOR_Y_GOLD = "\x3l\v000\t000\fdSell %s\fd for %lu gold?";
+
+const char *const NO_NEED_OF_THIS = "\v005\x03c\fdWe have no need of this %s\f!";
+
+const char *const NOT_RECHARGABLE = "\v012\x03c\fdNot Rechargeable.  %s";
+
+const char *const NOT_ENCHANTABLE = "\v012\t000\x03cNot Enchantable.  %s";
+
+const char *const SPELL_FAILED = "Spell Failed!";
+
 } // End of namespace Xeen
diff --git a/engines/xeen/resources.h b/engines/xeen/resources.h
index 87b9468..6e757bc 100644
--- a/engines/xeen/resources.h
+++ b/engines/xeen/resources.h
@@ -176,6 +176,16 @@ extern const int METAL_LAC[9];
 
 extern const int ARMOR_STRENGTHS[14];
 
+extern const int MAKE_ITEM_ARR1[6];
+
+extern const int MAKE_ITEM_ARR2[6][7][2];
+
+extern const int MAKE_ITEM_ARR3[10][7][2];
+
+extern const int MAKE_ITEM_ARR4[2][7][2];
+
+extern const int MAKE_ITEM_ARR5[8][2];
+
 extern const int OUTDOOR_DRAWSTRCT_INDEXES[44];
 
 extern const int TOWN_MAXES[2][11];
@@ -420,6 +430,20 @@ extern const char *const CANNOT_DISCARD_CURSED_ITEM;
 
 extern const char *const PERMANENTLY_DISCARD;
 
+extern const char *const BACKPACK_IS_FULL;
+
+extern const char *const BUY_X_FOR_Y_GOLD;
+
+extern const char *const SELL_X_FOR_Y_GOLD;
+
+extern const char *const NO_NEED_OF_THIS;
+
+extern const char *const NOT_RECHARGABLE;
+
+extern const char *const SPELL_FAILED;
+
+extern const char *const NOT_ENCHANTABLE;
+
 } // End of namespace Xeen
 
 #endif	/* XEEN_RESOURCES_H */
diff --git a/engines/xeen/scripts.h b/engines/xeen/scripts.h
index 59f202e..d51cd0c 100644
--- a/engines/xeen/scripts.h
+++ b/engines/xeen/scripts.h
@@ -140,7 +140,6 @@ class Scripts {
 private:
 	XeenEngine *_vm;
 	int _charFX[6];
-	int _itemType;
 	int _treasureItems;
 	int _treasureGold;
 	int _treasureGems;
@@ -229,6 +228,7 @@ public:
 	bool _eventSkipped;
 	int _whoWill;
 	int _nEdamageType;
+	int _itemType;
 	Common::Array<MirrorEntry> _mirror;
 public:
 	Scripts(XeenEngine *vm);


Commit: 5ffbe2de873e6ac789ce9eff298a4ab21d02196b
    https://github.com/scummvm/scummvm/commit/5ffbe2de873e6ac789ce9eff298a4ab21d02196b
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-02-07T11:45:20-05:00

Commit Message:
XEEN: Implemented getIdentifiedDetails and getAttributes

Changed paths:
    engines/xeen/character.cpp
    engines/xeen/character.h
    engines/xeen/dialogs_items.cpp
    engines/xeen/dialogs_items.h
    engines/xeen/party.h
    engines/xeen/resources.cpp
    engines/xeen/resources.h
    engines/xeen/spells.h



diff --git a/engines/xeen/character.cpp b/engines/xeen/character.cpp
index 3489783..cde244b 100644
--- a/engines/xeen/character.cpp
+++ b/engines/xeen/character.cpp
@@ -44,21 +44,21 @@ void XeenItem::synchronize(Common::Serializer &s) {
 	s.syncAsByte(_frame);
 }
 
-int XeenItem::getElementalCategory() const {
+ElementalCategory XeenItem::getElementalCategory() const {
 	int idx;
 	for (idx = 0; ELEMENTAL_CATEGORIES[idx] < _material; ++idx)
 		;
 
-	return idx;
+	return (ElementalCategory)idx;
 }
 
-int XeenItem::getAttributeCategory() const {
+AttributeCategory XeenItem::getAttributeCategory() const {
 	int m = _material - 59;
 	int idx;
 	for (idx = 0; ATTRIBUTE_CATEGORIES[idx] < m; ++idx)
 		;
 
-	return idx;
+	return (AttributeCategory)idx;
 }
 
 /*------------------------------------------------------------------------*/
@@ -125,6 +125,24 @@ Common::String InventoryItems::getName(int itemIndex) {
 	return _names[id];
 }
 
+Common::String InventoryItems::getIdentifiedDetails(int itemIndex) {
+	XeenItem &item = operator[](itemIndex);
+
+	Common::String classes;
+	for (int charClass = CLASS_KNIGHT; charClass <= CLASS_RANGER; ++charClass) {
+		if (passRestrictions(charClass, true)) {
+			const char *const name = CLASS_NAMES[charClass];
+			classes += name[0];
+			classes += name[1];
+			classes += " ";
+		}
+	}
+	if (classes.size() == 30)
+		classes = ALL;
+
+	return getAttributes(item, classes);
+}
+
 /**
  * Discard an item from the inventory
  */
@@ -301,6 +319,53 @@ void WeaponItems::enchantItem(int itemIndex, int amount) {
 	}
 }
 
+/*
+ * Returns a text string listing all the stats/attributes of a given item
+ */
+Common::String WeaponItems::getAttributes(XeenItem &item, const Common::String &classes) {
+	Common::String attrBonus, elemDamage, physDamage, toHit, specialPower;
+	attrBonus = elemDamage = physDamage = toHit = specialPower = FIELD_NONE;
+
+	// First calculate physical damage
+	int minVal = WEAPON_DAMAGE_BASE[item._id];
+	int maxVal = minVal * WEAPON_DAMAGE_MULTIPLIER[item._id];
+
+	if (item._material >= 37 && item._material <= 58) {
+		minVal += METAL_DAMAGE[item._material - 37];
+		maxVal += METAL_DAMAGE[item._material - 37];
+		toHit = Common::String::format("%+d", METAL_DAMAGE_PERCENT[item._material - 37]);
+	}
+	
+	physDamage = Common::String::format(DAMAGE_X_TO_Y, minVal, maxVal);
+
+	// Next handle elemental/attribute damage
+	if (item._material < 37) {
+		int damage = ELEMENTAL_DAMAGE[item._material];
+		if (damage > 0) {
+			ElementalCategory elemCategory = item.getElementalCategory();
+			elemDamage = Common::String::format(ELEMENTAL_XY_DAMAGE,
+				damage, ELEMENTAL_NAMES[elemCategory]);
+		}
+	} else if (item._material >= 59) {
+		int bonus = ATTRIBUTE_BONUSES[item._material - 59];
+		AttributeCategory attrCategory = item.getAttributeCategory();
+		attrBonus = Common::String::format(ATTR_XY_BONUS, bonus,
+			ATTRIBUTE_NAMES[attrCategory]);
+	}
+
+	// Handle weapon effective against
+	int effective = item._bonusFlags & ITEMFLAG_BONUS_MASK;
+	if (effective) {
+		specialPower = Common::String::format(EFFECTIVE_AGAINST,
+			EFFECTIVENESS_NAMES[effective]);
+	}
+
+	return Common::String::format(ITEM_DETAILS, classes.c_str(),
+		toHit.c_str(), physDamage.c_str(), elemDamage.c_str(),
+		FIELD_NONE, FIELD_NONE, attrBonus.c_str(), specialPower.c_str()
+	);
+}
+
 /*------------------------------------------------------------------------*/
 
 /**
@@ -419,6 +484,41 @@ void ArmorItems::enchantItem(int itemIndex, int amount) {
 	}
 }
 
+/*
+* Returns a text string listing all the stats/attributes of a given item
+*/
+Common::String ArmorItems::getAttributes(XeenItem &item, const Common::String &classes) {
+	Common::String elemResist, attrBonus, acBonus;
+	elemResist = attrBonus = acBonus = FIELD_NONE;
+
+	if (item._material < 36) {
+		int resistence = ELEMENTAL_RESISTENCES[item._material];
+		if (resistence > 0) {
+			int eCategory = ELEM_FIRE;
+			while (eCategory < ELEM_MAGIC && ELEMENTAL_CATEGORIES[eCategory] < item._material)
+				++eCategory;
+				
+			elemResist = Common::String::format(ATTR_XY_BONUS, resistence,
+				ELEMENTAL_NAMES[eCategory]);
+		}
+	} else if (item._material >= 59) {
+		int bonus = ATTRIBUTE_BONUSES[item._material - 59];
+		AttributeCategory aCategory = item.getAttributeCategory();
+		attrBonus = Common::String::format(ATTR_XY_BONUS, bonus,
+			ATTRIBUTE_NAMES[aCategory]);
+	}
+
+	int strength = ARMOR_STRENGTHS[item._id];
+	if (item._material >= 37 && item._material <= 58) {
+		strength += METAL_LAC[item._material - 37];
+	}
+	acBonus = Common::String::format("%+d", strength);
+
+	return Common::String::format(ITEM_DETAILS, classes.c_str(),
+		FIELD_NONE, FIELD_NONE, FIELD_NONE,
+		elemResist.c_str(), acBonus.c_str(), attrBonus.c_str(), FIELD_NONE);
+}
+
 /*------------------------------------------------------------------------*/
 
 /**
@@ -490,6 +590,35 @@ Common::String AccessoryItems::getFullDescription(int itemIndex, int displayNum)
 	);
 }
 
+/*
+* Returns a text string listing all the stats/attributes of a given item
+*/
+Common::String AccessoryItems::getAttributes(XeenItem &item, const Common::String &classes) {
+	Common::String elemResist, attrBonus;
+	elemResist = attrBonus = FIELD_NONE;
+
+	if (item._material < 36) {
+		int resistence = ELEMENTAL_RESISTENCES[item._material];
+		if (resistence > 0) {
+			int eCategory = ELEM_FIRE;
+			while (eCategory < ELEM_MAGIC && ELEMENTAL_CATEGORIES[eCategory] < item._material)
+				++eCategory;
+
+			elemResist = Common::String::format(ATTR_XY_BONUS, resistence,
+				ELEMENTAL_NAMES[eCategory]);
+		}
+	} else if (item._material >= 59) {
+		int bonus = ATTRIBUTE_BONUSES[item._material - 59];
+		AttributeCategory aCategory = item.getAttributeCategory();
+		attrBonus = Common::String::format(ATTR_XY_BONUS, bonus,
+			ATTRIBUTE_NAMES[aCategory]);
+	}
+
+	return Common::String::format(ITEM_DETAILS, classes.c_str(),
+		FIELD_NONE, FIELD_NONE, FIELD_NONE,
+		elemResist.c_str(), FIELD_NONE, attrBonus.c_str(), FIELD_NONE);
+}
+
 /*------------------------------------------------------------------------*/
 
 /**
@@ -510,6 +639,22 @@ Common::String MiscItems::getFullDescription(int itemIndex, int displayNum) {
 	);
 }
 
+
+/*
+* Returns a text string listing all the stats/attributes of a given item
+*/
+Common::String MiscItems::getAttributes(XeenItem &item, const Common::String &classes) {
+	Common::String specialPower = FIELD_NONE;
+	Spells &spells = *vm()->_spells;
+
+	if (item._id) {
+		specialPower = spells._spellNames[MISC_SPELL_INDEX[item._id]];
+	}
+
+	return Common::String::format(ITEM_DETAILS, classes.c_str(),
+		FIELD_NONE, FIELD_NONE, FIELD_NONE, FIELD_NONE, FIELD_NONE, 
+		FIELD_NONE, specialPower.c_str());
+}
 /*------------------------------------------------------------------------*/
 
 InventoryItemsGroup::InventoryItemsGroup(InventoryItems &weapons, InventoryItems &armor,
@@ -975,8 +1120,8 @@ int Character::itemScan(int itemId) const {
 
 				if (item._frame && !(item._bonusFlags & 0xC0) && itemId < 11
 						&& itemId != 3 && item._material >= 59 && item._material <= 130) {
-					int mIndex = item.getAttributeCategory();
-					if (mIndex > 2)
+					int mIndex = (int)item.getAttributeCategory();
+					if (mIndex > PERSONALITY)
 						++mIndex;
 
 					if (mIndex == itemId)
@@ -991,8 +1136,8 @@ int Character::itemScan(int itemId) const {
 
 				if (item._frame && !(item._bonusFlags & 0xC0)) {
 					if (itemId < 11 && itemId != 3 && item._material >= 59 && item._material <= 130) {
-						int mIndex = item.getAttributeCategory();
-						if (mIndex > 2)
+						int mIndex = (int)item.getAttributeCategory();
+						if (mIndex > PERSONALITY)
 							++mIndex;
 
 						if (mIndex == itemId)
@@ -1023,8 +1168,8 @@ int Character::itemScan(int itemId) const {
 
 				if (item._frame && !(item._bonusFlags & 0xC0) && itemId < 11 && itemId != 3) {
 					if (item._material >= 59 && item._material <= 130) {
-						int mIndex = item.getAttributeCategory();
-						if (mIndex > 2)
+						int mIndex = (int)item.getAttributeCategory();
+						if (mIndex > PERSONALITY)
 							++mIndex;
 
 						if (mIndex == itemId) {
diff --git a/engines/xeen/character.h b/engines/xeen/character.h
index af9f7c6..6e6a772 100644
--- a/engines/xeen/character.h
+++ b/engines/xeen/character.h
@@ -73,6 +73,17 @@ enum Condition {
 	NO_CONDITION = 16
 };
 
+enum ElementalCategory { 
+	ELEM_FIRE = 0, ELEM_ELECTRICITY = 1, ELEM_COLD = 2,
+	ELEM_ACID_POISON = 3, ELEM_ENERGY = 4, ELEM_MAGIC = 5 
+};
+
+enum AttributeCategory {
+	ATTR_MIGHT = 0, ATTR_INTELLECT = 1, ATTR_PERSONALITY = 2, ATTR_SPEED = 3,
+	ATTR_ACCURACY = 4, ATTR_LUCK = 5, ATTR_HIT_POINTS = 6, ATTR_SPELL_POINTS = 7,
+	ATTR_ARMOR_CLASS = 8, ATTR_THIEVERY  = 9
+};
+
 class XeenEngine;
 class Character;
 
@@ -89,9 +100,9 @@ public:
 
 	void synchronize(Common::Serializer &s);
 
-	int getElementalCategory() const;
+	ElementalCategory getElementalCategory() const;
 
-	int getAttributeCategory() const;
+	AttributeCategory getAttributeCategory() const;
 };
 
 class InventoryItems : public Common::Array<XeenItem> {
@@ -103,6 +114,8 @@ protected:
 	XeenEngine *vm();
 	void equipError(int itemIndex1, ItemCategory category1, int itemIndex2,
 		ItemCategory category2);
+
+	virtual Common::String getAttributes(XeenItem &item, const Common::String &classes) = 0;
 public:
 	InventoryItems(Character *character, ItemCategory category);
 
@@ -114,6 +127,8 @@ public:
 
 	virtual Common::String getFullDescription(int itemIndex, int displayNum = 15) = 0;
 
+	Common::String getIdentifiedDetails(int itemIndex);
+
 	bool discardItem(int itemIndex);
 
 	virtual void equipItem(int itemIndex) {}
@@ -126,6 +141,8 @@ public:
 };
 
 class WeaponItems: public InventoryItems {
+protected:
+	virtual Common::String getAttributes(XeenItem &item, const Common::String &classes);
 public:
 	WeaponItems(Character *character) : InventoryItems(character, CATEGORY_WEAPON) {}
 
@@ -137,6 +154,8 @@ public:
 };
 
 class ArmorItems : public InventoryItems {
+protected:
+	virtual Common::String getAttributes(XeenItem &item, const Common::String &classes);
 public:
 	ArmorItems(Character *character) : InventoryItems(character, CATEGORY_ARMOR) {}
 
@@ -148,6 +167,8 @@ public:
 };
 
 class AccessoryItems : public InventoryItems {
+protected:
+	virtual Common::String getAttributes(XeenItem &item, const Common::String &classes);
 public:
 	AccessoryItems(Character *character) : InventoryItems(character, CATEGORY_ACCESSORY) {}
 
@@ -157,6 +178,8 @@ public:
 };
 
 class MiscItems : public InventoryItems {
+protected:
+	virtual Common::String getAttributes(XeenItem &item, const Common::String &classes);
 public:
 	MiscItems(Character *character) : InventoryItems(character, CATEGORY_MISC) {}
 
diff --git a/engines/xeen/dialogs_items.cpp b/engines/xeen/dialogs_items.cpp
index 46f07d4..8466097 100644
--- a/engines/xeen/dialogs_items.cpp
+++ b/engines/xeen/dialogs_items.cpp
@@ -117,10 +117,10 @@ Character *ItemsDialog::execute(Character *c, ItemsMode mode) {
 		case ITEMMODE_BLACKSMITH:
 			_iconSprites.draw(screen, 11, Common::Point(182, 109));
 			break;
-		case ITEMMODE_9:
+		case ITEMMODE_REPAIR:
 			_iconSprites.draw(screen, 15, Common::Point(250, 109));
 			break;
-		case ITEMMODE_10:
+		case ITEMMODE_IDENTIFY:
 			_iconSprites.draw(screen, 13, Common::Point(216, 109));
 			break;
 		default:
@@ -230,8 +230,8 @@ Character *ItemsDialog::execute(Character *c, ItemsMode mode) {
 		case ITEMMODE_2:
 		case ITEMMODE_RECHARGE:
 		case ITEMMODE_ENCHANT:
-		case ITEMMODE_9:
-		case ITEMMODE_10:
+		case ITEMMODE_REPAIR:
+		case ITEMMODE_IDENTIFY:
 		case ITEMMODE_TO_GOLD:
 			screen._windows[30].writeString(Common::String::format(X_FOR_Y,
 				CATEGORY_NAMES[category], startingChar->_name.c_str(),
@@ -269,10 +269,10 @@ Character *ItemsDialog::execute(Character *c, ItemsMode mode) {
 			case ITEMMODE_2:
 				actionIndex = 1;
 				break;
-			case ITEMMODE_9:
+			case ITEMMODE_REPAIR:
 				actionIndex = 3;
 				break;
-			case ITEMMODE_10:
+			case ITEMMODE_IDENTIFY:
 				actionIndex = 2;
 				break;
 			default:
@@ -448,10 +448,10 @@ int ItemsDialog::calcItemCost(Character *c, int itemIndex, ItemsMode mode,
 	case ITEMMODE_TO_GOLD:
 		level = level == 0 ? 1 : 0;
 		break;
-	case ITEMMODE_10:
+	case ITEMMODE_IDENTIFY:
 		level = 2;
 		break;
-	case ITEMMODE_9:
+	case ITEMMODE_REPAIR:
 		level = 3;
 		break;
 	default:
@@ -496,8 +496,8 @@ int ItemsDialog::calcItemCost(Character *c, int itemIndex, ItemsMode mode,
 		switch (mode) {
 		case ITEMMODE_BLACKSMITH:
 		case ITEMMODE_2:
-		case ITEMMODE_9:
-		case ITEMMODE_10:
+		case ITEMMODE_REPAIR:
+		case ITEMMODE_IDENTIFY:
 		case ITEMMODE_TO_GOLD:
 			result = (amount1 + amount2 + amount3 + amount4) / ITEM_SKILL_DIVISORS[level];
 			if (!result)
@@ -518,8 +518,8 @@ int ItemsDialog::calcItemCost(Character *c, int itemIndex, ItemsMode mode,
 		switch (mode) {
 		case ITEMMODE_BLACKSMITH:
 		case ITEMMODE_2:
-		case ITEMMODE_9:
-		case ITEMMODE_10:
+		case ITEMMODE_REPAIR:
+		case ITEMMODE_IDENTIFY:
 		case ITEMMODE_TO_GOLD:
 			result = (amount1 + amount2 + amount3 + amount4) / ITEM_SKILL_DIVISORS[level];
 			if (!result)
@@ -603,6 +603,8 @@ int ItemsDialog::doItemOptions(Character &c, int actionIndex, int itemIndex, Ite
 	}
 
 	if (itemIndex != -1) {
+		XeenItem &item = c._items[category][itemIndex];
+
 		switch (mode) {
 		case ITEMMODE_CHAR_INFO:
 		case ITEMMODE_8:
@@ -695,7 +697,6 @@ int ItemsDialog::doItemOptions(Character &c, int actionIndex, int itemIndex, Ite
 		}
 
 		case ITEMMODE_2: {
-			XeenItem &item = c._items[category][itemIndex];
 			bool noNeed;
 			switch (category) {
 			case CATEGORY_WEAPON:
@@ -742,20 +743,57 @@ int ItemsDialog::doItemOptions(Character &c, int actionIndex, int itemIndex, Ite
 			return 2;
 
 		case ITEMMODE_ENCHANT: {
-			Character *ps = &_itemsCharacter;
-			ps->clear();
-			int charges = _vm->getRandomNumber(1, _oldCharacter->getCurrentLevel() / 5 + 1);
-			charges = MIN(charges, 5);
-
-			switch (category) {
-			case CATEGORY_WEAPON:
+			int amount = _vm->getRandomNumber(1, _oldCharacter->getCurrentLevel() / 5 + 1);
+			amount = MIN(amount, 5);
+			_oldCharacter->_items[category].enchantItem(itemIndex, amount);
+			break;
+		}
 
-			default:
-				break;
+		case ITEMMODE_REPAIR:
+			if (!(item._bonusFlags & ITEMFLAG_BROKEN)) {
+				ErrorScroll::show(_vm, ITEM_NOT_BROKEN);
+			} else {
+				int cost = calcItemCost(&c, itemIndex, mode, actionIndex, category);
+				Common::String msg = Common::String::format(FIX_IDENTIFY_GOLD,
+					FIX_IDENTIFY[0],
+					c._items[category].getFullDescription(itemIndex),
+					cost);
+
+				if (Confirm::show(_vm, msg) && party.subtract(0, cost, 0)) {
+					item._bonusFlags &= ~ITEMFLAG_BROKEN;
+				}
 			}
+			break;
 
-			// TODO
-			return 2;
+		case ITEMMODE_IDENTIFY: {
+			int cost = calcItemCost(&c, itemIndex, mode, actionIndex, category);
+			Common::String msg = Common::String::format(FIX_IDENTIFY_GOLD,
+				FIX_IDENTIFY[1],
+				c._items[category].getFullDescription(itemIndex),
+				cost);
+
+			if (Confirm::show(_vm, msg) && party.subtract(0, cost, 0)) {
+				Common::String details = c._items[category].getIdentifiedDetails(itemIndex);
+				Common::String desc = c._items[category].getFullDescription(itemIndex);
+				Common::String msg = Common::String::format(IDENTIFY_ITEM_MSG,
+					desc.c_str(), details.c_str());
+
+				Window &w = screen._windows[14];
+				w.open();
+				w.writeString(msg);
+				w.update();
+
+				saveButtons();
+				clearButtons();
+
+				while (!_vm->shouldQuit() && !events.isKeyMousePressed())
+					events.pollEventsAndWait();
+				events.clearEvents();
+
+				restoreButtons();
+				w.close();
+			}
+			break;
 		}
 
 		default:
diff --git a/engines/xeen/dialogs_items.h b/engines/xeen/dialogs_items.h
index dab26e6..42fe015 100644
--- a/engines/xeen/dialogs_items.h
+++ b/engines/xeen/dialogs_items.h
@@ -32,7 +32,7 @@ namespace Xeen {
 enum ItemsMode {
 	ITEMMODE_CHAR_INFO = 0, ITEMMODE_BLACKSMITH = 1, ITEMMODE_2 = 2, ITEMMODE_3 = 3,
 	ITEMMODE_RECHARGE = 4, ITEMMODE_5 = 5, ITEMMODE_ENCHANT = 6, ITEMMODE_COMBAT = 7, ITEMMODE_8 = 8, 
-	ITEMMODE_9 = 9, ITEMMODE_10 = 10, ITEMMODE_TO_GOLD = 11
+	ITEMMODE_REPAIR = 9, ITEMMODE_IDENTIFY = 10, ITEMMODE_TO_GOLD = 11
 };
 
 class ItemsDialog : public ButtonContainer {
diff --git a/engines/xeen/party.h b/engines/xeen/party.h
index 8da1163..ec7a8b9 100644
--- a/engines/xeen/party.h
+++ b/engines/xeen/party.h
@@ -142,7 +142,7 @@ public:
 
 	void handleLight();
 
-	int subtract(int mode, uint amount, int whereId, ErrorWaitType wait);
+	int subtract(int mode, uint amount, int whereId, ErrorWaitType wait = WT_FREEZE_WAIT);
 
 	void notEnough(int consumableId, int whereId, bool mode, ErrorWaitType wait);
 };
diff --git a/engines/xeen/resources.cpp b/engines/xeen/resources.cpp
index 23eac4f..55060c8 100644
--- a/engines/xeen/resources.cpp
+++ b/engines/xeen/resources.cpp
@@ -592,6 +592,28 @@ const int ELEMENTAL_DAMAGE[37] = {
 	2, 4, 8, 16, 32, 2, 3, 4, 5, 10, 15, 20, 30, 5, 10, 25
 };
 
+const int WEAPON_DAMAGE_BASE[35] = {
+	0, 3, 2, 3, 2, 2, 4, 1, 2, 4, 2, 3,
+	2, 2, 1, 1, 1, 1, 4, 4, 3, 2, 4, 2,
+	2, 2, 5, 3, 3, 3, 3, 5, 4, 2, 6
+};
+
+const int WEAPON_DAMAGE_MULTIPLIER[35] = {
+	0, 3, 3, 4, 5, 4, 2, 3, 3, 3, 3, 3,
+	2, 4, 10, 6, 8, 9, 4, 3, 6, 8, 5, 6,
+	4, 5, 3, 5, 6, 7, 2, 2, 2, 2, 4
+};
+
+const int METAL_DAMAGE[22] = {
+	-3, -6, -4, -2, 2, 4, 6, 8, 10, 0, 1,
+	1, 2, 2, 3, 4, 5, 12, 15, 20, 30, 50
+};
+
+const int METAL_DAMAGE_PERCENT[22] = {
+	253, 252, 3, 2, 1, 2, 3, 4, 6, 0, 1,
+	1, 2, 2, 3, 4, 5, 6, 7, 8, 9, 10
+};
+
 const int METAL_LAC[9] = { -3, 0, -2, -1, 1, 2, 4, 6, 8 };
 
 const int ARMOR_STRENGTHS[14] = { 0, 2, 4, 5, 6, 7, 8, 10, 4, 2, 1, 1, 1, 1 };
@@ -791,6 +813,28 @@ const char *const GUILD_OPTIONS =
 	"\x03l\x09""000\x0B""090Gold"
 	"\x03r\x09""000%s\x02\x03""c\x0B""122\x09""040ESC\x01";
 
+const int MISC_SPELL_INDEX[74] = {
+	NO_SPELL, MS_Light, MS_Awaken, MS_MagicArrow,
+	MS_FirstAid, MS_FlyingFist, MS_EnergyBlast, MS_Sleep,
+	MS_Revitalize, MS_CureWounds, MS_Sparks, MS_Shrapmetal,
+	MS_InsectSpray, MS_ToxicCloud, MS_ProtFromElements, MS_Pain,
+	MS_Jump, MS_BeastMaster, MS_Clairvoyance, MS_TurnUndead,
+	MS_Levitate, MS_WizardEye, MS_Bless, MS_IdentifyMonster,
+	MS_LightningBolt, MS_HolyBonus, MS_PowerCure, MS_NaturesCure,
+	MS_LloydsBeacon, MS_PowerShield, MS_Heroism, MS_Hynotize,
+	MS_WalkOnWater, MS_FrostBite, MS_DetectMonster, MS_FireBall,
+	MS_ColdRay, MS_CurePoison, MS_AcidSpray, MS_TimeDistortion,
+	MS_DragonSleep, MS_CureDisease, MS_Teleport, MS_FingerOfDeath,
+	MS_CureParalysis, MS_GolemStopper, MS_PoisonVolley, MS_DeadlySwarm,
+	MS_SuperShelter, MS_DayOfProtection, MS_DayOfSorcery, MS_CreateFood,
+	MS_FieryFlail, MS_RechargeItem, MS_FantasticFreeze, MS_TownPortal,
+	MS_StoneToFlesh, MS_RaiseDead, MS_Etheralize, MS_DancingSword,
+	MS_MoonRay, MS_MassDistortion, MS_PrismaticLight, MS_EnchantItem,
+	MS_Incinerate, MS_HolyWord, MS_Resurrection, MS_ElementalStorm,
+	MS_MegaVolts, MS_Inferno, MS_SunRay, MS_Implosion,
+	MS_StarBurst, MS_DivineIntervention
+};
+
 const int SPELL_COSTS[77] = {
 	8, 1, 5, -2, 5, -2, 20, 10, 12, 8, 3,
 	- 3, 75, 40, 12, 6, 200, 10, 100, 30, -1, 30,
@@ -1087,6 +1131,19 @@ const char *const MISC_NAMES[22] = {
 	"bogus", "bogus", "bogus", "bogus"
 };
 
+const char *const ELEMENTAL_NAMES[6] = {
+	"Fire", "Elec", "Cold", "Acid/Poison", "Energy", "Magic"
+};
+
+const char *const ATTRIBUTE_NAMES[10] = {
+	"might", "Intellect", "Personality", "Speed", "accuracy", "Luck",
+	"Hit Points", "Spell Points", "Armor Class", "Thievery"
+};
+
+const char *const EFFECTIVENESS_NAMES[7] = {
+	nullptr, "Dragons", "Undead", "Golems", "Bugs", "Monsters", "Beasts"
+};
+
 const int WEAPON_BASE_COSTS[35] = {
 	0, 50, 15, 100, 80, 40, 60, 1, 10, 150, 30, 60, 8, 50,
 	100, 15, 30, 15, 200, 80, 250, 150, 400, 100, 40, 120,
@@ -1195,4 +1252,33 @@ const char *const NOT_ENCHANTABLE = "\v012\t000\x03cNot Enchantable.  %s";
 
 const char *const SPELL_FAILED = "Spell Failed!";
 
+const char *const ITEM_NOT_BROKEN =  "\fdThat item is not broken!";
+
+const char *const FIX_IDENTIFY[2] = { "Fix", "Identify" };
+
+const char *const FIX_IDENTIFY_GOLD = "\x3l\v000\t000%s %s\fd for %lu gold?";
+
+const char *const IDENTIFY_ITEM_MSG = "\fd\v000\t000\x3""cIdentify Item\x3l\n"
+	"\n"
+	"\v012%s\fd\n"
+	"\n"
+	"%s";
+
+const char *const ITEM_DETAILS =
+	"Proficient Classes\t132:\t140%s\n"
+	"to Hit Modifier\t132:\t140%s\n"
+	"Physical Damage\t132:\t140%s\n"
+	"Elemental Damage\t132:\t140%s\n"
+	"Elemental Resistance\t132:\t140%s\n"
+	"Armor Class Bonus\t132:\t140%s\n"
+	"Attribute Bonus\t132:\t140%s\n"
+	"Special Power\t132:\t140%s";
+
+const char *const ALL = "All";
+const char *const FIELD_NONE = "None";
+const char *const DAMAGE_X_TO_Y = "%d to %d";
+const char *const ELEMENTAL_XY_DAMAGE = "%+d %s Damage";
+const char *const ATTR_XY_BONUS = "%+d %s";
+const char *const EFFECTIVE_AGAINST = "x3 vs %s";
+
 } // End of namespace Xeen
diff --git a/engines/xeen/resources.h b/engines/xeen/resources.h
index 6e757bc..cab2af7 100644
--- a/engines/xeen/resources.h
+++ b/engines/xeen/resources.h
@@ -26,6 +26,7 @@
 #include "common/scummsys.h"
 #include "common/str-array.h"
 #include "gui/debugger.h"
+#include "xeen/spells.h"
 
 namespace Xeen {
 
@@ -172,6 +173,11 @@ extern const int ELEMENTAL_RESISTENCES[37];
 
 extern const int ELEMENTAL_DAMAGE[37];
 
+extern const int WEAPON_DAMAGE_BASE[35];
+extern const int WEAPON_DAMAGE_MULTIPLIER[35];
+extern const int METAL_DAMAGE[22];
+extern const int METAL_DAMAGE_PERCENT[22];
+
 extern const int METAL_LAC[9];
 
 extern const int ARMOR_STRENGTHS[14];
@@ -250,6 +256,8 @@ extern const char *const BUY_SPELLS;
 
 extern const char *const GUILD_OPTIONS;
 
+extern const int MISC_SPELL_INDEX[74];
+
 extern const int SPELL_COSTS[77];
 
 extern const int CLOUDS_SPELL_OFFSETS[5][20];
@@ -376,6 +384,9 @@ extern const char *const WEAPON_NAMES[35];
 extern const char *const ARMOR_NAMES[14];
 extern const char *const ACCESSORY_NAMES[11];
 extern const char *const MISC_NAMES[22];
+extern const char *const ELEMENTAL_NAMES[6];
+extern const char *const ATTRIBUTE_NAMES[10];
+extern const char *const EFFECTIVENESS_NAMES[7];
 
 extern const int WEAPON_BASE_COSTS[35];
 extern const int ARMOR_BASE_COSTS[25];
@@ -444,6 +455,23 @@ extern const char *const SPELL_FAILED;
 
 extern const char *const NOT_ENCHANTABLE;
 
+extern const char *const ITEM_NOT_BROKEN;
+
+extern const char *const FIX_IDENTIFY[2];
+
+extern const char *const FIX_IDENTIFY_GOLD;
+
+extern const char *const IDENTIFY_ITEM_MSG;
+
+extern const char *const ITEM_DETAILS;
+
+extern const char *const ALL;
+extern const char *const FIELD_NONE;
+extern const char *const DAMAGE_X_TO_Y;
+extern const char *const ELEMENTAL_XY_DAMAGE;
+extern const char *const ATTR_XY_BONUS;
+extern const char *const EFFECTIVE_AGAINST;
+
 } // End of namespace Xeen
 
 #endif	/* XEEN_RESOURCES_H */
diff --git a/engines/xeen/spells.h b/engines/xeen/spells.h
index c2f9737..15389be 100644
--- a/engines/xeen/spells.h
+++ b/engines/xeen/spells.h
@@ -32,6 +32,34 @@ class XeenEngine;
 
 #define MAX_SPELLS_PER_CLASS 40
 
+enum MagicSpell {
+	MS_AcidSpray = 0, MS_Awaken = 1, MS_BeastMaster = 2, MS_Bless = 3,
+	MS_Clairvoyance = 4,  MS_ColdRay = 5, MS_CreateFood = 6,
+	MS_CureDisease = 7, MS_CureParalysis = 8, MS_CurePoison = 9,
+	MS_CureWounds = 10, MS_DancingSword = 11, MS_DayOfProtection = 12,
+	MS_DayOfSorcery = 13, MS_DeadlySwarm = 14, MS_DetectMonster = 15,
+	MS_DivineIntervention = 16, MS_DragonSleep = 17, MS_ElementalStorm = 18,
+	MS_EnchantItem = 19, MS_EnergyBlast = 20, MS_Etheralize = 21,
+	MS_FantasticFreeze = 22, MS_FieryFlail = 23, MS_FingerOfDeath = 24,
+	MS_FireBall = 25, MS_FirstAid = 26, MS_FlyingFist = 27,
+	MS_FrostBite = 28, MS_GolemStopper = 29, MS_Heroism = 30,
+	MS_HolyBonus = 31, MS_HolyWord = 32, MS_Hynotize = 33,
+	MS_IdentifyMonster = 34, MS_Implosion = 35, MS_Incinerate = 36,
+	MS_Inferno = 37, MS_InsectSpray = 38, MS_ItemToGold = 39,
+	MS_Jump = 40, MS_Levitate = 41, MS_Light = 42, MS_LightningBolt = 43,
+	MS_LloydsBeacon = 44, MS_MagicArrow = 45, MS_MassDistortion = 46,
+	MS_MegaVolts = 47, MS_MoonRay = 48, MS_NaturesCure = 49, MS_Pain = 50,
+	MS_PoisonVolley = 51, MS_PowerCure = 52, MS_PowerShield = 53,
+	MS_PrismaticLight = 54, MS_ProtFromElements = 55, MS_RaiseDead = 56,
+	MS_RechargeItem = 57, MS_Resurrection = 58, MS_Revitalize = 59,
+	MS_Shrapmetal = 60, MS_Sleep = 61, MS_Sparks = 62, MS_StarBurst = 63,
+	MS_StoneToFlesh = 64, MS_SunRay = 65, MS_SuperShelter = 66,
+	MS_SuppressDisease = 67, MS_SuppressPoison = 68, MS_Teleport = 69,
+	MS_TimeDistortion = 70, MS_TownPortal = 71, MS_ToxicCloud = 72,
+	MS_TurnUndead = 73, MS_WalkOnWater = 74, MS_WizardEye = 75,
+	NO_SPELL = 76
+};
+
 class Spells {
 private:
 	XeenEngine *_vm;


Commit: 4bd128be7f799719cca87b5cac3966ee042ac769
    https://github.com/scummvm/scummvm/commit/4bd128be7f799719cca87b5cac3966ee042ac769
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-02-07T12:04:39-05:00

Commit Message:
XEEN: Finished doItemOptions

Changed paths:
    engines/xeen/dialogs_items.cpp
    engines/xeen/dialogs_items.h



diff --git a/engines/xeen/dialogs_items.cpp b/engines/xeen/dialogs_items.cpp
index 8466097..bbfbd95 100644
--- a/engines/xeen/dialogs_items.cpp
+++ b/engines/xeen/dialogs_items.cpp
@@ -552,7 +552,8 @@ int ItemsDialog::doItemOptions(Character &c, int actionIndex, int itemIndex, Ite
 	XeenItem *itemCategories[4] = { &c._weapons[0], &c._armor[0], &c._accessories[0], &c._misc[0] };
 	XeenItem *items = itemCategories[category];
 	if (!items[0]._id)
-		return false;
+		// Inventory is empty
+		return category == CATEGORY_MISC ? 0 : 2;
 
 	Window &w = screen._windows[11];
 	SpriteResource escSprites;
@@ -796,6 +797,11 @@ int ItemsDialog::doItemOptions(Character &c, int actionIndex, int itemIndex, Ite
 			break;
 		}
 
+		case ITEMMODE_TO_GOLD:
+			// Convert item in inventory to gold
+			itemToGold(c, itemIndex, category, mode);
+			return 2;
+
 		default:
 			break;
 		}
@@ -807,4 +813,26 @@ int ItemsDialog::doItemOptions(Character &c, int actionIndex, int itemIndex, Ite
 	return true;
 }
 
+void ItemsDialog::itemToGold(Character &c, int itemIndex, ItemCategory category,
+		ItemsMode mode) {
+	XeenItem &item = c._items[category][itemIndex];
+	Party &party = *_vm->_party;
+	SoundManager &sound = *_vm->_sound;
+
+	if (category == CATEGORY_WEAPON && item._id == 34) {
+		sound.playFX(21);
+		ErrorScroll::show(_vm, Common::String::format("\v012\t000\x03c%s",
+			SPELL_FAILED));
+	} else if (item._id != 0) {
+		// There is a valid item present
+		// Calculate cost of item and add it to the party's total
+		int cost = calcItemCost(&c, itemIndex, mode, 1, category);
+		party._gold += cost;
+
+		// Remove the item from the inventory
+		item.clear();
+		c._items[category].sort();
+	}
+}
+
 } // End of namespace Xeen
diff --git a/engines/xeen/dialogs_items.h b/engines/xeen/dialogs_items.h
index 42fe015..77b1540 100644
--- a/engines/xeen/dialogs_items.h
+++ b/engines/xeen/dialogs_items.h
@@ -60,6 +60,8 @@ private:
 
 	int doItemOptions(Character &c, int actionIndex, int itemIndex, 
 		ItemCategory category, ItemsMode mode);
+
+	void itemToGold(Character &c, int itemIndex, ItemCategory category, ItemsMode mode);
 public:
 	static Character *show(XeenEngine *vm, Character *c, ItemsMode mode);
 };


Commit: b633704847f12b87b0d4287ef18282b7165a64d6
    https://github.com/scummvm/scummvm/commit/b633704847f12b87b0d4287ef18282b7165a64d6
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-02-07T15:27:53-05:00

Commit Message:
XEEN: Implemented remainder of ItemsDialog

Changed paths:
  A engines/xeen/dialogs_quests.cpp
  A engines/xeen/dialogs_quests.h
    engines/xeen/character.h
    engines/xeen/dialogs_items.cpp
    engines/xeen/dialogs_items.h
    engines/xeen/module.mk
    engines/xeen/resources.cpp
    engines/xeen/resources.h



diff --git a/engines/xeen/character.h b/engines/xeen/character.h
index 6e6a772..af9e331 100644
--- a/engines/xeen/character.h
+++ b/engines/xeen/character.h
@@ -98,6 +98,8 @@ public:
 
 	void clear();
 
+	bool empty() const { return _id != 0; }
+
 	void synchronize(Common::Serializer &s);
 
 	ElementalCategory getElementalCategory() const;
diff --git a/engines/xeen/dialogs_items.cpp b/engines/xeen/dialogs_items.cpp
index bbfbd95..83e0dd2 100644
--- a/engines/xeen/dialogs_items.cpp
+++ b/engines/xeen/dialogs_items.cpp
@@ -22,6 +22,7 @@
 
 #include "xeen/dialogs_items.h"
 #include "xeen/dialogs_query.h"
+#include "xeen/dialogs_quests.h"
 #include "xeen/resources.h"
 #include "xeen/xeen.h"
 
@@ -47,7 +48,11 @@ Character *ItemsDialog::execute(Character *c, ItemsMode mode) {
 	int varA = mode == ITEMMODE_COMBAT ? 1 : 0;
 	if (varA != 0)
 		mode = ITEMMODE_CHAR_INFO;
-	int varE = mode == 1 ? 1 : 0;
+	bool updateStock = mode == ITEMMODE_BLACKSMITH;
+	int itemIndex = -1;
+	Common::StringArray lines;
+	int arr[40];
+	int actionIndex = -1;
 
 	events.setCursor(0);
 	loadButtons(mode, c);
@@ -55,9 +60,9 @@ Character *ItemsDialog::execute(Character *c, ItemsMode mode) {
 	screen._windows[29].open();
 	screen._windows[30].open();
 
-	bool redrawFlag = true;
+	enum { REDRAW_NONE, REDRAW_TEXT, REDRAW_FULL } redrawFlag = REDRAW_FULL;
 	while (!_vm->shouldQuit()) {
-		if (redrawFlag) {
+		if (redrawFlag == REDRAW_FULL) {
 			if ((mode != ITEMMODE_CHAR_INFO || category != CATEGORY_MISC) && mode != ITEMMODE_ENCHANT
 					&& mode != ITEMMODE_RECHARGE && mode != ITEMMODE_TO_GOLD) {
 				_buttons[8]._bounds.moveTo(148, _buttons[8]._bounds.top);
@@ -94,174 +99,177 @@ Character *ItemsDialog::execute(Character *c, ItemsMode mode) {
 
 			screen._windows[29].writeString(msg);
 			drawButtons(&screen);
-		}
 
-		Common::StringArray lines;
-		int arr[40];
-		Common::fill(&arr[0], &arr[40], 0);
-		int var2 = -1;
-	
-		if (mode == ITEMMODE_CHAR_INFO || category != 3) {
-			_iconSprites.draw(screen, 8, Common::Point(148, 109));
-		}
-		if (mode != ITEMMODE_ENCHANT && mode != ITEMMODE_RECHARGE && mode != ITEMMODE_TO_GOLD) {
-			_iconSprites.draw(screen, 10, Common::Point(182, 109));
-			_iconSprites.draw(screen, 12, Common::Point(216, 109));
-			_iconSprites.draw(screen, 14, Common::Point(250, 109));
+			Common::fill(&arr[0], &arr[40], 0);
+			itemIndex = -1;
 		}
 
-		switch (mode) {
-		case ITEMMODE_CHAR_INFO:
-			_iconSprites.draw(screen, 9, Common::Point(148, 109));
-			break;
-		case ITEMMODE_BLACKSMITH:
-			_iconSprites.draw(screen, 11, Common::Point(182, 109));
-			break;
-		case ITEMMODE_REPAIR:
-			_iconSprites.draw(screen, 15, Common::Point(250, 109));
-			break;
-		case ITEMMODE_IDENTIFY:
-			_iconSprites.draw(screen, 13, Common::Point(216, 109));
-			break;
-		default:
-			break;
-		}
+		if (redrawFlag == REDRAW_TEXT || redrawFlag == REDRAW_FULL) {
+			lines.clear();
 
-		for (int idx = 0; idx < 9; ++idx) {
-			_itemsDrawList[idx]._y = 10 + idx * 9;
+			if (mode == ITEMMODE_CHAR_INFO || category != 3) {
+				_iconSprites.draw(screen, 8, Common::Point(148, 109));
+			}
+			if (mode != ITEMMODE_ENCHANT && mode != ITEMMODE_RECHARGE && mode != ITEMMODE_TO_GOLD) {
+				_iconSprites.draw(screen, 10, Common::Point(182, 109));
+				_iconSprites.draw(screen, 12, Common::Point(216, 109));
+				_iconSprites.draw(screen, 14, Common::Point(250, 109));
+			}
 
-			switch (category) {
-			case CATEGORY_WEAPON: 
-			case CATEGORY_ARMOR:
-			case CATEGORY_ACCESSORY: {
-				XeenItem &i = (category == CATEGORY_WEAPON) ? c->_weapons[idx] :
-					((category == CATEGORY_ARMOR) ? c->_armor[idx] : c->_accessories[idx]);
-
-				if (i._id) {
-					if (mode == ITEMMODE_CHAR_INFO || mode == ITEMMODE_8
-							|| mode == ITEMMODE_ENCHANT || mode == ITEMMODE_RECHARGE) {
-						lines.push_back(Common::String::format(ITEMS_DIALOG_LINE1, 
-							arr[idx], idx + 1,
-							c->_items[category].getFullDescription(idx, arr[idx])));
+			switch (mode) {
+			case ITEMMODE_CHAR_INFO:
+				_iconSprites.draw(screen, 9, Common::Point(148, 109));
+				break;
+			case ITEMMODE_BLACKSMITH:
+				_iconSprites.draw(screen, 11, Common::Point(182, 109));
+				break;
+			case ITEMMODE_REPAIR:
+				_iconSprites.draw(screen, 15, Common::Point(250, 109));
+				break;
+			case ITEMMODE_IDENTIFY:
+				_iconSprites.draw(screen, 13, Common::Point(216, 109));
+				break;
+			default:
+				break;
+			}
+
+			for (int idx = 0; idx < 9; ++idx) {
+				_itemsDrawList[idx]._y = 10 + idx * 9;
+
+				switch (category) {
+				case CATEGORY_WEAPON: 
+				case CATEGORY_ARMOR:
+				case CATEGORY_ACCESSORY: {
+					XeenItem &i = (category == CATEGORY_WEAPON) ? c->_weapons[idx] :
+						((category == CATEGORY_ARMOR) ? c->_armor[idx] : c->_accessories[idx]);
+
+					if (i._id) {
+						if (mode == ITEMMODE_CHAR_INFO || mode == ITEMMODE_8
+								|| mode == ITEMMODE_ENCHANT || mode == ITEMMODE_RECHARGE) {
+							lines.push_back(Common::String::format(ITEMS_DIALOG_LINE1, 
+								arr[idx], idx + 1,
+								c->_items[category].getFullDescription(idx, arr[idx])));
+						} else {
+							lines.push_back(Common::String::format(ITEMS_DIALOG_LINE2,
+								arr[idx], idx + 1,
+								c->_items[category].getFullDescription(idx, arr[idx]),
+								calcItemCost(c, idx, mode,
+									mode == ITEMMODE_TO_GOLD ? 1 : startingChar->_skills[MERCHANT],
+									category)
+							));
+						}
+
+						DrawStruct &ds = _itemsDrawList[idx];
+						ds._sprites = &_equipSprites;
+						if (c->_weapons.passRestrictions(i._id, true))
+							ds._frame = i._frame;
+						else
+							ds._frame = 14;
+					} else if (_itemsDrawList[idx]._sprites == nullptr) {
+						lines.push_back(NO_ITEMS_AVAILABLE);
+					}
+					break;
+				}
+
+				case CATEGORY_MISC: {
+					XeenItem &i = c->_misc[idx];
+					_itemsDrawList[idx]._sprites = nullptr;
+
+					if (i._material == 0) {
+						// No item
+						if (idx == 0) {
+							lines.push_back(NO_ITEMS_AVAILABLE);
+						}
 					} else {
+						ItemsMode tempMode = mode;
+						int skill = startingChar->_skills[MERCHANT];
+
+						if (mode == ITEMMODE_CHAR_INFO || mode == ITEMMODE_8
+								|| mode == ITEMMODE_ENCHANT || mode == ITEMMODE_RECHARGE) {
+							tempMode = ITEMMODE_ENCHANT;
+						} else if (mode == ITEMMODE_TO_GOLD) {
+							skill = 1;
+						}
+
 						lines.push_back(Common::String::format(ITEMS_DIALOG_LINE2,
 							arr[idx], idx + 1,
 							c->_items[category].getFullDescription(idx, arr[idx]),
-							calcItemCost(c, idx, mode,
-								mode == ITEMMODE_TO_GOLD ? 1 : startingChar->_skills[MERCHANT],
-								category)
+							calcItemCost(c, idx, tempMode, skill, category)
 						));
 					}
+					break;
+				}
 
-					DrawStruct &ds = _itemsDrawList[idx];
-					ds._sprites = &_equipSprites;
-					if (c->_weapons.passRestrictions(i._id, true))
-						ds._frame = i._frame;
-					else
-						ds._frame = 14;
-				} else if (_itemsDrawList[idx]._sprites == nullptr) {
-					lines.push_back(NO_ITEMS_AVAILABLE);
+				default:
+					break;
 				}
-				break;
 			}
+			while (lines.size() < INV_ITEMS_TOTAL)
+				lines.push_back("");
 
-			case CATEGORY_MISC: {
-				XeenItem &i = c->_misc[idx];
-				_itemsDrawList[idx]._sprites = nullptr;
+			// Draw out overall text and the list of items
+			switch (mode) {
+			case ITEMMODE_CHAR_INFO:
+			case ITEMMODE_8:
+				screen._windows[30].writeString(Common::String::format(X_FOR_THE_Y,
+					category == CATEGORY_MISC ? "\x3l" : "\x3c",
+					CATEGORY_NAMES[category], c->_name.c_str(), CLASS_NAMES[c->_class],
+					category == CATEGORY_MISC ? FMT_CHARGES : " ",
+					lines[0].c_str(), lines[1].c_str(), lines[2].c_str(), lines[3].c_str(),
+					lines[4].c_str(), lines[5].c_str(), lines[6].c_str(), lines[7].c_str(),
+					lines[8].c_str()
+				));
 
-				if (i._material == 0) {
-					// No item
-					if (idx == 0) {
-						lines.push_back(NO_ITEMS_AVAILABLE);
-					}
-				} else {
-					ItemsMode tempMode = mode;
-					int skill = startingChar->_skills[MERCHANT];
-
-					if (mode == ITEMMODE_CHAR_INFO || mode == ITEMMODE_8
-							|| mode == ITEMMODE_ENCHANT || mode == ITEMMODE_RECHARGE) {
-						tempMode = ITEMMODE_ENCHANT;
-					} else if (mode == ITEMMODE_TO_GOLD) {
-						skill = 1;
-					}
+			case ITEMMODE_BLACKSMITH: {
+				// Original uses var in this block that's never set?!
+				const int v1 = 0;
+				screen._windows[30].writeString(Common::String::format(AVAILABLE_GOLD_COST,
+					CATEGORY_NAMES[category], 
+					v1 ? "" : "s", party._gold,
+					lines[0].c_str(), lines[1].c_str(), lines[2].c_str(), lines[3].c_str(),
+					lines[4].c_str(), lines[5].c_str(), lines[6].c_str(), lines[7].c_str(),
+					lines[8].c_str()
+				));
+				break;
+			}
+
+			case ITEMMODE_2:
+			case ITEMMODE_RECHARGE:
+			case ITEMMODE_ENCHANT:
+			case ITEMMODE_REPAIR:
+			case ITEMMODE_IDENTIFY:
+			case ITEMMODE_TO_GOLD:
+				screen._windows[30].writeString(Common::String::format(X_FOR_Y,
+					CATEGORY_NAMES[category], startingChar->_name.c_str(),
+					(mode == ITEMMODE_RECHARGE || mode == ITEMMODE_ENCHANT) ? CHARGES : COST,
+					lines[0].c_str(), lines[1].c_str(), lines[2].c_str(), lines[3].c_str(),
+					lines[4].c_str(), lines[5].c_str(), lines[6].c_str(), lines[7].c_str(),
+					lines[8].c_str()
+				));
+				break;
 
-					lines.push_back(Common::String::format(ITEMS_DIALOG_LINE2,
-						arr[idx], idx + 1,
-						c->_items[category].getFullDescription(idx, arr[idx]),
-						calcItemCost(c, idx, tempMode, skill, category)
+			case ITEMMODE_3:
+			case ITEMMODE_5:
+				screen._windows[30].writeString(Common::String::format(X_FOR_Y_GOLD,
+					CATEGORY_NAMES[category], c->_name.c_str(), party._gold, CHARGES,
+					lines[0].c_str(), lines[1].c_str(), lines[2].c_str(), lines[3].c_str(),
+					lines[4].c_str(), lines[5].c_str(), lines[6].c_str(), lines[7].c_str(),
+					lines[8].c_str()
 					));
-				}
 				break;
-			}
 
 			default:
 				break;
 			}
-		}
-		while (lines.size() < INV_ITEMS_TOTAL)
-			lines.push_back("");
-
-		// Draw out overall text and the list of items
-		switch (mode) {
-		case ITEMMODE_CHAR_INFO:
-		case ITEMMODE_8:
-			screen._windows[30].writeString(Common::String::format(X_FOR_THE_Y,
-				category == CATEGORY_MISC ? "\x3l" : "\x3c",
-				CATEGORY_NAMES[category], c->_name.c_str(), CLASS_NAMES[c->_class],
-				category == CATEGORY_MISC ? FMT_CHARGES : " ",
-				lines[0].c_str(), lines[1].c_str(), lines[2].c_str(), lines[3].c_str(),
-				lines[4].c_str(), lines[5].c_str(), lines[6].c_str(), lines[7].c_str(),
-				lines[8].c_str()
-			));
-
-		case ITEMMODE_BLACKSMITH: {
-			// Original uses var in this block that's never set?!
-			const int v1 = 0;
-			screen._windows[30].writeString(Common::String::format(AVAILABLE_GOLD_COST,
-				CATEGORY_NAMES[category], 
-				v1 ? "" : "s", party._gold,
-				lines[0].c_str(), lines[1].c_str(), lines[2].c_str(), lines[3].c_str(),
-				lines[4].c_str(), lines[5].c_str(), lines[6].c_str(), lines[7].c_str(),
-				lines[8].c_str()
-			));
-			break;
-		}
-
-		case ITEMMODE_2:
-		case ITEMMODE_RECHARGE:
-		case ITEMMODE_ENCHANT:
-		case ITEMMODE_REPAIR:
-		case ITEMMODE_IDENTIFY:
-		case ITEMMODE_TO_GOLD:
-			screen._windows[30].writeString(Common::String::format(X_FOR_Y,
-				CATEGORY_NAMES[category], startingChar->_name.c_str(),
-				(mode == ITEMMODE_RECHARGE || mode == ITEMMODE_ENCHANT) ? CHARGES : COST,
-				lines[0].c_str(), lines[1].c_str(), lines[2].c_str(), lines[3].c_str(),
-				lines[4].c_str(), lines[5].c_str(), lines[6].c_str(), lines[7].c_str(),
-				lines[8].c_str()
-			));
-			break;
-
-		case ITEMMODE_3:
-		case ITEMMODE_5:
-			screen._windows[30].writeString(Common::String::format(X_FOR_Y_GOLD,
-				CATEGORY_NAMES[category], c->_name.c_str(), party._gold, CHARGES,
-				lines[0].c_str(), lines[1].c_str(), lines[2].c_str(), lines[3].c_str(),
-				lines[4].c_str(), lines[5].c_str(), lines[6].c_str(), lines[7].c_str(),
-				lines[8].c_str()
-				));
-			break;
 
-		default:
-			break;
+			// Draw the glyphs for the items
+			screen._windows[0].drawList(_itemsDrawList, INV_ITEMS_TOTAL);
+			screen._windows[0].update();
 		}
 
-		// Draw the glyphs for the items
-		screen._windows[0].drawList(_itemsDrawList, INV_ITEMS_TOTAL);
-		screen._windows[0].update();
+		redrawFlag = REDRAW_NONE;
 
-		if (var2 != -1) {
-			int actionIndex = -1;
+		if (itemIndex != -1) {
 			switch (mode) {
 			case ITEMMODE_BLACKSMITH:
 				actionIndex = 0;
@@ -278,15 +286,229 @@ Character *ItemsDialog::execute(Character *c, ItemsMode mode) {
 			default:
 				break;
 			}
-
-			if (actionIndex >= 0) {
-				doItemOptions(*c, actionIndex, var2, category, mode);
+		} 
+		
+		// If it's time to do an item action, take care of it
+		if (actionIndex >= 0) {
+			int result = doItemOptions(*c, actionIndex, itemIndex, category, mode);
+			if (result == 1) {
+				// Finish dialog with no selected character
+				c = nullptr;
+				break;
+			} else if (result == 2) {
+				// Close dialogs and finish dialog with original starting character
+				screen._windows[30].close();
+				screen._windows[29].close();
+				c = startingChar;
+				break;
 			}
+
+			// Otherwise, result and continue showing dialog
+			actionIndex = -1;
+		}
+		
+		// Wait for a selection
+		_buttonValue = 0;
+		while (!_vm->shouldQuit() && !_buttonValue) {
+			events.pollEventsAndWait();
+			checkEvents(_vm);
 		}
+		if (_vm->shouldQuit())
+			return nullptr;
+
+		// Handle escaping out of dialog
+		if (_buttonValue == Common::KEYCODE_ESCAPE) {
+			if (mode == ITEMMODE_8)
+				continue;
+			break;
+		}
+
+		// Handle other selections
+		switch (_buttonValue) {
+		case Common::KEYCODE_F1:
+		case Common::KEYCODE_F2:
+		case Common::KEYCODE_F3:
+		case Common::KEYCODE_F4:
+		case Common::KEYCODE_F5:
+		case Common::KEYCODE_F6:
+			if (!varA && mode != ITEMMODE_3 && mode != ITEMMODE_ENCHANT 
+					&& mode != ITEMMODE_RECHARGE && mode != ITEMMODE_TO_GOLD
+					&& party._mazeId != 0) {
+				_buttonValue -= Common::KEYCODE_F1;
+				
+				if (_buttonValue < (int)(_vm->_mode == MODE_InCombat ?
+						party._combatParty.size() : party._activeParty.size())) {
+					// Character number is valid
+					redrawFlag = REDRAW_TEXT;
+					Character *newChar = _vm->_mode == MODE_InCombat ?
+						party._combatParty[_buttonValue] : &party._activeParty[_buttonValue];
+
+					if (mode == ITEMMODE_BLACKSMITH) {
+						_oldCharacter = newChar;
+						startingChar = newChar;
+						c = &_itemsCharacter;
+					} else if (mode != ITEMMODE_2 && mode != ITEMMODE_REPAIR
+							&& mode != ITEMMODE_IDENTIFY && itemIndex != -1) {
+						InventoryItems &destItems = newChar->_items[category];
+						XeenItem &destItem = destItems[INV_ITEMS_TOTAL - 1];
+						InventoryItems &srcItems = c->_items[category];
+						XeenItem &srcItem = srcItems[itemIndex];
+
+						if (srcItem._bonusFlags & ITEMFLAG_CURSED)
+							ErrorScroll::show(_vm, CANNOT_REMOVE_CURSED_ITEM);
+						else if (destItems[INV_ITEMS_TOTAL - 1]._id)
+							ErrorScroll::show(_vm, Common::String::format(
+							CATEGORY_BACKPACK_IS_FULL[category], c->_name.c_str()));
+						else {
+							destItem = srcItem;
+							srcItem.clear();
+							destItem._frame = 0;
+
+							srcItems.sort();
+							destItems.sort();
+						}
+
+						continue;
+					}
+
+					c = newChar;
+					startingChar = newChar;
+					intf.highlightChar(_buttonValue);
+				}
+			}
+			break;
+
+		case Common::KEYCODE_1:
+		case Common::KEYCODE_2:
+		case Common::KEYCODE_3:
+		case Common::KEYCODE_4:
+		case Common::KEYCODE_5:
+		case Common::KEYCODE_6:
+		case Common::KEYCODE_7:
+		case Common::KEYCODE_8:
+		case Common::KEYCODE_9:
+			// Select an item
+			if (mode == ITEMMODE_3)
+				break;
+				
+			_buttonValue -= Common::KEYCODE_1;
+			if (_buttonValue != itemIndex) {
+				// Check whether the new selection has an associated item
+				if (!c->_items[category][_buttonValue].empty()) {
+					itemIndex = _buttonValue;
+					Common::fill(&arr[0], &arr[40], 0);
+					arr[itemIndex] = 15;
+				}
+
+				redrawFlag = REDRAW_TEXT;
+			}
+			break;
+
+		case Common::KEYCODE_a:
+			// Armor category
+			category = CATEGORY_ARMOR;
+			redrawFlag = REDRAW_FULL;
+			break;
 
-		// TODO
+		case Common::KEYCODE_b:
+			// Buy
+			if (mode != ITEMMODE_CHAR_INFO && mode != ITEMMODE_RECHARGE &&
+					mode != ITEMMODE_ENCHANT && mode != ITEMMODE_TO_GOLD) {
+				mode = ITEMMODE_BLACKSMITH;
+				c = &_itemsCharacter;
+				redrawFlag = REDRAW_FULL;
+			}
+			break;
+
+		case Common::KEYCODE_c:
+			// Accessories category
+			category = CATEGORY_ACCESSORY;
+			redrawFlag = REDRAW_FULL;
+			break;
+
+		case Common::KEYCODE_d:
+			if (mode == ITEMMODE_CHAR_INFO)
+				actionIndex = 3;
+			break;
+			
+		case Common::KEYCODE_e:
+			if (mode == ITEMMODE_CHAR_INFO || mode == ITEMMODE_ENCHANT ||
+					mode == ITEMMODE_TO_GOLD) {
+				if (category != CATEGORY_MISC) {
+					actionIndex = mode == ITEMMODE_ENCHANT ? 4 : 0;
+				}
+			}
+			break;
+
+		case Common::KEYCODE_f:
+			if (mode != ITEMMODE_CHAR_INFO && mode != ITEMMODE_RECHARGE &&
+					mode != ITEMMODE_ENCHANT && mode != ITEMMODE_TO_GOLD) {
+				mode = ITEMMODE_REPAIR;
+				c = startingChar;
+				redrawFlag = REDRAW_TEXT;
+			}	
+			break;
+
+		case Common::KEYCODE_g:
+			if (mode == ITEMMODE_TO_GOLD)
+				actionIndex = 6;
+			break;
+
+		case Common::KEYCODE_i:
+			if (mode != ITEMMODE_CHAR_INFO && mode != ITEMMODE_RECHARGE &&
+					mode != ITEMMODE_ENCHANT && mode != ITEMMODE_TO_GOLD) {
+				mode = ITEMMODE_IDENTIFY;
+				c = startingChar;
+				redrawFlag = REDRAW_TEXT;
+			}
+			break;
+
+		case Common::KEYCODE_n:
+			// Misc category
+			category = CATEGORY_MISC;
+			redrawFlag = REDRAW_TEXT;
+			break;
+
+		case Common::KEYCODE_q:
+			if (mode == ITEMMODE_CHAR_INFO) {
+				Quests::show(_vm);
+				redrawFlag = REDRAW_TEXT;
+			}
+			break;
+
+		case Common::KEYCODE_r:
+			if (mode == ITEMMODE_CHAR_INFO)
+				actionIndex = 1;
+			else if (mode == ITEMMODE_RECHARGE)
+				actionIndex = 5;
+			break;
+
+		case Common::KEYCODE_s:
+			if (mode != ITEMMODE_CHAR_INFO && mode != ITEMMODE_RECHARGE &&
+					mode != ITEMMODE_ENCHANT && mode != ITEMMODE_TO_GOLD) {
+				mode = ITEMMODE_2;
+				c = startingChar;
+				redrawFlag = REDRAW_TEXT;
+			}
+			break;
+
+		case Common::KEYCODE_u:
+			if (mode == ITEMMODE_CHAR_INFO && category == CATEGORY_MISC)
+				actionIndex = 2;
+			break;
+
+		case Common::KEYCODE_w:
+			// Weapons category
+			category = CATEGORY_WEAPON;
+			redrawFlag = REDRAW_TEXT;
+			break;
+		}
 	}
 
+	intf.charIconsPrint(true);
+	if (updateStock)
+		charData2BlackData();
+
 	return c;
 }
 
@@ -379,6 +601,27 @@ void ItemsDialog::blackData2CharData() {
 }
 
 /**
+* Saves the inventory from the temporary _itemsCharacter character back into the
+* blacksmith storage, so changes in blacksmith inventory remain persistent
+*/
+void ItemsDialog::charData2BlackData() {
+	Party &party = *_vm->_party;
+	bool isDarkCc = _vm->_files->_isDarkCc;
+	int slotIndex = 0;
+	while (party._mazeId != (int)BLACKSMITH_MAP_IDS[isDarkCc][slotIndex] && slotIndex < 4)
+		++slotIndex;
+	if (slotIndex == 4)
+		slotIndex = 0;
+
+	for (int idx = 0; idx < INV_ITEMS_TOTAL; ++idx) {
+		party._blacksmithWeapons[isDarkCc][idx] = _itemsCharacter._weapons[idx];
+		party._blacksmithArmor[isDarkCc][idx] = _itemsCharacter._armor[idx];
+		party._blacksmithAccessories[isDarkCc][idx] = _itemsCharacter._accessories[idx];
+		party._blacksmithMisc[isDarkCc][idx] = _itemsCharacter._misc[idx];
+	}
+}
+
+/**
  * Sets the equipment icon to use for each item for display
  */
 void ItemsDialog::setEquipmentIcons() {
diff --git a/engines/xeen/dialogs_items.h b/engines/xeen/dialogs_items.h
index 77b1540..bc995c5 100644
--- a/engines/xeen/dialogs_items.h
+++ b/engines/xeen/dialogs_items.h
@@ -53,6 +53,8 @@ private:
 
 	void blackData2CharData();
 
+	void charData2BlackData();
+
 	void setEquipmentIcons();
 
 	int calcItemCost(Character *c, int itemIndex, ItemsMode mode, int skillLevel, 
diff --git a/engines/xeen/dialogs_quests.cpp b/engines/xeen/dialogs_quests.cpp
new file mode 100644
index 0000000..2765719
--- /dev/null
+++ b/engines/xeen/dialogs_quests.cpp
@@ -0,0 +1,40 @@
+/* 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_quests.h"
+#include "xeen/events.h"
+#include "xeen/xeen.h"
+
+namespace Xeen {
+
+void Quests::show(XeenEngine *vm) {
+	Quests *dlg = new Quests(vm);
+	dlg->execute();
+	delete dlg;
+}
+
+void Quests::execute() {
+	// TODO
+}
+
+} // End of namespace Xeen
diff --git a/engines/xeen/dialogs_quests.h b/engines/xeen/dialogs_quests.h
new file mode 100644
index 0000000..fb39d3a
--- /dev/null
+++ b/engines/xeen/dialogs_quests.h
@@ -0,0 +1,43 @@
+/* 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_QUESTS_H
+#define XEEN_DIALOGS_QUESTS_H
+
+#include "xeen/dialogs.h"
+
+namespace Xeen {
+
+class Quests : public ButtonContainer {
+private:
+	XeenEngine *_vm;
+
+	Quests(XeenEngine *vm) : ButtonContainer(), _vm(vm) {}
+
+	void execute();
+public:
+	static void show(XeenEngine *vm);
+};
+
+} // End of namespace Xeen
+
+#endif /* XEEN_DIALOGS_QUESTS_H */
diff --git a/engines/xeen/module.mk b/engines/xeen/module.mk
index 6a36f91..8c526b4 100644
--- a/engines/xeen/module.mk
+++ b/engines/xeen/module.mk
@@ -19,6 +19,7 @@ MODULE_OBJS := \
 	dialogs_input.o \
 	dialogs_items.o \
 	dialogs_query.o \
+	dialogs_quests.o \
 	dialogs_quick_ref.o \
 	dialogs_spells.o \
 	dialogs_whowill.o \
diff --git a/engines/xeen/resources.cpp b/engines/xeen/resources.cpp
index 55060c8..991c430 100644
--- a/engines/xeen/resources.cpp
+++ b/engines/xeen/resources.cpp
@@ -1240,6 +1240,13 @@ const char *const PERMANENTLY_DISCARD = "\v000\t000\x03lPermanently discard %s\f
 
 const char *const BACKPACK_IS_FULL = "\v005\x03c\fd%s's backpack is full.";
 
+const char *const CATEGORY_BACKPACK_IS_FULL[4] = {
+	"\v010\t000\x3""c%s's weapons backpack is full.",
+	"\v010\t000\x3""c%s's armor backpack is full.",
+	"\v010\t000\x3""c%s's accessories backpack is full.",
+	"\v010\t000\x3""c%s's miscellaneous backpack is full."
+};
+
 const char *const BUY_X_FOR_Y_GOLD = "\x3l\v000\t000\fdBuy %s\fd for %lu gold?";
 
 const char *const SELL_X_FOR_Y_GOLD = "\x3l\v000\t000\fdSell %s\fd for %lu gold?";
diff --git a/engines/xeen/resources.h b/engines/xeen/resources.h
index cab2af7..4c79a1e 100644
--- a/engines/xeen/resources.h
+++ b/engines/xeen/resources.h
@@ -443,6 +443,8 @@ extern const char *const PERMANENTLY_DISCARD;
 
 extern const char *const BACKPACK_IS_FULL;
 
+extern const char *const CATEGORY_BACKPACK_IS_FULL[4];
+
 extern const char *const BUY_X_FOR_Y_GOLD;
 
 extern const char *const SELL_X_FOR_Y_GOLD;


Commit: 90db7872f14c67f990c74f6b2d971f479dc87941
    https://github.com/scummvm/scummvm/commit/90db7872f14c67f990c74f6b2d971f479dc87941
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-02-07T18:02:03-05:00

Commit Message:
XEEN: Implement Quests dialog

Changed paths:
    engines/xeen/dialogs_quests.cpp
    engines/xeen/dialogs_quests.h
    engines/xeen/interface.cpp
    engines/xeen/party.h
    engines/xeen/resources.cpp
    engines/xeen/resources.h



diff --git a/engines/xeen/dialogs_quests.cpp b/engines/xeen/dialogs_quests.cpp
index 2765719..1725594 100644
--- a/engines/xeen/dialogs_quests.cpp
+++ b/engines/xeen/dialogs_quests.cpp
@@ -23,10 +23,13 @@
 #include "common/scummsys.h"
 #include "xeen/dialogs_quests.h"
 #include "xeen/events.h"
+#include "xeen/party.h"
 #include "xeen/xeen.h"
 
 namespace Xeen {
 
+#define MAX_DIALOG_LINES 128
+
 void Quests::show(XeenEngine *vm) {
 	Quests *dlg = new Quests(vm);
 	dlg->execute();
@@ -34,7 +37,212 @@ void Quests::show(XeenEngine *vm) {
 }
 
 void Quests::execute() {
-	// TODO
+	EventsManager &events = *_vm->_events;
+	Party &party = *_vm->_party;
+	Screen &screen = *_vm->_screen;
+	bool isDarkCc = _vm->_files->_isDarkCc;
+	int count = 0;
+	bool headerShown = false;
+	int topRow = 0;
+
+	addButtons();
+	loadQuestNotes();
+
+	enum { QUEST_ITEMS, CURRENT_QUESTS, AUTO_NOTES } mode = QUEST_ITEMS;
+	bool windowFlag;
+	if (screen._windows[29]._enabled) {
+		windowFlag = false;
+	} else {
+		screen._windows[29].open();
+		screen._windows[30].open();
+		windowFlag = true;
+	}
+
+	screen._windows[29].writeString(QUESTS_DIALOG_TEXT);
+	drawButtons(&screen);
+
+	while (!_vm->shouldQuit()) {
+		Common::String lines[MAX_DIALOG_LINES];
+
+		switch (mode) {
+		case QUEST_ITEMS:
+			for (int idx = 0; idx < TOTAL_QUEST_ITEMS; ++idx)
+				lines[idx] = "\b \b*";
+
+			count = 0;
+			headerShown = false;
+			for (int idx = 0; idx < TOTAL_QUEST_ITEMS; ++idx) {
+				if (party._questItems[idx]) {
+					if (!count && !headerShown && idx < 35) {
+						lines[count++] = CLOUDS_OF_XEEN_LINE;
+					}
+					if (idx >= 35 && !headerShown) {
+						lines[count++] = DARKSIDE_OF_XEEN_LINE;
+						headerShown = true;
+					}
+
+					switch (idx) {
+					case 17:
+					case 26:
+					case 79:
+					case 80:
+					case 81:
+					case 82:
+					case 83:
+					case 84:
+						lines[count++] = Common::String::format("%d %s%c",
+							party._questItems[idx], QUEST_ITEM_NAMES[idx],
+							party._questItems[idx] == 1 ? ' ' : 's');
+						break;
+					default:
+						lines[count++] = QUEST_ITEM_NAMES[idx];
+						break;
+					}
+				}
+			}
+
+			if (count == 0) {
+				screen._windows[30].writeString(NO_QUEST_ITEMS);
+			} else {
+				screen._windows[30].writeString(Common::String::format(QUEST_ITEMS_DATA,
+					lines[topRow].c_str(), lines[topRow + 1].c_str(),
+					lines[topRow + 2].c_str(), lines[topRow + 3].c_str(),
+					lines[topRow + 4].c_str(), lines[topRow + 5].c_str(),
+					lines[topRow + 6].c_str(), lines[topRow + 7].c_str(),
+					lines[topRow + 8].c_str()
+				));
+			}
+			break;
+
+		case CURRENT_QUESTS:
+			for (int idx = 0; idx < TOTAL_QUEST_ITEMS; ++idx)
+				lines[idx] = "";
+
+			count = 0;
+			headerShown = false;
+			for (int idx = 0; idx < TOTAL_QUEST_FLAGS; ++idx) {
+				if (party._quests[idx]) {
+					if (!count && !headerShown && idx < 29) {
+						lines[count++] = CLOUDS_OF_XEEN_LINE;
+					}
+					if (idx > 28 && !headerShown) {
+						lines[count++] = DARKSIDE_OF_XEEN_LINE;
+						headerShown = true;
+					}
+
+					lines[count++] = _questNotes[idx];
+				}
+			}
+
+			if (count == 0)
+				lines[1] = NO_CURRENT_QUESTS;
+
+			screen._windows[30].writeString(Common::String::format(CURRENT_QUESTS_DATA,
+				lines[topRow].c_str(), lines[topRow + 1].c_str(), lines[topRow + 2].c_str()));
+			break;
+
+		case AUTO_NOTES:
+			for (int idx = 0; idx < MAX_DIALOG_LINES; ++idx)
+				lines[idx] = "";
+
+			count = 0;
+			headerShown = false;
+			for (int idx = 0; idx < MAX_DIALOG_LINES; ++idx) {
+				if (party._worldFlags[idx]) {
+					if (!count && !headerShown && idx < 72) {
+						lines[count++] = CLOUDS_OF_XEEN_LINE;
+					}
+					if (idx >= 72 && !headerShown) {
+						lines[count++] = DARKSIDE_OF_XEEN_LINE;
+						headerShown = true;
+					}
+
+					lines[count++] = _questNotes[idx + 56];
+				}
+			}
+
+			if (count == 0)
+				lines[1] = NO_AUTO_NOTES;
+
+			screen._windows[30].writeString(Common::String::format(AUTO_NOTES_DATA,
+				lines[topRow].c_str(), lines[topRow + 1].c_str(),
+				lines[topRow + 2].c_str(), lines[topRow + 3].c_str(),
+				lines[topRow + 4].c_str(), lines[topRow + 5].c_str(),
+				lines[topRow + 6].c_str(), lines[topRow + 7].c_str(),
+				lines[topRow + 8].c_str()
+			));
+			break;
+		}
+
+		screen._windows[30].writeString("\v000\t000");
+		screen._windows[24].update();
+
+		// Key handling
+		_buttonValue = 0;
+		while (!_vm->shouldQuit() && !_buttonValue) {
+			events.pollEventsAndWait();
+			checkEvents(_vm);
+		}
+
+		if (_buttonValue == Common::KEYCODE_ESCAPE)
+			break;
+
+		switch (_buttonValue) {
+		case Common::KEYCODE_a:
+			mode = AUTO_NOTES;
+			break;
+		case Common::KEYCODE_i:
+			mode = QUEST_ITEMS;
+			break;
+		case Common::KEYCODE_q:
+			mode = CURRENT_QUESTS;
+			break;
+		case Common::KEYCODE_HOME:
+			topRow = 0;
+			break;
+		case Common::KEYCODE_END:
+			topRow = count - 1;
+			break;
+		case Common::KEYCODE_PAGEUP:
+			topRow = MAX(topRow - 3, 0);
+			break;
+		case Common::KEYCODE_PAGEDOWN:
+			topRow = CLIP(topRow + 3, 0, count - 1);
+			break;
+		case Common::KEYCODE_UP:
+		case Common::KEYCODE_KP8:
+			topRow = MAX(topRow - 1, 0);
+			break;
+		case Common::KEYCODE_DOWN:
+		case Common::KEYCODE_KP2:
+			topRow = CLIP(topRow + 1, 0, count - 1);
+			break;
+		default:
+			break;
+		}
+	}
+
+	if (windowFlag) {
+		screen._windows[30].close();
+		screen._windows[29].close();
+	}
+}
+
+void Quests::addButtons() {
+	_iconSprites.load("quest.icn");
+	addButton(Common::Rect(12, 109, 36, 129), Common::KEYCODE_i, &_iconSprites);
+	addButton(Common::Rect(80, 109, 104, 129), Common::KEYCODE_q, &_iconSprites);
+	addButton(Common::Rect(148, 109, 172, 129), Common::KEYCODE_a, &_iconSprites);
+	addButton(Common::Rect(216, 109, 240, 129), Common::KEYCODE_i, &_iconSprites);
+	addButton(Common::Rect(250, 109, 274, 129), Common::KEYCODE_UP, &_iconSprites);
+	addButton(Common::Rect(284, 109, 308, 129), Common::KEYCODE_DOWN, &_iconSprites);
+}
+
+void Quests::loadQuestNotes() {
+	File f("qnotes.bin");
+	while (f.pos() < f.size())
+		_questNotes.push_back(f.readString());
+	f.close();
 }
 
 } // End of namespace Xeen
diff --git a/engines/xeen/dialogs_quests.h b/engines/xeen/dialogs_quests.h
index fb39d3a..234accd 100644
--- a/engines/xeen/dialogs_quests.h
+++ b/engines/xeen/dialogs_quests.h
@@ -23,6 +23,7 @@
 #ifndef XEEN_DIALOGS_QUESTS_H
 #define XEEN_DIALOGS_QUESTS_H
 
+#include "common/str-array.h"
 #include "xeen/dialogs.h"
 
 namespace Xeen {
@@ -30,10 +31,16 @@ namespace Xeen {
 class Quests : public ButtonContainer {
 private:
 	XeenEngine *_vm;
+	SpriteResource _iconSprites;
+	Common::StringArray _questNotes;
 
 	Quests(XeenEngine *vm) : ButtonContainer(), _vm(vm) {}
 
 	void execute();
+
+	void addButtons();
+
+	void loadQuestNotes();
 public:
 	static void show(XeenEngine *vm);
 };
diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp
index 520cad5..34c7b54 100644
--- a/engines/xeen/interface.cpp
+++ b/engines/xeen/interface.cpp
@@ -25,6 +25,7 @@
 #include "xeen/dialogs_error.h"
 #include "xeen/dialogs_automap.h"
 #include "xeen/dialogs_info.h"
+#include "xeen/dialogs_quests.h"
 #include "xeen/dialogs_quick_ref.h"
 #include "xeen/resources.h"
 #include "xeen/xeen.h"
@@ -710,6 +711,11 @@ void Interface::perform() {
 		QuickReferenceDialog::show(_vm);
 		break;
 
+	case Common::KEYCODE_v:
+		// Show the quests dialog
+		Quests::show(_vm);
+		break;
+
 	default:
 		break;
 	}
diff --git a/engines/xeen/party.h b/engines/xeen/party.h
index ec7a8b9..b1ca067 100644
--- a/engines/xeen/party.h
+++ b/engines/xeen/party.h
@@ -45,6 +45,8 @@ enum Difficulty { ADVENTURER = 0, WARRIOR = 1 };
 #define XEEN_TOTAL_CHARACTERS 24
 #define MAX_ACTIVE_PARTY 6
 #define TOTAL_STATS 7
+#define TOTAL_QUEST_ITEMS 85
+#define TOTAL_QUEST_FLAGS 56
 
 class Roster: public Common::Array<Character> {
 public:
@@ -107,7 +109,7 @@ public:
 	bool _gameFlags[512];
 	bool _worldFlags[128];
 	bool _quests[64];
-	int _questItems[85];
+	int _questItems[TOTAL_QUEST_ITEMS];
 	bool _characterFlags[30][24];
 public:
 	// Other party related runtime data
diff --git a/engines/xeen/resources.cpp b/engines/xeen/resources.cpp
index 991c430..eeea54c 100644
--- a/engines/xeen/resources.cpp
+++ b/engines/xeen/resources.cpp
@@ -1144,6 +1144,94 @@ const char *const EFFECTIVENESS_NAMES[7] = {
 	nullptr, "Dragons", "Undead", "Golems", "Bugs", "Monsters", "Beasts"
 };
 
+const char *const QUEST_ITEM_NAMES[85] = {
+	"Deed to New Castle",
+	"Crystal Key to Witch Tower",
+	"Skeleton Key to Darzog's Tower",
+	"Enchanted Key to Tower of High Magic",
+	"Jeweled Amulet of the Northern Sphinx",
+	"Stone of a Thousand Terrors",
+	"Golem Stone of Admittance",
+	"Yak Stone of Opening",
+	"Xeen's Scepter of Temporal Distortion",
+	"Alacorn of Falista",
+	"Elixir of Restoration",
+	"Wand of Faery Magic",
+	"Princess Roxanne's Tiara",
+	"Holy Book of Elvenkind",
+	"Scarab of Imaging",
+	"Crystals of Piezoelectricity",
+	"Scroll of Insight",
+	"Phirna Root",
+	"Orothin's Bone Whistle",
+	"Barok's Magic Pendant",
+	"Ligono's Missing Skull",
+	"Last Flower of Summer",
+	"Last Raindrop of Spring",
+	"Last Snowflake of Winter",
+	"Last Leaf of Autumn",
+	"Ever Hot Lava Rock",
+	"King's Mega Credit",
+	"Excavation Permit",
+	"Cupie Doll",
+	"Might Doll",
+	"Speed Doll",
+	"Endurance Doll",
+	"Accuracy Doll",
+	"Luck Doll",
+	"Widget",
+	"Pass to Castleview",
+	"Pass to Sandcaster",
+	"Pass to Lakeside",
+	"Pass to Necropolis",
+	"Pass to Olympus",
+	"Key to Great Western Tower",
+	"Key to Great Southern Tower",
+	"Key to Great Eastern Tower",
+	"Key to Great Northern Tower",
+	"Key to Ellinger's Tower",
+	"Key to Dragon Tower",
+	"Key to Darkstone Tower",
+	"Key to Temple of Bark",
+	"Key to Dungeon of Lost Souls",
+	"Key to Ancient Pyramid",
+	"Key to Dungeon of Death",
+	"Amulet of the Southern Sphinx",
+	"Dragon Pharoah's Orb",
+	"Cube of Power",
+	"Chime of Opening",
+	"Gold ID Card",
+	"Silver ID Card",
+	"Vulture Repellant",
+	"Bridle",
+	"Enchanted Bridle",
+	"Treasure Map (Goto E1 x1, y11)",
+	nullptr,
+	"Fake Map",
+	"Onyx Necklace",
+	"Dragon Egg",
+	"Tribble",
+	"Golden Pegasus Statuette",
+	"Golden Dragon Statuette",
+	"Golden Griffin Statuette",
+	"Chalice of Protection",
+	"Jewel of Ages",
+	"Songbird of Serenity",
+	"Sandro's Heart",
+	"Ector's Ring",
+	"Vespar's Emerald Handle",
+	"Queen Kalindra's Crown",
+	"Caleb's Magnifying Glass",
+	"Soul Box",
+	"Soul Box with Corak inside",
+	"Ruby Rock",
+	"Emerald Rock",
+	"Sapphire Rock",
+	"Diamond Rock",
+	"Monga Melon",
+	"Energy Disk"
+};
+
 const int WEAPON_BASE_COSTS[35] = {
 	0, 50, 15, 100, 80, 40, 60, 1, 10, 150, 30, 60, 8, 50,
 	100, 15, 30, 15, 200, 80, 250, 150, 400, 100, 40, 120,
@@ -1288,4 +1376,51 @@ const char *const ELEMENTAL_XY_DAMAGE = "%+d %s Damage";
 const char *const ATTR_XY_BONUS = "%+d %s";
 const char *const EFFECTIVE_AGAINST = "x3 vs %s";
 
+const char *const QUESTS_DIALOG_TEXT =
+	"\r2\x2""c\v021\t017\f37I\fdtems\t085\f37Q\fduests\t153"
+	"\f37A\fduto Notes\t221\f37U\fdp\t255\f37D\fdown\t289Exit";
+
+const char *const CLOUDS_OF_XEEN_LINE = "\b \b*-- \f04Clouds of Xeen\fd --";
+const char *const DARKSIDE_OF_XEEN_LINE = "\b \b*-- \f04Darkside of Xeen\fd --";
+
+const char *const NO_QUEST_ITEMS =
+	"\rd\x3""c\v000	000Quest Items\x3l\x2\n"
+	"\n"
+	"\x3""cNo Quest Items";
+const char *const NO_CURRENT_QUESTS =
+	"\x3""c\v000\t000\n"
+	"\n"
+	"No Current Quests";
+const char *const NO_AUTO_NOTES = "\x3""cNo Auto Notes";
+
+const char *const QUEST_ITEMS_DATA =
+	"\r\x1\fd\x3""c\v000\t000Quest Items\x3l\x2\n"
+	"\f04 * \fd%s\n"
+	"\f04 * \fd%s\n"
+	"\f04 * \fd%s\n"
+	"\f04 * \fd%s\n"
+	"\f04 * \fd%s\n"
+	"\f04 * \fd%s\n"
+	"\f04 * \fd%s\n"
+	"\f04 * \fd%s\n"
+	"\f04 * \fd%s";
+const char *const CURRENT_QUESTS_DATA = 
+	"\r\x1\fd\x3""c\t000\v000Current Quests\x3l\x2\n"
+	"%s\n"
+	"\n"
+	"%s\n"
+	"\n"
+	"%s";
+const char *const AUTO_NOTES_DATA =
+	"\r\x1\fd\x3""c\t000\v000Auto Notes\x3l\x2\n"
+	"%s\x3l\n"
+	"%s\x3l\n"
+	"%s\x3l\n"
+	"%s\x3l\n"
+	"%s\x3l\n"
+	"%s\x3l\n"
+	"%s\x3l\n"
+	"%s\x3l\n"
+	"%s\x3l";
+
 } // End of namespace Xeen
diff --git a/engines/xeen/resources.h b/engines/xeen/resources.h
index 4c79a1e..9c0136c 100644
--- a/engines/xeen/resources.h
+++ b/engines/xeen/resources.h
@@ -387,6 +387,7 @@ extern const char *const MISC_NAMES[22];
 extern const char *const ELEMENTAL_NAMES[6];
 extern const char *const ATTRIBUTE_NAMES[10];
 extern const char *const EFFECTIVENESS_NAMES[7];
+extern const char *const QUEST_ITEM_NAMES[85];
 
 extern const int WEAPON_BASE_COSTS[35];
 extern const int ARMOR_BASE_COSTS[25];
@@ -474,6 +475,17 @@ extern const char *const ELEMENTAL_XY_DAMAGE;
 extern const char *const ATTR_XY_BONUS;
 extern const char *const EFFECTIVE_AGAINST;
 
+extern const char *const QUESTS_DIALOG_TEXT;
+extern const char *const CLOUDS_OF_XEEN_LINE;
+extern const char *const DARKSIDE_OF_XEEN_LINE;
+
+extern const char *const NO_QUEST_ITEMS;
+extern const char *const NO_CURRENT_QUESTS;
+extern const char *const NO_AUTO_NOTES;
+extern const char *const QUEST_ITEMS_DATA;
+extern const char *const CURRENT_QUESTS_DATA;
+extern const char *const AUTO_NOTES_DATA;
+
 } // End of namespace Xeen
 
 #endif	/* XEEN_RESOURCES_H */


Commit: 528fce5ac4ffec769a0f60472a6d947320b3301b
    https://github.com/scummvm/scummvm/commit/528fce5ac4ffec769a0f60472a6d947320b3301b
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-02-07T18:14:43-05:00

Commit Message:
XEEN: Fix headers and key handling in Quests dialog

Changed paths:
    engines/xeen/dialogs_quests.cpp
    engines/xeen/resources.cpp



diff --git a/engines/xeen/dialogs_quests.cpp b/engines/xeen/dialogs_quests.cpp
index 1725594..146415b 100644
--- a/engines/xeen/dialogs_quests.cpp
+++ b/engines/xeen/dialogs_quests.cpp
@@ -233,9 +233,9 @@ void Quests::addButtons() {
 	addButton(Common::Rect(12, 109, 36, 129), Common::KEYCODE_i, &_iconSprites);
 	addButton(Common::Rect(80, 109, 104, 129), Common::KEYCODE_q, &_iconSprites);
 	addButton(Common::Rect(148, 109, 172, 129), Common::KEYCODE_a, &_iconSprites);
-	addButton(Common::Rect(216, 109, 240, 129), Common::KEYCODE_i, &_iconSprites);
-	addButton(Common::Rect(250, 109, 274, 129), Common::KEYCODE_UP, &_iconSprites);
-	addButton(Common::Rect(284, 109, 308, 129), Common::KEYCODE_DOWN, &_iconSprites);
+	addButton(Common::Rect(216, 109, 240, 129), Common::KEYCODE_UP, &_iconSprites);
+	addButton(Common::Rect(250, 109, 274, 129), Common::KEYCODE_DOWN, &_iconSprites);
+	addButton(Common::Rect(284, 109, 308, 129), Common::KEYCODE_ESCAPE, &_iconSprites);
 }
 
 void Quests::loadQuestNotes() {
diff --git a/engines/xeen/resources.cpp b/engines/xeen/resources.cpp
index eeea54c..5a50e07 100644
--- a/engines/xeen/resources.cpp
+++ b/engines/xeen/resources.cpp
@@ -1377,14 +1377,14 @@ const char *const ATTR_XY_BONUS = "%+d %s";
 const char *const EFFECTIVE_AGAINST = "x3 vs %s";
 
 const char *const QUESTS_DIALOG_TEXT =
-	"\r2\x2""c\v021\t017\f37I\fdtems\t085\f37Q\fduests\t153"
-	"\f37A\fduto Notes\t221\f37U\fdp\t255\f37D\fdown\t289Exit";
-
+	"\r\x2\x3""c\v021\t017\f37I\fdtems\t085\f37Q\fduests\t153"
+	"\f37A\fduto Notes	221\f37U\fdp\t255\f37D\fdown"
+	"\t289Exit";
 const char *const CLOUDS_OF_XEEN_LINE = "\b \b*-- \f04Clouds of Xeen\fd --";
 const char *const DARKSIDE_OF_XEEN_LINE = "\b \b*-- \f04Darkside of Xeen\fd --";
 
 const char *const NO_QUEST_ITEMS =
-	"\rd\x3""c\v000	000Quest Items\x3l\x2\n"
+	"\r\x3""c\v000	000Quest Items\x3l\x2\n"
 	"\n"
 	"\x3""cNo Quest Items";
 const char *const NO_CURRENT_QUESTS =


Commit: c313113f6b72524c1bdc41fd30c2bdc4182de3a4
    https://github.com/scummvm/scummvm/commit/c313113f6b72524c1bdc41fd30c2bdc4182de3a4
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-02-07T18:32:37-05:00

Commit Message:
XEEN: Fix for switching modes and loading auto notes in Quests dialog

Changed paths:
    engines/xeen/dialogs_quests.cpp
    engines/xeen/resources.cpp



diff --git a/engines/xeen/dialogs_quests.cpp b/engines/xeen/dialogs_quests.cpp
index 146415b..284e157 100644
--- a/engines/xeen/dialogs_quests.cpp
+++ b/engines/xeen/dialogs_quests.cpp
@@ -40,7 +40,7 @@ void Quests::execute() {
 	EventsManager &events = *_vm->_events;
 	Party &party = *_vm->_party;
 	Screen &screen = *_vm->_screen;
-	bool isDarkCc = _vm->_files->_isDarkCc;
+	Mode oldMode = _vm->_mode;
 	int count = 0;
 	bool headerShown = false;
 	int topRow = 0;
@@ -190,12 +190,15 @@ void Quests::execute() {
 		switch (_buttonValue) {
 		case Common::KEYCODE_a:
 			mode = AUTO_NOTES;
+			topRow = 0;
 			break;
 		case Common::KEYCODE_i:
 			mode = QUEST_ITEMS;
+			topRow = 0;
 			break;
 		case Common::KEYCODE_q:
 			mode = CURRENT_QUESTS;
+			topRow = 0;
 			break;
 		case Common::KEYCODE_HOME:
 			topRow = 0;
@@ -226,10 +229,13 @@ void Quests::execute() {
 		screen._windows[30].close();
 		screen._windows[29].close();
 	}
+	_vm->_mode = oldMode;
 }
 
 void Quests::addButtons() {
 	_iconSprites.load("quest.icn");
+
+
 	addButton(Common::Rect(12, 109, 36, 129), Common::KEYCODE_i, &_iconSprites);
 	addButton(Common::Rect(80, 109, 104, 129), Common::KEYCODE_q, &_iconSprites);
 	addButton(Common::Rect(148, 109, 172, 129), Common::KEYCODE_a, &_iconSprites);
@@ -239,7 +245,7 @@ void Quests::addButtons() {
 }
 
 void Quests::loadQuestNotes() {
-	File f("qnotes.bin");
+	File f("qnotes.bin", *_vm->_files->_sideArchives[_vm->getGameID() == GType_Clouds ? 0 : 1]);
 	while (f.pos() < f.size())
 		_questNotes.push_back(f.readString());
 	f.close();
diff --git a/engines/xeen/resources.cpp b/engines/xeen/resources.cpp
index 5a50e07..204e727 100644
--- a/engines/xeen/resources.cpp
+++ b/engines/xeen/resources.cpp
@@ -1206,7 +1206,7 @@ const char *const QUEST_ITEM_NAMES[85] = {
 	"Bridle",
 	"Enchanted Bridle",
 	"Treasure Map (Goto E1 x1, y11)",
-	nullptr,
+	"",
 	"Fake Map",
 	"Onyx Necklace",
 	"Dragon Egg",


Commit: 996ce240833477855f5787a9f3501e8dc8ba8022
    https://github.com/scummvm/scummvm/commit/996ce240833477855f5787a9f3501e8dc8ba8022
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-02-07T18:43:05-05:00

Commit Message:
XEEN: Fix writeString to constrain text to window

Changed paths:
    engines/xeen/font.cpp
    engines/xeen/font.h



diff --git a/engines/xeen/font.cpp b/engines/xeen/font.cpp
index aca747e..53308ae 100644
--- a/engines/xeen/font.cpp
+++ b/engines/xeen/font.cpp
@@ -60,7 +60,7 @@ void FontSurface::writeSymbol(int symbolId) {
 /**
  * Write a string to the surface
  * @param s			String to display
- * @param bounds	Window bounds to display string within
+ * @param clipRect	Window bounds to display string within
  * @returns			Any string remainder that couldn't be displayed
  * @remarks		Note that bounds is just used for wrapping purposes. Unless
  *		justification is set, the message will be written at _writePos
@@ -183,7 +183,7 @@ Common::String FontSurface::writeString(const Common::String &s, const Common::R
 				continue;
 			} else if (c == 6) {
 				// Non-breakable space
-				writeChar(' ');
+				writeChar(' ', bounds);
 			} else if (c == 7) {
 				// Set text background color
 				int bgColor = fontAtoi();
@@ -210,7 +210,7 @@ Common::String FontSurface::writeString(const Common::String &s, const Common::R
 					Common::copy(&_textColors[0], &_textColors[4], &oldColor[0]);
 
 					_textColors[1] = _textColors[2] = _textColors[3] = _bgColor;
-					writeChar(c);
+					writeChar(c, bounds);
 
 					Common::copy(&oldColor[0], &oldColor[4], &_textColors[0]);
 					_writePos.x = oldX;
@@ -239,7 +239,7 @@ Common::String FontSurface::writeString(const Common::String &s, const Common::R
 				break;
 			} else {
 				// Standard character - write it out
-				writeChar(c);
+				writeChar(c, bounds);
 			}
 		}
 
@@ -340,7 +340,7 @@ void FontSurface::setTextColor(int idx) {
 /**
  * Wrie a character to the surface
  */
-void FontSurface::writeChar(char c) {
+void FontSurface::writeChar(char c, const Common::Rect &clipRect) {
 	// Get y position, handling kerning
 	int y = _writePos.y;
 	if (c == 'g' || c == 'p' || c == 'q' || c == 'y')
@@ -354,11 +354,17 @@ void FontSurface::writeChar(char c) {
 		uint16 lineData = READ_LE_UINT16(srcP); srcP += 2;
 		byte *destP = (byte *)getBasePtr(_writePos.x, y);
 
+		// Ignore line if it's outside the clipping rect
+		if (y < clipRect.top || y >= clipRect.bottom)
+			continue;
+		const byte *lineStart = (const byte *)getBasePtr(clipRect.left, y);
+		const byte *lineEnd = (const byte *)getBasePtr(clipRect.right, y);
+
 		for (int xp = 0; xp < FONT_WIDTH; ++xp, ++destP) {
 			int colIndex = lineData & 3;
 			lineData >>= 2;
 
-			if (colIndex)
+			if (colIndex && destP >= lineStart && destP < lineEnd)
 				*destP = _textColors[colIndex];
 		}
 	}
diff --git a/engines/xeen/font.h b/engines/xeen/font.h
index 6b362d7..db61e3e 100644
--- a/engines/xeen/font.h
+++ b/engines/xeen/font.h
@@ -48,7 +48,7 @@ private:
 
 	void setTextColor(int idx);
 
-	void writeChar(char c);
+	void writeChar(char c, const Common::Rect &clipRect);
 public:
 	const byte *_fontData;
 	Common::Point _writePos;
@@ -63,7 +63,7 @@ public:
 
 	void writeSymbol(int symbolId);
 
-	Common::String writeString(const Common::String &s, const Common::Rect &bounds);
+	Common::String writeString(const Common::String &s, const Common::Rect &clipRect);
 };
 
 } // End of namespace Xeen


Commit: 54ae7eb22a33ec6bb506d5458a0f7c1bbc6945fd
    https://github.com/scummvm/scummvm/commit/54ae7eb22a33ec6bb506d5458a0f7c1bbc6945fd
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-02-07T19:00:21-05:00

Commit Message:
XEEN: Fix incorrect variable usage in makeItem

Changed paths:
    engines/xeen/character.cpp



diff --git a/engines/xeen/character.cpp b/engines/xeen/character.cpp
index cde244b..9d67567 100644
--- a/engines/xeen/character.cpp
+++ b/engines/xeen/character.cpp
@@ -1693,32 +1693,23 @@ int Character::makeItem(int p1, int itemIndex, int p3) {
 			rval = vm->getRandomNumber(1, 100);
 			if (rval <= 15) {
 				mult = 0;
-			}
-			else if (rval <= 25) {
+			} else if (rval <= 25) {
 				mult = 1;
-			}
-			else if (rval <= 35) {
+			} else if (rval <= 35) {
 				mult = 2;
-			}
-			else if (mult <= 50) {
+			} else if (rval <= 50) {
 				mult = 3;
-			}
-			else if (mult <= 65) {
+			} else if (rval <= 65) {
 				mult = 4;
-			}
-			else if (mult <= 80) {
+			} else if (rval <= 80) {
 				mult = 5;
-			}
-			else if (mult <= 85) {
+			} else if (rval <= 85) {
 				mult = 6;
-			}
-			else if (mult <= 90) {
+			} else if (rval <= 90) {
 				mult = 7;
-			}
-			else if (mult <= 95) {
+			} else if (rval <= 95) {
 				mult = 8;
-			}
-			else {
+			} else {
 				mult = 9;
 			}
 


Commit: 65ecc9b72138f2dcef0ccf3765363559649b77a2
    https://github.com/scummvm/scummvm/commit/65ecc9b72138f2dcef0ccf3765363559649b77a2
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-02-07T19:08:44-05:00

Commit Message:
XEEN: Another fix for makeItem variable usage

Changed paths:
    engines/xeen/character.cpp



diff --git a/engines/xeen/character.cpp b/engines/xeen/character.cpp
index 9d67567..4e4a4da 100644
--- a/engines/xeen/character.cpp
+++ b/engines/xeen/character.cpp
@@ -1718,7 +1718,7 @@ int Character::makeItem(int p1, int itemIndex, int p3) {
 			break;
 
 		case 3:
-			rval = p1 == 7 || vm->getRandomNumber(1, 100) > 70;
+			mult = p1 == 7 || vm->getRandomNumber(1, 100) > 70 ? 1 : 0;
 			v16 = vm->getRandomNumber(MAKE_ITEM_ARR4[mult][p1][0],
 				MAKE_ITEM_ARR4[mult][p1][1]);
 			break;


Commit: d6e760552e785e466b5d2088570baa182d42ccd0
    https://github.com/scummvm/scummvm/commit/d6e760552e785e466b5d2088570baa182d42ccd0
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-02-07T21:17:31-05:00

Commit Message:
XEEN: Implemented resting

Changed paths:
    engines/xeen/character.h
    engines/xeen/dialogs_char_info.cpp
    engines/xeen/dialogs_error.cpp
    engines/xeen/dialogs_items.cpp
    engines/xeen/dialogs_spells.cpp
    engines/xeen/interface.cpp
    engines/xeen/interface.h
    engines/xeen/interface_map.cpp
    engines/xeen/map.cpp
    engines/xeen/map.h
    engines/xeen/party.cpp
    engines/xeen/party.h
    engines/xeen/resources.cpp
    engines/xeen/resources.h
    engines/xeen/spells.cpp
    engines/xeen/xeen.h



diff --git a/engines/xeen/character.h b/engines/xeen/character.h
index af9e331..c9a787c 100644
--- a/engines/xeen/character.h
+++ b/engines/xeen/character.h
@@ -67,7 +67,7 @@ enum Skill {
 
 enum Condition {
 	CURSED = 0, HEART_BROKEN = 1, WEAK = 2, POISONED = 3,
-	DISEASED = 4, INSANE = 5, IN_LOVE = 6, DRUNK = 7, SLEEP = 8,
+	DISEASED = 4, INSANE = 5, IN_LOVE = 6, DRUNK = 7, ASLEEP = 8,
 	DEPRESSED = 9, CONFUSED = 10, PARALYZED = 11, UNCONSCIOUS = 12,
 	DEAD = 13, STONED = 14, ERADICATED = 15,
 	NO_CONDITION = 16
diff --git a/engines/xeen/dialogs_char_info.cpp b/engines/xeen/dialogs_char_info.cpp
index 0c71bfb..36ca5bd 100644
--- a/engines/xeen/dialogs_char_info.cpp
+++ b/engines/xeen/dialogs_char_info.cpp
@@ -47,7 +47,7 @@ void CharacterInfo::execute(int charIndex) {
 	loadDrawStructs();
 	addButtons();
 
-	Character *c = (oldMode != MODE_InCombat) ? &party._activeParty[charIndex] : party._combatParty[charIndex];
+	Character *c = (oldMode != MODE_COMBAT) ? &party._activeParty[charIndex] : party._combatParty[charIndex];
 	intf.highlightChar(charIndex);
 	Window &w = screen._windows[24];
 	w.open();
@@ -86,9 +86,9 @@ void CharacterInfo::execute(int charIndex) {
 		case Common::KEYCODE_F5:
 		case Common::KEYCODE_F6:
 			_buttonValue -= Common::KEYCODE_F1;
-			if (_buttonValue < (int)(oldMode == MODE_InCombat ? party._combatParty.size() : party._activeParty.size())) {
+			if (_buttonValue < (int)(oldMode == MODE_COMBAT ? party._combatParty.size() : party._activeParty.size())) {
 				charIndex = _buttonValue;
-				c = (oldMode != MODE_InCombat) ? &party._activeParty[charIndex] : party._combatParty[charIndex];
+				c = (oldMode != MODE_COMBAT) ? &party._activeParty[charIndex] : party._combatParty[charIndex];
 			} else {
 				_vm->_mode = MODE_CHARACTER_INFO;
 			}
@@ -166,14 +166,14 @@ void CharacterInfo::execute(int charIndex) {
 			w.update();
 
 			bool result = expandStat(_cursorCell, *c);
-			_vm->_mode = MODE_InCombat;
+			_vm->_mode = MODE_COMBAT;
 			if (result)
 				redrawFlag = true;
 			break;
 		}
 
 		case Common::KEYCODE_e:
-			if (oldMode == MODE_InCombat) {
+			if (oldMode == MODE_COMBAT) {
 				ErrorScroll::show(_vm, EXCHANGING_IN_COMBAT, WT_FREEZE_WAIT);
 			} else {
 				_vm->_mode = oldMode;
@@ -185,7 +185,7 @@ void CharacterInfo::execute(int charIndex) {
 
 		case Common::KEYCODE_i:
 			_vm->_mode = oldMode;
-			_vm->_combat->_itemFlag = _vm->_mode == MODE_InCombat;
+			_vm->_combat->_itemFlag = _vm->_mode == MODE_COMBAT;
 			c = ItemsDialog::show(_vm, c, ITEMMODE_CHAR_INFO);
 
 			if (!c) {
diff --git a/engines/xeen/dialogs_error.cpp b/engines/xeen/dialogs_error.cpp
index 598af1e..4fe39db 100644
--- a/engines/xeen/dialogs_error.cpp
+++ b/engines/xeen/dialogs_error.cpp
@@ -76,7 +76,7 @@ void ErrorDialog::execute(const Common::String &msg, ErrorWaitType waitType) {
 /*------------------------------------------------------------------------*/
 
 void ErrorScroll::show(XeenEngine *vm, const Common::String &msg, ErrorWaitType waitType) {
-	Common::String s = Common::String::format("\x03c\v010\t000%s", msg.c_str());
+	Common::String s = Common::String::format("\x3""c\v010\t000%s", msg.c_str());
 	ErrorDialog::show(vm, s, waitType);
 }
 
diff --git a/engines/xeen/dialogs_items.cpp b/engines/xeen/dialogs_items.cpp
index 83e0dd2..002a8fb 100644
--- a/engines/xeen/dialogs_items.cpp
+++ b/engines/xeen/dialogs_items.cpp
@@ -336,11 +336,11 @@ Character *ItemsDialog::execute(Character *c, ItemsMode mode) {
 					&& party._mazeId != 0) {
 				_buttonValue -= Common::KEYCODE_F1;
 				
-				if (_buttonValue < (int)(_vm->_mode == MODE_InCombat ?
+				if (_buttonValue < (int)(_vm->_mode == MODE_COMBAT ?
 						party._combatParty.size() : party._activeParty.size())) {
 					// Character number is valid
 					redrawFlag = REDRAW_TEXT;
-					Character *newChar = _vm->_mode == MODE_InCombat ?
+					Character *newChar = _vm->_mode == MODE_COMBAT ?
 						party._combatParty[_buttonValue] : &party._activeParty[_buttonValue];
 
 					if (mode == ITEMMODE_BLACKSMITH) {
@@ -867,7 +867,7 @@ int ItemsDialog::doItemOptions(Character &c, int actionIndex, int itemIndex, Ite
 
 					Condition condition = c.worstCondition();
 					switch (condition) {
-					case SLEEP:
+					case ASLEEP:
 					case PARALYZED:
 					case UNCONSCIOUS:
 					case DEAD:
diff --git a/engines/xeen/dialogs_spells.cpp b/engines/xeen/dialogs_spells.cpp
index 4f86707..dc05be6 100644
--- a/engines/xeen/dialogs_spells.cpp
+++ b/engines/xeen/dialogs_spells.cpp
@@ -109,7 +109,7 @@ Character *SpellsScroll::execute(Character *c, int v2) {
 		switch (_buttonValue) {
 		case Common::KEYCODE_F1:
 		case Common::KEYCODE_F6:
-			if (_vm->_mode != MODE_InCombat) {
+			if (_vm->_mode != MODE_COMBAT) {
 				_buttonValue -= Common::KEYCODE_F1;
 				if (_buttonValue < party._partyCount) {
 					c = &party._activeParty[_buttonValue];
diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp
index 34c7b54..c31ff84 100644
--- a/engines/xeen/interface.cpp
+++ b/engines/xeen/interface.cpp
@@ -25,6 +25,7 @@
 #include "xeen/dialogs_error.h"
 #include "xeen/dialogs_automap.h"
 #include "xeen/dialogs_info.h"
+#include "xeen/dialogs_query.h"
 #include "xeen/dialogs_quests.h"
 #include "xeen/dialogs_quick_ref.h"
 #include "xeen/resources.h"
@@ -334,7 +335,7 @@ void Interface::setupFaces(int charIndex, Common::Array<int> xeenSideChars, bool
 
 void Interface::charIconsPrint(bool updateFlag) {
 	Screen &screen = *_vm->_screen;
-	bool stateFlag = _vm->_mode == MODE_InCombat;
+	bool stateFlag = _vm->_mode == MODE_COMBAT;
 	_restoreSprites.draw(screen, 0, Common::Point(8, 149));
 
 	// Handle drawing the party faces
@@ -711,6 +712,11 @@ void Interface::perform() {
 		QuickReferenceDialog::show(_vm);
 		break;
 
+	case Common::KEYCODE_r:
+		// Rest
+		rest();
+		break;
+
 	case Common::KEYCODE_v:
 		// Show the quests dialog
 		Quests::show(_vm);
@@ -949,4 +955,135 @@ bool Interface::checkMoveDirection(int key) {
 	return true;
 }
 
+void Interface::rest() {
+	EventsManager &events = *_vm->_events;
+	Map &map = *_vm->_map;
+	Party &party = *_vm->_party;
+	Screen &screen = *_vm->_screen;
+	SoundManager &sound = *_vm->_sound;
+
+	map.cellFlagLookup(party._mazePosition);
+
+	if ((map._currentCantRest || (map.mazeData()._mazeFlags & RESTRICTION_REST))
+			&& _vm->_mode != MODE_12) {
+		ErrorScroll::show(_vm, TOO_DANGEROUS_TO_REST, WT_NONFREEZED_WAIT);
+	} else {
+		// Check whether any character is in danger of dying
+		bool dangerFlag = false;
+		for (uint charIdx = 0; charIdx < party._activeParty.size(); ++charIdx) {
+			for (int attrib = MIGHT; attrib <= LUCK; ++attrib) {
+				if (party._activeParty[charIdx].getStat((Attribute)attrib) < 1)
+					dangerFlag = true;
+			}
+		}
+
+		if (dangerFlag) {
+			if (!Confirm::show(_vm, SOME_CHARS_MAY_DIE))
+				return;
+		}
+
+		// Mark all the players as being asleep
+		for (uint charIdx = 0; charIdx < party._activeParty.size(); ++charIdx) {
+			party._activeParty[charIdx]._conditions[ASLEEP] = 1;
+		}
+		charIconsPrint(true);
+
+		Mode oldMode = _vm->_mode;
+		_vm->_mode = MODE_SLEEPING;
+
+		if (oldMode == MODE_12) {
+			party.changeTime(8 * 60);
+		} else {
+			for (int idx = 0; idx < 10; ++idx) {
+				chargeStep();
+				draw3d(true);
+				
+				if (_vm->_mode == MODE_1) {
+					_vm->_mode = oldMode;
+					return;
+				}
+			}
+
+			party.changeTime(map._isOutdoors ? 380 : 470);
+		}
+
+		if (_vm->getRandomNumber(1, 20) == 1) {
+			// Show dream
+			screen.saveBackground();
+			screen.fadeOut(4);
+			events.hideCursor();
+
+			screen.loadBackground("scene1.raw");
+			screen._windows[0].update();
+			screen.fadeIn(4);
+
+			events.updateGameCounter();
+			while (!_vm->shouldQuit() && events.timeElapsed() < 7)
+				events.pollEventsAndWait();
+
+			File f("dreams2.voc");
+			sound.playSample(&f, 1);
+			while (!_vm->shouldQuit() && sound.playSample(1, 0))
+				events.pollEventsAndWait();
+			f.close();
+
+			f.openFile("laff1.voc");
+			sound.playSample(&f, 1);
+			while (!_vm->shouldQuit() && sound.playSample(1, 0))
+				events.pollEventsAndWait();
+			f.close();
+
+			events.updateGameCounter();
+			while (!_vm->shouldQuit() && events.timeElapsed() < 7)
+				events.pollEventsAndWait();
+
+			screen.fadeOut(4);
+			events.setCursor(0);
+			screen.restoreBackground();
+			screen._windows[0].update();
+
+			screen.fadeIn(4);
+		}
+
+		party.resetTemps();
+
+		// Wake up the party
+		bool starving = false;
+		int foodConsumed = 0;
+		for (uint charIdx = 0; charIdx < party._activeParty.size(); ++charIdx) {
+			Character &c = party._activeParty[charIdx];
+			c._conditions[ASLEEP] = 0;
+
+			if (party._food == 0) {
+				starving = true;
+			} else {
+				party._rested = true;
+				Condition condition = c.worstCondition();
+
+				if (condition < DEAD || condition > ERADICATED) {
+					--party._food;
+					++foodConsumed;
+					party._heroism = 0;
+					party._holyBonus = 0;
+					party._powerShield = 0;
+					party._blessed = 0;
+					c._conditions[UNCONSCIOUS] = 0;
+					c._currentHp = c.getMaxHP();
+					c._currentSp = c.getMaxSP();
+				}
+			}
+		}
+
+		charIconsPrint(true);
+		_vm->_mode = oldMode;
+		doStepCode();
+		draw3d(true);
+
+		ErrorScroll::show(_vm, Common::String::format(REST_COMPLETE,
+			starving ? PARTY_IS_STARVING : HIT_SPELL_POINTS_RESTORED,
+			foodConsumed));
+		party.checkPartyDead();
+	}
+}
+
 } // End of namespace Xeen
diff --git a/engines/xeen/interface.h b/engines/xeen/interface.h
index 103b8b6..cecc5c3 100644
--- a/engines/xeen/interface.h
+++ b/engines/xeen/interface.h
@@ -104,6 +104,8 @@ public:
 	void unhighlightChar();
 
 	void perform();
+
+	void rest();
 };
 
 } // End of namespace Xeen
diff --git a/engines/xeen/interface_map.cpp b/engines/xeen/interface_map.cpp
index c8683a7..42c5ff4 100644
--- a/engines/xeen/interface_map.cpp
+++ b/engines/xeen/interface_map.cpp
@@ -426,7 +426,7 @@ void InterfaceMap::draw3d(bool updateFlag) {
 	_flipUIFrame = (_flipUIFrame + 1) % 4;
 	if (_flipUIFrame == 0)
 		_flipWater = !_flipWater;
-	if (_tillMove && (_vm->_mode == MODE_1 || _vm->_mode == MODE_InCombat) &&
+	if (_tillMove && (_vm->_mode == MODE_1 || _vm->_mode == MODE_COMBAT) &&
 		!_flag1 && _vm->_moveMonsters) {
 		if (--_tillMove == 0)
 			moveMonsters();
diff --git a/engines/xeen/map.cpp b/engines/xeen/map.cpp
index 51e87ef..dc58c2d 100644
--- a/engines/xeen/map.cpp
+++ b/engines/xeen/map.cpp
@@ -1369,7 +1369,7 @@ void Map::cellFlagLookup(const Common::Point &pt) {
 	// Get the cell flags
 	const MazeCell &cell = _mazeData[_mazeDataIndex]._cells[pos.y][pos.x];
 	_currentIsGrate = cell._flags & OUTFLAG_GRATE;
-	_currentCantRest = cell._flags & FLAG_WATER;
+	_currentCantRest = cell._flags & RESTRICTION_REST;
 	_currentIsDrain = cell._flags & OUTFLAG_DRAIN;
 	_currentIsEvent = cell._flags & FLAG_AUTOEXECUTE_EVENT;
 	_currentSky = (cell._flags & OUTFLAG_OBJECT_EXISTS) ? 1 : 0;
diff --git a/engines/xeen/map.h b/engines/xeen/map.h
index abc3641..806b408 100644
--- a/engines/xeen/map.h
+++ b/engines/xeen/map.h
@@ -137,8 +137,13 @@ public:
 
 enum MazeFlags {
 	OUTFLAG_GRATE = 0x80, OUTFLAG_DRAIN = 0x20, OUTFLAG_OBJECT_EXISTS = 0x08,
-	INFLAG_INSIDE = 0x08,
-	FLAG_WATER = 0x40, FLAG_AUTOEXECUTE_EVENT = 0x10,
+	INFLAG_INSIDE = 0x08, FLAG_AUTOEXECUTE_EVENT = 0x10,
+	RESTRICTION_ETHERIALIZE = 0x40, RESTRICTION_80 = 0x80, 
+	RESTRICTION_TOWN_PORTAL = 0x100, RESTRICTION_SUPER_SHELTER = 0x200,
+	RESTRICTION_TIME_DISTORTION = 0x400, RESTRICTION_LLOYDS_BEACON = 0x800,
+	RESTRICTION_TELPORT = 0x1000, RESTRICTION_2000 = 0x2000,
+	RESTRICTION_REST = 0x4000, RESTRICTION_SAVE = 0x8000,
+
 	FLAG_GROUND_BITS = 7
 };
 
diff --git a/engines/xeen/party.cpp b/engines/xeen/party.cpp
index be8f4e6..ff59ed9 100644
--- a/engines/xeen/party.cpp
+++ b/engines/xeen/party.cpp
@@ -102,6 +102,7 @@ Party::Party(XeenEngine *vm) {
 	_falling = false;
 	_fallMaze = 0;
 	_fallDamage = 0;
+	_dead = false;
 }
 
 void Party::synchronize(Common::Serializer &s) {
@@ -360,7 +361,7 @@ void Party::addTime(int numMinutes) {
 	if (_newDay && _minutes >= 300) {
 		if (_vm->_mode != MODE_9 && _vm->_mode != MODE_17) {
 			resetTemps();
-			if (_rested || _vm->_mode == MODE_5) {
+			if (_rested || _vm->_mode == MODE_SLEEPING) {
 				_rested = false;
 			} else {
 				for (int idx = 0; idx < _partyCount; ++idx) {
@@ -497,4 +498,19 @@ void Party::notEnough(int consumableId, int whereId, bool mode, ErrorWaitType wa
 	ErrorScroll::show(_vm, msg, wait);
 }
 
+void Party::checkPartyDead() {
+	bool inCombat = _vm->_mode == MODE_COMBAT;
+
+	for (uint charIdx = 0; charIdx < (inCombat ? _combatParty.size() : _activeParty.size()); ++charIdx) {
+		Character &c = inCombat ? *_combatParty[charIdx] : _activeParty[charIdx];
+		Condition cond = c.worstCondition();
+		if (cond <= CONFUSED || cond == NO_CONDITION) {
+			_dead = false;
+			return;
+		}
+	}
+
+	_dead = true;
+}
+
 } // End of namespace Xeen
diff --git a/engines/xeen/party.h b/engines/xeen/party.h
index b1ca067..5b7da05 100644
--- a/engines/xeen/party.h
+++ b/engines/xeen/party.h
@@ -125,6 +125,7 @@ public:
 	int _fallMaze;
 	int _fallDamage;
 	DamageType _damageType;
+	bool _dead;
 public:
 	Party(XeenEngine *vm);
 
@@ -147,6 +148,8 @@ public:
 	int subtract(int mode, uint amount, int whereId, ErrorWaitType wait = WT_FREEZE_WAIT);
 
 	void notEnough(int consumableId, int whereId, bool mode, ErrorWaitType wait);
+
+	void checkPartyDead();
 };
 
 } // End of namespace Xeen
diff --git a/engines/xeen/resources.cpp b/engines/xeen/resources.cpp
index 204e727..d127ddc 100644
--- a/engines/xeen/resources.cpp
+++ b/engines/xeen/resources.cpp
@@ -1423,4 +1423,13 @@ const char *const AUTO_NOTES_DATA =
 	"%s\x3l\n"
 	"%s\x3l";
 
+const char *const REST_COMPLETE = 
+	"\v000\t0008 hours pass.  Rest complete.\n"
+	"%s\n"
+	"%d food consumed.";
+const char *const PARTY_IS_STARVING = "\f07The Party is Starving!\fd";
+const char *const HIT_SPELL_POINTS_RESTORED = "Hit Pts and Spell Pts restored.";
+const char *const TOO_DANGEROUS_TO_REST = "Too dangerous to rest here!";
+const char *const SOME_CHARS_MAY_DIE = "Some Chars may die. Rest anyway?";
+
 } // End of namespace Xeen
diff --git a/engines/xeen/resources.h b/engines/xeen/resources.h
index 9c0136c..517d6e4 100644
--- a/engines/xeen/resources.h
+++ b/engines/xeen/resources.h
@@ -486,6 +486,12 @@ extern const char *const QUEST_ITEMS_DATA;
 extern const char *const CURRENT_QUESTS_DATA;
 extern const char *const AUTO_NOTES_DATA;
 
+extern const char *const REST_COMPLETE;
+extern const char *const PARTY_IS_STARVING;
+extern const char *const HIT_SPELL_POINTS_RESTORED;
+extern const char *const TOO_DANGEROUS_TO_REST;
+extern const char *const SOME_CHARS_MAY_DIE;
+
 } // End of namespace Xeen
 
 #endif	/* XEEN_RESOURCES_H */
diff --git a/engines/xeen/spells.cpp b/engines/xeen/spells.cpp
index 50e7766..4943d95 100644
--- a/engines/xeen/spells.cpp
+++ b/engines/xeen/spells.cpp
@@ -92,7 +92,7 @@ void Spells::doSpell(int spellId) {
 		&Spells::implosion, &Spells::starBurst, &Spells::divineIntervention
 	};
 
-	if (_vm->_mode == MODE_InCombat) {
+	if (_vm->_mode == MODE_COMBAT) {
 		if (spellId == 15 || spellId == 20 || spellId == 27 || spellId == 41
 				|| spellId == 47 || spellId == 54 || spellId == 57) {
 			ErrorDialog::show(_vm, Common::String::format(CANT_CAST_WHILE_ENGAGED,
diff --git a/engines/xeen/xeen.h b/engines/xeen/xeen.h
index af2044b..537768e 100644
--- a/engines/xeen/xeen.h
+++ b/engines/xeen/xeen.h
@@ -78,15 +78,16 @@ enum Mode {
 	MODE_FF = -1,
 	MODE_0 = 0,
 	MODE_1 = 1,
-	MODE_InCombat = 2,
+	MODE_COMBAT = 2,
 	MODE_3 = 3,
 	MODE_4 = 4,
-	MODE_5 = 5,
+	MODE_SLEEPING = 5,
 	MODE_6 = 6,
 	MODE_7 = 7,
 	MODE_8 = 8,
 	MODE_9 = 9,
 	MODE_CHARACTER_INFO = 10,
+	MODE_12 = 12,
 	MODE_17 = 17
 };
 


Commit: a381c49c4dddb1c8bb211b9fcaa1aec94410772c
    https://github.com/scummvm/scummvm/commit/a381c49c4dddb1c8bb211b9fcaa1aec94410772c
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-02-07T22:47:28-05:00

Commit Message:
XEEN: Implemented bashing

Changed paths:
    engines/xeen/character.cpp
    engines/xeen/character.h
    engines/xeen/events.cpp
    engines/xeen/events.h
    engines/xeen/interface.cpp
    engines/xeen/interface.h
    engines/xeen/interface_map.h



diff --git a/engines/xeen/character.cpp b/engines/xeen/character.cpp
index 4e4a4da..fb1447d 100644
--- a/engines/xeen/character.cpp
+++ b/engines/xeen/character.cpp
@@ -1757,5 +1757,33 @@ int Character::makeItem(int p1, int itemIndex, int p3) {
 	return category;
 }
 
+void Character::subtractHitPoints(int amount) {
+	SoundManager &sound = *Party::_vm->_sound;
+	_currentHp -= amount;
+	bool flag = _currentHp <= 10;
+
+	if (_currentHp < 1) {
+		int v = getMaxHP() + _currentHp;
+		if (v >= 1) {
+			_conditions[UNCONSCIOUS] = 1;
+			sound.playFX(38);;
+		} else {
+			_conditions[DEAD] = 1;
+			flag = true;
+			if (_currentHp > 0)
+				_currentHp = 0;
+		}
+
+		if (flag) {
+			// Check for breaking equipped armor
+			for (int idx = 0; idx < INV_ITEMS_TOTAL; ++idx) {
+				XeenItem &item = _armor[idx];
+				if (item._id && item._frame)
+					item._bonusFlags |= ITEMFLAG_BROKEN;
+			}
+		}
+	}
+}
+
 
 } // End of namespace Xeen
diff --git a/engines/xeen/character.h b/engines/xeen/character.h
index c9a787c..7fc13f1 100644
--- a/engines/xeen/character.h
+++ b/engines/xeen/character.h
@@ -309,6 +309,8 @@ public:
 	int getNumAwards() const;
 
 	int makeItem(int p1, int itemIndex, int p3);
+
+	void subtractHitPoints(int amount);
 };
 
 } // End of namespace Xeen
diff --git a/engines/xeen/events.cpp b/engines/xeen/events.cpp
index e0c3b26..89a1ac3 100644
--- a/engines/xeen/events.cpp
+++ b/engines/xeen/events.cpp
@@ -168,6 +168,14 @@ bool EventsManager::wait(uint numFrames, bool interruptable) {
 	return false;
 }
 
+void EventsManager::ipause(int amount) {
+	updateGameCounter();
+	do {
+		_vm->_interface->draw3d(true);
+		pollEventsAndWait();
+	} while (!_vm->shouldQuit() && timeElapsed() < amount);
+}
+
 /**
  * Handles moving to the next game frame
  */
diff --git a/engines/xeen/events.h b/engines/xeen/events.h
index 1705bb4..5d6918b 100644
--- a/engines/xeen/events.h
+++ b/engines/xeen/events.h
@@ -90,6 +90,8 @@ public:
 	uint32 timeElapsed5() const { return _frameCounter - _gameCounters[5]; }
 
 	bool wait(uint numFrames, bool interruptable = false);
+
+	void ipause(int amount);
 };
 
 class GameEvent {
diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp
index c31ff84..0d734aa 100644
--- a/engines/xeen/interface.cpp
+++ b/engines/xeen/interface.cpp
@@ -695,6 +695,32 @@ void Interface::perform() {
 		_vm->_moveMonsters = true;
 		break;
 
+	case Common::KEYCODE_b:
+		chargeStep();
+		
+		if (map.getCell(2) < map.mazeData()._difficulties._wallNoPass
+				&& !map._isOutdoors) {
+			switch (party._mazeDirection) {
+			case DIR_NORTH:
+				++party._mazePosition.y;
+				break;
+			case DIR_EAST:
+				++party._mazePosition.x;
+				break;
+			case DIR_SOUTH:
+				--party._mazePosition.y;
+				break;
+			case DIR_WEST:
+				--party._mazePosition.x;
+				break;
+			}
+			chargeStep();
+			stepTime();
+		} else {
+			bash(party._mazePosition, party._mazeDirection);
+		}
+		break;
+
 	case Common::KEYCODE_i:
 		// Show Info dialog
 		_vm->_moveMonsters = false;
@@ -1086,4 +1112,94 @@ void Interface::rest() {
 	}
 }
 
+void Interface::bash(const Common::Point &pt, Direction direction) {
+	EventsManager &events = *_vm->_events;
+	Map &map = *_vm->_map;
+	Party &party = *_vm->_party;
+	Screen &screen = *_vm->_screen;
+	SoundManager &sound = *_vm->_sound;
+
+	if (map._isOutdoors)
+		return;
+
+	sound.playFX(31);
+
+	uint charNum1 = 0, charNum2 = 0;
+	for (uint charIdx = 0; charIdx < party._activeParty.size(); ++charIdx) {
+		Character &c = party._activeParty[charIdx];
+		Condition condition = c.worstCondition();
+
+		if (!(condition == ASLEEP || (condition >= PARALYZED &&
+				condition <= ERADICATED))) {
+			if (charNum1) {
+				charNum2 = charIdx + 1;
+				break;
+			} else {
+				charNum1 = charIdx + 1;
+			}
+		}
+	}
+
+	party._activeParty[charNum1 - 1].subtractHitPoints(2);
+	_charPowSprites.draw(screen._windows[0], 0, 
+		Common::Point(CHAR_FACES_X[charNum1 - 1], 150));
+	screen._windows[0].update();
+
+	if (charNum2) {
+		party._activeParty[charNum2 - 1].subtractHitPoints(2);
+		_charPowSprites.draw(screen._windows[0], 0,
+			Common::Point(CHAR_FACES_X[charNum2 - 1], 150));
+		screen._windows[0].update();
+	}
+
+	int cell = map.mazeLookup(Common::Point(pt.x + SCREEN_POSITIONING_X[direction][7],
+		pt.y + SCREEN_POSITIONING_Y[direction][7]), 0, 0xffff);
+	if (cell != INVALID_CELL) {
+		int v = map.getCell(2);
+
+		if (v == 7) {
+			++_wo[207];
+			++_wo[267];
+			++_wo[287];
+		} else if (v == 14) {
+			++_wo[267];
+			++_wo[287];
+		} else if (v == 15) {
+			++_wo[287];
+		} else {
+			int might = party._activeParty[charNum1 - 1].getStat(MIGHT) +
+				_vm->getRandomNumber(1, 30);
+			if (charNum2)
+				might += party._activeParty[charNum2 - 1].getStat(MIGHT);
+
+			int bashThreshold = (v == 9) ? map.mazeData()._difficulties._bashGrate :
+				map.mazeData()._difficulties._bashWall;
+			if (might >= bashThreshold) {
+				// Remove the wall on the current cell, and the reverse wall
+				// on the cell we're bashing through to
+				map.setWall(pt, direction, 3);
+				switch (direction) {
+				case DIR_NORTH:
+					map.setWall(Common::Point(pt.x, pt.y + 1), DIR_SOUTH, 3);
+					break;
+				case DIR_EAST:
+					map.setWall(Common::Point(pt.x + 1, pt.y), DIR_WEST, 3);
+					break;
+				case DIR_SOUTH:
+					map.setWall(Common::Point(pt.x, pt.y - 1), DIR_NORTH, 3);
+					break;
+				case DIR_WEST:
+					map.setWall(Common::Point(pt.x - 1, pt.y), DIR_EAST, 3);
+					break;
+				}
+			}
+		}
+	}
+
+	party.checkPartyDead();
+	events.ipause(2);
+	charIconsPrint(true);
+}
+
+
 } // End of namespace Xeen
diff --git a/engines/xeen/interface.h b/engines/xeen/interface.h
index cecc5c3..9d7cb5c 100644
--- a/engines/xeen/interface.h
+++ b/engines/xeen/interface.h
@@ -106,6 +106,8 @@ public:
 	void perform();
 
 	void rest();
+
+	void bash(const Common::Point &pt, Direction direction);
 };
 
 } // End of namespace Xeen
diff --git a/engines/xeen/interface_map.h b/engines/xeen/interface_map.h
index 197f239..034d1a6 100644
--- a/engines/xeen/interface_map.h
+++ b/engines/xeen/interface_map.h
@@ -96,7 +96,6 @@ private:
 	SpriteResource _spellFxSprites;
 	SpriteResource _fecpSprites;
 	SpriteResource _blessSprites;
-	SpriteResource _charPowSprites;
 	int _combatFloatCounter;
 
 	void initDrawStructs();
@@ -130,6 +129,7 @@ protected:
 public:
 	OutdoorDrawList _outdoorList;
 	IndoorDrawList _indoorList;
+	SpriteResource _charPowSprites;
 	SpriteResource _globalSprites;
 	bool _upDoorText;
 	Common::String _screenText;


Commit: ccb224d89ae4fcb889adc4e53062e90d9318851c
    https://github.com/scummvm/scummvm/commit/ccb224d89ae4fcb889adc4e53062e90d9318851c
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-02-08T16:03:13-05:00

Commit Message:
XEEN: In progress Dismiss dialog

Changed paths:
  A engines/xeen/dialogs_dismiss.cpp
  A engines/xeen/dialogs_dismiss.h
    engines/xeen/interface.cpp
    engines/xeen/interface.h
    engines/xeen/module.mk
    engines/xeen/resources.cpp
    engines/xeen/resources.h



diff --git a/engines/xeen/dialogs_dismiss.cpp b/engines/xeen/dialogs_dismiss.cpp
new file mode 100644
index 0000000..304c7a0
--- /dev/null
+++ b/engines/xeen/dialogs_dismiss.cpp
@@ -0,0 +1,99 @@
+/* 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 "xeen/dialogs_dismiss.h"
+#include "xeen/party.h"
+#include "xeen/resources.h"
+#include "xeen/xeen.h"
+
+namespace Xeen {
+
+void Dismiss::show(XeenEngine *vm) {
+	Dismiss *dlg = new Dismiss(vm);
+	dlg->execute();
+	delete dlg;
+}
+
+void Dismiss::execute() {
+	Screen &screen = *_vm->_screen;
+	EventsManager &events = *_vm->_events;
+	Interface &intf = *_vm->_interface;
+	Party &party = *_vm->_party;
+	loadButtons();
+
+	Window &w = screen._windows[31];
+	w.open();
+	_iconSprites.draw(w, 0, Common::Point(225, 120));
+	w.update();
+
+	while (!_vm->shouldQuit()) {
+		do {
+			events.updateGameCounter();
+			intf.draw3d(false);
+			w.frame();
+			w.writeString("\r");
+			_iconSprites.draw(w, 0, Common::Point(225, 120));
+			screen._windows[3].update();
+			w.update();
+
+			do {
+				events.pollEventsAndWait();
+				checkEvents(_vm);
+			} while (!_vm->shouldQuit() && !_buttonValue && events.timeElapsed() == 0);
+		} while (!_vm->shouldQuit() && !_buttonValue);
+
+		if (_buttonValue >= Common::KEYCODE_F1 && _buttonValue <= Common::KEYCODE_F6) {
+			_buttonValue -= Common::KEYCODE_F1;
+
+			if (_buttonValue < (int)party._activeParty.size()) {
+				if (party._activeParty.size() == 1) {
+					w.close();
+					ErrorScroll::show(_vm, CANT_DISMISS_LAST_CHAR, WT_NONFREEZED_WAIT);
+					w.open();
+				} else {
+					Character tempChar = party._activeParty[_buttonValue];
+					int charIndex = party._partyMembers[_buttonValue];
+					intf._partyFaces[_buttonValue] = 0;
+
+					intf.sortFaces();
+//					party.sortParty();
+
+					// TODO
+				}
+				break;
+			}
+		} else if (_buttonValue == Common::KEYCODE_ESCAPE) {
+			
+		}
+	}
+}
+
+void Dismiss::loadButtons() {
+	_iconSprites.load("esc.icn");
+	addButton(Common::Rect(225, 120, 249, 140), Common::KEYCODE_ESCAPE, &_iconSprites);
+	addButton(Common::Rect(16, 16, 48, 48), Common::KEYCODE_1, &_iconSprites, false);
+	addButton(Common::Rect(117, 16, 149, 48), Common::KEYCODE_2, &_iconSprites, false);
+	addButton(Common::Rect(16, 59, 48, 91), Common::KEYCODE_3, &_iconSprites, false);
+	addButton(Common::Rect(117, 59, 149, 91), Common::KEYCODE_4, &_iconSprites, false);
+}
+
+} // End of namespace Xeen
diff --git a/engines/xeen/dialogs_dismiss.h b/engines/xeen/dialogs_dismiss.h
new file mode 100644
index 0000000..ec40e87
--- /dev/null
+++ b/engines/xeen/dialogs_dismiss.h
@@ -0,0 +1,47 @@
+/* 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_DISMISS_H
+#define XEEN_DIALOGS_DISMISS_H
+
+#include "xeen/dialogs.h"
+#include "xeen/party.h"
+
+namespace Xeen {
+
+class Dismiss : public ButtonContainer {
+private:
+	XeenEngine *_vm;
+	SpriteResource _iconSprites;
+
+	Dismiss(XeenEngine *vm) : ButtonContainer(), _vm(vm) {}
+
+	void execute();
+
+	void loadButtons();
+public:
+	static void show(XeenEngine *vm);
+};
+
+} // End of namespace Xeen
+
+#endif /* XEEN_DIALOGS_DISMISS_H */
diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp
index 0d734aa..b51801f 100644
--- a/engines/xeen/interface.cpp
+++ b/engines/xeen/interface.cpp
@@ -385,6 +385,23 @@ void Interface::charIconsPrint(bool updateFlag) {
 		screen._windows[33].update();
 }
 
+/**
+ * Removes any empty character entries from the faces list
+ */
+void Interface::sortFaces() {
+	for (uint charIdx = 0; charIdx < MAX_ACTIVE_PARTY; ++charIdx) {
+		if (!_partyFaces[charIdx]) {
+			for (uint charIdx2 = charIdx + 1; charIdx2 < 8; ++charIdx2) {
+				if (_partyFaces[charIdx2]) {
+					_partyFaces[charIdx] = _partyFaces[charIdx2];
+					_partyFaces[charIdx2] = 0;
+					break;
+				}
+			}
+		}
+	}
+}
+
 void Interface::drawViewBackground(int bgType) {
 	if (bgType >= 4)
 		return;
diff --git a/engines/xeen/interface.h b/engines/xeen/interface.h
index 9d7cb5c..0f5ca18 100644
--- a/engines/xeen/interface.h
+++ b/engines/xeen/interface.h
@@ -97,6 +97,8 @@ public:
 
 	void charIconsPrint(bool updateFlag);
 
+	void sortFaces();
+
 	void doFalling();
 
 	void highlightChar(int charId);
diff --git a/engines/xeen/module.mk b/engines/xeen/module.mk
index 8c526b4..50d7891 100644
--- a/engines/xeen/module.mk
+++ b/engines/xeen/module.mk
@@ -12,6 +12,7 @@ MODULE_OBJS := \
 	automap.o \
 	dialogs_automap.o \
 	dialogs_char_info.o \
+	dialogs_dismiss.o \
 	dialogs_error.o \
 	dialogs_exchange.o \
 	dialogs_options.o \
diff --git a/engines/xeen/resources.cpp b/engines/xeen/resources.cpp
index d127ddc..11b2092 100644
--- a/engines/xeen/resources.cpp
+++ b/engines/xeen/resources.cpp
@@ -1432,4 +1432,6 @@ const char *const HIT_SPELL_POINTS_RESTORED = "Hit Pts and Spell Pts restored.";
 const char *const TOO_DANGEROUS_TO_REST = "Too dangerous to rest here!";
 const char *const SOME_CHARS_MAY_DIE = "Some Chars may die. Rest anyway?";
 
+const char *const CANT_DISMISS_LAST_CHAR = "You cannot dismiss your last character!";
+
 } // End of namespace Xeen
diff --git a/engines/xeen/resources.h b/engines/xeen/resources.h
index 517d6e4..f7609bc 100644
--- a/engines/xeen/resources.h
+++ b/engines/xeen/resources.h
@@ -492,6 +492,8 @@ extern const char *const HIT_SPELL_POINTS_RESTORED;
 extern const char *const TOO_DANGEROUS_TO_REST;
 extern const char *const SOME_CHARS_MAY_DIE;
 
+extern const char *const CANT_DISMISS_LAST_CHAR;
+
 } // End of namespace Xeen
 
 #endif	/* XEEN_RESOURCES_H */


Commit: 62eb39515b0f19a52861e9dd0fb4ac6af8c1c2ba
    https://github.com/scummvm/scummvm/commit/62eb39515b0f19a52861e9dd0fb4ac6af8c1c2ba
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-02-09T20:57:19-05:00

Commit Message:
XEEN: Some refactoring needed for resources the party dialog will need

Changed paths:
  A engines/xeen/dialogs_party.cpp
  A engines/xeen/dialogs_party.h
    engines/xeen/events.cpp
    engines/xeen/events.h
    engines/xeen/interface.cpp
    engines/xeen/interface.h
    engines/xeen/module.mk
    engines/xeen/resources.cpp
    engines/xeen/resources.h
    engines/xeen/scripts.cpp
    engines/xeen/scripts.h
    engines/xeen/town.cpp
    engines/xeen/xeen.cpp
    engines/xeen/xeen.h



diff --git a/engines/xeen/dialogs_party.cpp b/engines/xeen/dialogs_party.cpp
new file mode 100644
index 0000000..510cd65
--- /dev/null
+++ b/engines/xeen/dialogs_party.cpp
@@ -0,0 +1,153 @@
+/* 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_party.h"
+#include "xeen/character.h"
+#include "xeen/events.h"
+#include "xeen/party.h"
+#include "xeen/xeen.h"
+
+namespace Xeen {
+
+	void PartyDialog::show(XeenEngine *vm) {
+	PartyDialog *dlg = new PartyDialog(vm);
+	dlg->execute();
+	delete dlg;
+}
+
+void PartyDialog::execute() {
+	EventsManager &events = *_vm->_events;
+	Map &map = *_vm->_map;
+	Screen &screen = *_vm->_screen;
+
+	loadButtons();
+	setupBackground();
+
+	_vm->_mode = MODE_1;
+	Common::Array<int> xeenSideChars;
+
+	// Build up a list of characters on the same Xeen side being loaded
+	for (int i = 0; i < XEEN_TOTAL_CHARACTERS; ++i) {
+		Character &player = _vm->_roster[i];
+		if (player._name.empty() || player._xeenSide != (map._loadDarkSide ? 1 : 0))
+			continue;
+
+		xeenSideChars.push_back(i);
+	}
+
+	Window &w = screen._windows[11];
+	w.open();
+	setupFaces(0, xeenSideChars, false);
+	w.writeString(_displayText);
+	w.drawList(&_faceDrawStructs[0], 4);
+
+	_iconSprites.draw(w, 0, Common::Point(16, 100));
+	_iconSprites.draw(w, 2, Common::Point(52, 100));
+	_iconSprites.draw(w, 4, Common::Point(87, 100));
+	_iconSprites.draw(w, 6, Common::Point(122, 100));
+	_iconSprites.draw(w, 8, Common::Point(157, 100));
+	_iconSprites.draw(w, 10, Common::Point(192, 100));
+
+	screen.loadPalette("mm4.pal");
+	// TODO
+}
+
+void PartyDialog::loadButtons() {
+	_iconSprites.load("inn.icn");
+	addButton(Common::Rect(16, 100, 40, 120), Common::KEYCODE_UP, &_iconSprites);
+	addButton(Common::Rect(52, 100, 76, 120), Common::KEYCODE_DOWN, &_iconSprites);
+	addButton(Common::Rect(87, 100, 111, 120), Common::KEYCODE_d, &_iconSprites);
+	addButton(Common::Rect(122, 100, 146, 120), Common::KEYCODE_r, &_iconSprites);
+	addButton(Common::Rect(157, 100, 181, 120), Common::KEYCODE_c, &_iconSprites);
+	addButton(Common::Rect(192, 100, 116, 120), Common::KEYCODE_x, &_iconSprites);
+	addButton(Common::Rect(0, 0, 0, 0), Common::KEYCODE_ESCAPE, &_iconSprites, false);
+	addButton(Common::Rect(16, 16, 48, 48), Common::KEYCODE_1, &_iconSprites, false);
+	addButton(Common::Rect(117, 16, 149, 48), Common::KEYCODE_2, &_iconSprites, false);
+	addButton(Common::Rect(59, 59, 91, 91), Common::KEYCODE_3, &_iconSprites, false);
+	addButton(Common::Rect(117, 59, 151, 91), Common::KEYCODE_4, &_iconSprites, false);
+}
+
+void PartyDialog::initDrawStructs() {
+	_faceDrawStructs[0] = DrawStruct(0, 0, 0);
+	_faceDrawStructs[1] = DrawStruct(0, 101, 0);
+	_faceDrawStructs[2] = DrawStruct(0, 0, 43);
+	_faceDrawStructs[3] = DrawStruct(0, 101, 43);
+}
+
+void PartyDialog::setupBackground() {
+	_vm->_screen->loadBackground("back.raw");
+	_vm->_interface->assembleBorder();
+}
+
+/**
+ * Sets up the faces for display in the party dialog
+ */
+void PartyDialog::setupFaces(int charIndex, Common::Array<int> xeenSideChars, bool updateFlag) {
+	Resources &res = *_vm->_resources;
+	Common::String charNames[4];
+	Common::String charRaces[4];
+	Common::String charSex[4];
+	Common::String charClasses[4];
+	int posIndex;
+	int charId;
+
+	for (posIndex = 0; posIndex < 4; ++posIndex) {
+		charId = xeenSideChars[charIndex];
+		bool isInParty = _vm->_party->isInParty(charId);
+
+		if (charId == 0xff) {
+			while ((int)_buttons.size() >(7 + posIndex))
+				_buttons.remove_at(_buttons.size() - 1);
+			break;
+		}
+
+		Common::Rect &b = _buttons[7 + posIndex]._bounds;
+		b.moveTo((posIndex & 1) ? 117 : 16, b.top);
+		Character &ps = _vm->_roster[xeenSideChars[charIndex + posIndex]];
+		charNames[posIndex] = isInParty ? IN_PARTY : ps._name;
+		charRaces[posIndex] = RACE_NAMES[ps._race];
+		charSex[posIndex] = SEX_NAMES[ps._sex];
+		charClasses[posIndex] = CLASS_NAMES[ps._class];
+	}
+
+	charIconsPrint(updateFlag);
+
+	// Set up the sprite set to use for each face
+	charId = xeenSideChars[charIndex];
+	_faceDrawStructs[0]._sprites = (charId == 0xff) ? (SpriteResource *)nullptr : &res._charFaces[charId];
+	charId = xeenSideChars[charIndex + 1];
+	_faceDrawStructs[1]._sprites = (charId == 0xff) ? (SpriteResource *)nullptr : &res._charFaces[charId];
+	charId = xeenSideChars[charIndex + 2];
+	_faceDrawStructs[2]._sprites = (charId == 0xff) ? (SpriteResource *)nullptr : &res._charFaces[charId];
+	charId = xeenSideChars[charIndex + 3];
+	_faceDrawStructs[3]._sprites = (charId == 0xff) ? (SpriteResource *)nullptr : &res._charFaces[charId];
+
+	_displayText = Common::String::format(PARTY_DETAILS,
+		charNames[0].c_str(), charRaces[0].c_str(), charSex[0].c_str(), charClasses[0].c_str(),
+		charNames[1].c_str(), charRaces[1].c_str(), charSex[1].c_str(), charClasses[1].c_str(),
+		charNames[2].c_str(), charRaces[2].c_str(), charSex[2].c_str(), charClasses[2].c_str(),
+		charNames[3].c_str(), charRaces[3].c_str(), charSex[3].c_str(), charClasses[3].c_str()
+		);
+}
+
+} // End of namespace Xeen
diff --git a/engines/xeen/dialogs_party.h b/engines/xeen/dialogs_party.h
new file mode 100644
index 0000000..c2768e9
--- /dev/null
+++ b/engines/xeen/dialogs_party.h
@@ -0,0 +1,58 @@
+/* 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_PARTY_H
+#define XEEN_DIALOGS_PARTY_H
+
+#include "xeen/dialogs.h"
+#include "xeen/screen.h"
+#include "xeen/sprites.h"
+
+namespace Xeen {
+
+class PartyDialog : public ButtonContainer {
+private:
+	XeenEngine *_vm;
+	SpriteResource _iconSprites;
+	DrawStruct _faceDrawStructs[4];
+	Common::String _displayText;
+
+	PartyDialog(XeenEngine *vm) : ButtonContainer(), _vm(vm) {}
+
+	void execute();
+
+	void loadButtons();
+
+	void initDrawStructs();
+
+	void setupBackground();
+
+	void charIconsPrint(bool updateFlag);
+
+	void setupFaces(int charIndex, Common::Array<int> xeenSideChars, bool updateFlag);
+public:
+	static void show(XeenEngine *vm);
+};
+
+} // End of namespace Xeen
+
+#endif /* XEEN_DIALOGS_PARTY_H */
diff --git a/engines/xeen/events.cpp b/engines/xeen/events.cpp
index 89a1ac3..9f13861 100644
--- a/engines/xeen/events.cpp
+++ b/engines/xeen/events.cpp
@@ -168,7 +168,7 @@ bool EventsManager::wait(uint numFrames, bool interruptable) {
 	return false;
 }
 
-void EventsManager::ipause(int amount) {
+void EventsManager::ipause(uint amount) {
 	updateGameCounter();
 	do {
 		_vm->_interface->draw3d(true);
diff --git a/engines/xeen/events.h b/engines/xeen/events.h
index 5d6918b..cce3155 100644
--- a/engines/xeen/events.h
+++ b/engines/xeen/events.h
@@ -91,7 +91,7 @@ public:
 
 	bool wait(uint numFrames, bool interruptable = false);
 
-	void ipause(int amount);
+	void ipause(uint amount);
 };
 
 class GameEvent {
diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp
index b51801f..a88217e 100644
--- a/engines/xeen/interface.cpp
+++ b/engines/xeen/interface.cpp
@@ -46,11 +46,6 @@ Interface::Interface(XeenEngine *vm) : ButtonContainer(), InterfaceMap(vm), _vm(
 
 
 void Interface::initDrawStructs() {
-	_faceDrawStructs[0] = DrawStruct(0, 0, 0);
-	_faceDrawStructs[1] = DrawStruct(0, 101, 0);
-	_faceDrawStructs[2] = DrawStruct(0, 0, 43);
-	_faceDrawStructs[3] = DrawStruct(0, 101, 43);
-
 	_mainList[0] = DrawStruct(7, 232, 74);
 	_mainList[1] = DrawStruct(0, 235, 75);
 	_mainList[2] = DrawStruct(2, 260, 75);
@@ -85,70 +80,8 @@ void Interface::setup() {
 }
 
 void Interface::manageCharacters(bool soundPlayed) {
-	EventsManager &events = *_vm->_events;
-	Map &map = *_vm->_map;
-	Screen &screen = *_vm->_screen;
-	bool flag = false;
-
-start:
-	if (_vm->_party->_mazeId != 0) {
-		_vm->_mode = MODE_0;
-		_buttonsLoaded = true;
-	} else {
-		if (!soundPlayed) {
-			warning("TODO: loadSound?");
-		}
-
-		if (!_partyFaces[0]) {
-			// Xeen only uses 24 of possible 30 character slots
-			loadCharIcons();
-
-			for (int i = 0; i < _vm->_party->_partyCount; ++i)
-				_partyFaces[i] = &_charFaces[_vm->_party->_partyMembers[i]];
-		}
-
-		_vm->_mode = MODE_1;
-		Common::Array<int> xeenSideChars;
-
-		// Build up a list of characters on the same Xeen side being loaded
-		for (int i = 0; i < XEEN_TOTAL_CHARACTERS; ++i) {
-			Character &player = _vm->_roster[i];
-			if (player._name.empty() || player._xeenSide != (map._loadDarkSide ? 1 : 0))
-				continue;
-
-			xeenSideChars.push_back(i);
-		}
-
-		// 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);
-
-		setupBackground();
-		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();
@@ -264,76 +197,23 @@ start:
 
 	for (int i = 0; i < TOTAL_CHARACTERS; ++i)
 		_charFaces[i].clear();
+		*/
 }
 
 void Interface::loadCharIcons() {
-	for (int i = 0; i < XEEN_TOTAL_CHARACTERS; ++i) {
-		// Load new character resource
-		Common::String name = Common::String::format("char%02d.fac", i + 1);
-		_charFaces[i].load(name);
-	}
-
 	_dseFace.load("dse.fac");
 }
 
 void Interface::loadPartyIcons() {
-	for (int i = 0; i < _vm->_party->_partyCount; ++i)
-		_partyFaces[i] = &_charFaces[_vm->_party->_partyMembers[i]];
-}
-
-void Interface::setupBackground() {
-	_vm->_screen->loadBackground("back.raw");
-	assembleBorder();
-}
-
-void Interface::setupFaces(int charIndex, Common::Array<int> xeenSideChars, bool updateFlag) {
-	Common::String playerNames[4];
-	Common::String playerRaces[4];
-	Common::String playerSex[4];
-	Common::String playerClass[4];
-	int posIndex;
-	int charId;
-
-	for (posIndex = 0; posIndex < 4; ++posIndex) {
-		charId = xeenSideChars[charIndex];
-		bool isInParty = _vm->_party->isInParty(charId);
-
-		if (charId == 0xff) {
-			while ((int)_buttons.size() > (7 + posIndex))
-				_buttons.remove_at(_buttons.size() - 1);
-			break;
-		}
-
-		Common::Rect &b = _buttons[7 + posIndex]._bounds;
-		b.moveTo((posIndex & 1) ? 117 : 16, b.top);
-		Character &ps = _vm->_roster[xeenSideChars[charIndex + posIndex]];
-		playerNames[posIndex] = isInParty ? IN_PARTY : ps._name;
-		playerRaces[posIndex] = RACE_NAMES[ps._race];
-		playerSex[posIndex] = SEX_NAMES[ps._sex];
-		playerClass[posIndex] = CLASS_NAMES[ps._class];
-	}
+	Party &party = *_vm->_party;
+	Resources &res = *_vm->_resources;
 
-	charIconsPrint(updateFlag);
-
-	// Set up the sprite set to use for each face
-	charId = xeenSideChars[charIndex];
-	_faceDrawStructs[0]._sprites = (charId == 0xff) ? (SpriteResource *)nullptr : &_charFaces[charId];
-	charId = xeenSideChars[charIndex + 1];
-	_faceDrawStructs[1]._sprites = (charId == 0xff) ? (SpriteResource *)nullptr : &_charFaces[charId];
-	charId = xeenSideChars[charIndex + 2];
-	_faceDrawStructs[2]._sprites = (charId == 0xff) ? (SpriteResource *)nullptr : &_charFaces[charId];
-	charId = xeenSideChars[charIndex + 3];
-	_faceDrawStructs[3]._sprites = (charId == 0xff) ? (SpriteResource *)nullptr : &_charFaces[charId];
-
-	_interfaceText = Common::String::format(PARTY_DETAILS,
-		playerNames[0].c_str(), playerRaces[0].c_str(), playerSex[0].c_str(), playerClass[0].c_str(),
-		playerNames[1].c_str(), playerRaces[1].c_str(), playerSex[1].c_str(), playerClass[1].c_str(),
-		playerNames[2].c_str(), playerRaces[2].c_str(), playerSex[2].c_str(), playerClass[2].c_str(),
-		playerNames[3].c_str(), playerRaces[3].c_str(), playerSex[3].c_str(), playerClass[3].c_str()
-	);
+	for (int i = 0; i < party._partyCount; ++i)
+		_partyFaces[i] = &res._charFaces[_vm->_party->_partyMembers[i]];
 }
 
 void Interface::charIconsPrint(bool updateFlag) {
+	Resources &res = *_vm->_resources;
 	Screen &screen = *_vm->_screen;
 	bool stateFlag = _vm->_mode == MODE_COMBAT;
 	_restoreSprites.draw(screen, 0, Common::Point(8, 149));
@@ -346,8 +226,7 @@ void Interface::charIconsPrint(bool updateFlag) {
 		Condition charCondition = ps.worstCondition();
 		int charFrame = FACE_CONDITION_FRAMES[charCondition];
 		
-		SpriteResource *sprites = (charFrame > 4 && !_charFaces[0].empty()) ?
-			&_dseFace : _partyFaces[charIndex];
+		SpriteResource *sprites = (charFrame > 4) ? &_dseFace : _partyFaces[charIndex];
 		if (charFrame > 4)
 			charFrame -= 5;
 
diff --git a/engines/xeen/interface.h b/engines/xeen/interface.h
index 0f5ca18..9ab9102 100644
--- a/engines/xeen/interface.h
+++ b/engines/xeen/interface.h
@@ -44,8 +44,6 @@ private:
 	SpriteResource _hpSprites;
 	SpriteResource _uiSprites;
 	SpriteResource _iconSprites;
-	SpriteResource _charFaces[TOTAL_CHARACTERS];
-	DrawStruct _faceDrawStructs[4];
 	DrawStruct _mainList[16];
 	int _combatCharIds[8];
 
@@ -59,8 +57,6 @@ private:
 
 	void setupBackground();
 
-	void setupFaces(int charIndex, Common::Array<int> xeenSideChars, bool updateFlag);
-
 	void drawViewBackground(int bgType);
 
 	void moveCharacterToRoster();
diff --git a/engines/xeen/module.mk b/engines/xeen/module.mk
index 50d7891..083abb9 100644
--- a/engines/xeen/module.mk
+++ b/engines/xeen/module.mk
@@ -19,6 +19,7 @@ MODULE_OBJS := \
 	dialogs_info.o \
 	dialogs_input.o \
 	dialogs_items.o \
+	dialogs_party.o \
 	dialogs_query.o \
 	dialogs_quests.o \
 	dialogs_quick_ref.o \
diff --git a/engines/xeen/resources.cpp b/engines/xeen/resources.cpp
index 11b2092..7067886 100644
--- a/engines/xeen/resources.cpp
+++ b/engines/xeen/resources.cpp
@@ -31,6 +31,12 @@ Resources::Resources() {
 	while (f.pos() < f.size())
 		_maeNames.push_back(f.readString());
 	f.close();
+
+	for (int i = 0; i < XEEN_TOTAL_CHARACTERS; ++i) {
+		// Load new character resource
+		Common::String name = Common::String::format("char%02d.fac", i + 1);
+		_charFaces[i].load(name);
+	}
 }
 
 /*------------------------------------------------------------------------*/
diff --git a/engines/xeen/resources.h b/engines/xeen/resources.h
index f7609bc..dd3a775 100644
--- a/engines/xeen/resources.h
+++ b/engines/xeen/resources.h
@@ -26,6 +26,7 @@
 #include "common/scummsys.h"
 #include "common/str-array.h"
 #include "gui/debugger.h"
+#include "xeen/party.h"
 #include "xeen/spells.h"
 
 namespace Xeen {
@@ -34,6 +35,7 @@ class Resources {
 public:
 	// Magic and equipment names
 	Common::StringArray _maeNames;
+	SpriteResource _charFaces[TOTAL_CHARACTERS];
 public:
 	Resources();
 };
diff --git a/engines/xeen/scripts.cpp b/engines/xeen/scripts.cpp
index 4859e93..3837509 100644
--- a/engines/xeen/scripts.cpp
+++ b/engines/xeen/scripts.cpp
@@ -107,7 +107,7 @@ Scripts::Scripts(XeenEngine *vm) : _vm(vm) {
 	_var50 = false;
 }
 
-bool Scripts::checkEvents() {
+int Scripts::checkEvents() {
 	Combat &combat = *_vm->_combat;
 	EventsManager &events = *_vm->_events;
 	Interface &intf = *_vm->_interface;
diff --git a/engines/xeen/scripts.h b/engines/xeen/scripts.h
index d51cd0c..d353581 100644
--- a/engines/xeen/scripts.h
+++ b/engines/xeen/scripts.h
@@ -233,7 +233,7 @@ public:
 public:
 	Scripts(XeenEngine *vm);
 
-	bool checkEvents();
+	int checkEvents();
 
 	void giveTreasure();
 
diff --git a/engines/xeen/town.cpp b/engines/xeen/town.cpp
index 3a07d2a..c12973c 100644
--- a/engines/xeen/town.cpp
+++ b/engines/xeen/town.cpp
@@ -630,6 +630,7 @@ Character *Town::doTavernOptions(Character *c) {
 		}
 		break;
 	case Common::KEYCODE_f: {
+		// Food
 		if (party._mazeId == (isDarkCc ? 29 : 28)) {
 			_v22 = party._partyCount * 15;
 			_v23 = 10;
@@ -680,6 +681,7 @@ Character *Town::doTavernOptions(Character *c) {
 	}
 
 	case Common::KEYCODE_r: {
+		// Rumors
 		if (party._mazeId == (isDarkCc ? 29 : 28)) {
 			idx = 0;
 		} else if (party._mazeId == (isDarkCc ? 31 : 30)) {
@@ -701,8 +703,7 @@ Character *Town::doTavernOptions(Character *c) {
 	}
 
 	case Common::KEYCODE_s: {
-		// Save game
-		// TODO: This needs to be fit in better with ScummVM framework
+		// Sign In
 		int idx = isDarkCc ? (party._mazeId - 29) >> 1 : party._mazeId - 28;
 		assert(idx >= 0);
 		party._mazePosition.x = TAVERN_EXIT_LIST[isDarkCc ? 1 : 0][_townActionId][idx][0];
@@ -723,7 +724,7 @@ Character *Town::doTavernOptions(Character *c) {
 
 		party.addTime(1440);
 		party._mazeId = 0;
-		_vm->quitGame();
+		_vm->_quitMode = 2;
 		break;
 	}
 
diff --git a/engines/xeen/xeen.cpp b/engines/xeen/xeen.cpp
index d34e8ed..ed94426 100644
--- a/engines/xeen/xeen.cpp
+++ b/engines/xeen/xeen.cpp
@@ -51,6 +51,7 @@ XeenEngine::XeenEngine(OSystem *syst, const XeenGameDescription *gameDesc)
 	_spells = nullptr;
 	_town = nullptr;
 	_eventData = nullptr;
+	_quitMode = 0;
 	_dangerSenseAllowed = false;
 	_noDirectionSense = false;
 	_moveMonsters = false;
@@ -289,6 +290,7 @@ void XeenEngine::playGame() {
  */
 void XeenEngine::play() {
 	// TODO: Init variables
+	_quitMode = 0;
 
 	_interface->setup();
 	_screen->loadBackground("back.raw");
@@ -331,8 +333,8 @@ void XeenEngine::gameLoop() {
 	while (!shouldQuit()) {
 		_map->cellFlagLookup(_party->_mazePosition);
 		if (_map->_currentIsEvent) {
-			_scripts->checkEvents();
-			if (shouldQuit())
+			_quitMode = _scripts->checkEvents();
+			if (shouldQuit() || _quitMode)
 				return;
 		}
 		_scripts->giveTreasure();
diff --git a/engines/xeen/xeen.h b/engines/xeen/xeen.h
index 537768e..4664998 100644
--- a/engines/xeen/xeen.h
+++ b/engines/xeen/xeen.h
@@ -153,6 +153,7 @@ public:
 	GameEvent _gameEvent;
 	Common::SeekableReadStream *_eventData;
 	Roster _roster;
+	int _quitMode;
 	bool _dangerSenseAllowed;
 	bool _noDirectionSense;
 	bool _moveMonsters;


Commit: c798a555105c58f82d373b92b479a577d4215cb9
    https://github.com/scummvm/scummvm/commit/c798a555105c58f82d373b92b479a577d4215cb9
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-02-09T21:34:03-05:00

Commit Message:
XEEN: More refactoring needed for party dialog setup

Changed paths:
    engines/xeen/dialogs_party.cpp
    engines/xeen/interface.cpp
    engines/xeen/interface.h
    engines/xeen/party.cpp
    engines/xeen/party.h
    engines/xeen/saves.cpp
    engines/xeen/saves.h
    engines/xeen/xeen.cpp
    engines/xeen/xeen.h



diff --git a/engines/xeen/dialogs_party.cpp b/engines/xeen/dialogs_party.cpp
index 510cd65..aa8d58f 100644
--- a/engines/xeen/dialogs_party.cpp
+++ b/engines/xeen/dialogs_party.cpp
@@ -38,38 +38,161 @@ namespace Xeen {
 void PartyDialog::execute() {
 	EventsManager &events = *_vm->_events;
 	Map &map = *_vm->_map;
+	Party &party = *_vm->_party;
 	Screen &screen = *_vm->_screen;
 
 	loadButtons();
 	setupBackground();
 
-	_vm->_mode = MODE_1;
-	Common::Array<int> xeenSideChars;
+	while (!_vm->shouldQuit()) {
+		_vm->_mode = MODE_1;
+		Common::Array<int> xeenSideChars;
 
-	// Build up a list of characters on the same Xeen side being loaded
-	for (int i = 0; i < XEEN_TOTAL_CHARACTERS; ++i) {
-		Character &player = _vm->_roster[i];
-		if (player._name.empty() || player._xeenSide != (map._loadDarkSide ? 1 : 0))
-			continue;
+		party.loadActiveParty();
 
-		xeenSideChars.push_back(i);
+		// Build up a list of characters on the same Xeen side being loaded
+		for (int i = 0; i < XEEN_TOTAL_CHARACTERS; ++i) {
+			Character &player = party._roster[i];
+			if (player._name.empty() || player._xeenSide != (map._loadDarkSide ? 1 : 0))
+				continue;
+
+			xeenSideChars.push_back(i);
+		}
+
+		Window &w = screen._windows[11];
+		w.open();
+		setupFaces(0, xeenSideChars, false);
+		w.writeString(_displayText);
+		w.drawList(&_faceDrawStructs[0], 4);
+
+		_iconSprites.draw(w, 0, Common::Point(16, 100));
+		_iconSprites.draw(w, 2, Common::Point(52, 100));
+		_iconSprites.draw(w, 4, Common::Point(87, 100));
+		_iconSprites.draw(w, 6, Common::Point(122, 100));
+		_iconSprites.draw(w, 8, Common::Point(157, 100));
+		_iconSprites.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();
+					moveCharacterToRoster();
+					_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;
+			}
+		}
 	}
 
-	Window &w = screen._windows[11];
-	w.open();
-	setupFaces(0, xeenSideChars, false);
-	w.writeString(_displayText);
-	w.drawList(&_faceDrawStructs[0], 4);
-
-	_iconSprites.draw(w, 0, Common::Point(16, 100));
-	_iconSprites.draw(w, 2, Common::Point(52, 100));
-	_iconSprites.draw(w, 4, Common::Point(87, 100));
-	_iconSprites.draw(w, 6, Common::Point(122, 100));
-	_iconSprites.draw(w, 8, Common::Point(157, 100));
-	_iconSprites.draw(w, 10, Common::Point(192, 100));
-
-	screen.loadPalette("mm4.pal");
-	// TODO
+	for (int i = 0; i < TOTAL_CHARACTERS; ++i)
+		_charFaces[i].clear();
+		*/
+		// TODO
+	}
 }
 
 void PartyDialog::loadButtons() {
@@ -103,6 +226,7 @@ void PartyDialog::setupBackground() {
  * Sets up the faces for display in the party dialog
  */
 void PartyDialog::setupFaces(int charIndex, Common::Array<int> xeenSideChars, bool updateFlag) {
+	Party &party = *_vm->_party;
 	Resources &res = *_vm->_resources;
 	Common::String charNames[4];
 	Common::String charRaces[4];
@@ -123,7 +247,7 @@ void PartyDialog::setupFaces(int charIndex, Common::Array<int> xeenSideChars, bo
 
 		Common::Rect &b = _buttons[7 + posIndex]._bounds;
 		b.moveTo((posIndex & 1) ? 117 : 16, b.top);
-		Character &ps = _vm->_roster[xeenSideChars[charIndex + posIndex]];
+		Character &ps = party._roster[xeenSideChars[charIndex + posIndex]];
 		charNames[posIndex] = isInParty ? IN_PARTY : ps._name;
 		charRaces[posIndex] = RACE_NAMES[ps._race];
 		charSex[posIndex] = SEX_NAMES[ps._sex];
diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp
index a88217e..8aa938b 100644
--- a/engines/xeen/interface.cpp
+++ b/engines/xeen/interface.cpp
@@ -69,139 +69,11 @@ void Interface::setup() {
 	_restoreSprites.load("restorex.icn");
 	_hpSprites.load("hpbars.icn");
 	_uiSprites.load("inn.icn");
-
-	// 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->_newDay = _vm->_party->_minutes >= 300;
-}
-
-void Interface::manageCharacters(bool soundPlayed) {
-	/*
-	
-
-		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();
-					moveCharacterToRoster();
-					_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();
-		*/
-}
-
-void Interface::loadCharIcons() {
 	_dseFace.load("dse.fac");
+
+	Party &party = *_vm->_party;
+	party.loadActiveParty();
+	party._newDay = party._minutes >= 300;
 }
 
 void Interface::loadPartyIcons() {
@@ -304,7 +176,6 @@ void Interface::moveCharacterToRoster() {
 
 void Interface::startup() {
 	Screen &screen = *_vm->_screen;
-	loadCharIcons();
 	_iconSprites.load("main.icn");
 
 	animate3d();
diff --git a/engines/xeen/interface.h b/engines/xeen/interface.h
index 9ab9102..cce2eaa 100644
--- a/engines/xeen/interface.h
+++ b/engines/xeen/interface.h
@@ -83,8 +83,6 @@ public:
 
 	void manageCharacters(bool soundPlayed);
 
-	void loadCharIcons();
-
 	void loadPartyIcons();
 
 	void startup();
diff --git a/engines/xeen/party.cpp b/engines/xeen/party.cpp
index ff59ed9..5cf5181 100644
--- a/engines/xeen/party.cpp
+++ b/engines/xeen/party.cpp
@@ -186,6 +186,13 @@ void Party::synchronize(Common::Serializer &s) {
 	s.syncBytes(&dummy[0], 30);
 }
 
+void Party::loadActiveParty() {
+	_activeParty.resize(_partyCount);
+	for (int i = 0; i < _partyCount; ++i) {
+		_activeParty[i] = _roster[_partyMembers[i]];
+	}
+}
+
 bool Party::checkSkill(Skill skillId) {
 	uint total = 0;
 	for (uint i = 0; i < _activeParty.size(); ++i) {
diff --git a/engines/xeen/party.h b/engines/xeen/party.h
index 5b7da05..1382969 100644
--- a/engines/xeen/party.h
+++ b/engines/xeen/party.h
@@ -113,6 +113,7 @@ public:
 	bool _characterFlags[30][24];
 public:
 	// Other party related runtime data
+	Roster _roster;
 	Common::Array<Character> _activeParty;
 	Common::Array<Character *> _combatParty;
 	int _combatPartyCount;
@@ -131,6 +132,8 @@ public:
 
 	void synchronize(Common::Serializer &s);
 
+	void loadActiveParty();
+
 	bool checkSkill(Skill skillId);
 
 	bool isInParty(int charId);
diff --git a/engines/xeen/saves.cpp b/engines/xeen/saves.cpp
index 85ab60b..61022a3 100644
--- a/engines/xeen/saves.cpp
+++ b/engines/xeen/saves.cpp
@@ -45,8 +45,8 @@ void OutFile::finalize() {
 
 /*------------------------------------------------------------------------*/
 
-SavesManager::SavesManager(XeenEngine *vm, Party &party, Roster &roster) : 
-		BaseCCArchive(), _vm(vm), _party(party), _roster(roster) {
+SavesManager::SavesManager(XeenEngine *vm, Party &party) : 
+		BaseCCArchive(), _vm(vm), _party(party) {
 	SearchMan.add("saves", this, 0, false);
 	_data = nullptr;
 	_wonWorld = false;
@@ -113,7 +113,7 @@ void SavesManager::load(Common::SeekableReadStream *stream) {
 	// Load in the character stats and active party
 	Common::SeekableReadStream *chr = createReadStreamForMember("maze.chr");
 	Common::Serializer sChr(chr, nullptr);
-	_roster.synchronize(sChr);
+	_party._roster.synchronize(sChr);
 	delete chr;
 
 	Common::SeekableReadStream *pty = createReadStreamForMember("maze.pty");
@@ -158,7 +158,7 @@ void SavesManager::reset() {
 
 	File fChar("maze.chr", gameCur);
 	Common::Serializer sChar(&fChar, nullptr);
-	_roster.synchronize(sChar);
+	_party._roster.synchronize(sChar);
 	fChar.close();
 }
 
diff --git a/engines/xeen/saves.h b/engines/xeen/saves.h
index 5d35518..8f112f6 100644
--- a/engines/xeen/saves.h
+++ b/engines/xeen/saves.h
@@ -59,7 +59,6 @@ class SavesManager: public BaseCCArchive {
 private:
 	XeenEngine *_vm;
 	Party &_party;
-	Roster &_roster;
 	byte *_data;
 	Common::HashMap<uint16, Common::MemoryWriteStreamDynamic > _newData;
 
@@ -70,7 +69,7 @@ public:
 	bool _wonWorld;
 	bool _wonDarkSide;
 public:
-	SavesManager(XeenEngine *vm, Party &party, Roster &roster);
+	SavesManager(XeenEngine *vm, Party &party);
 
 	~SavesManager();
 
diff --git a/engines/xeen/xeen.cpp b/engines/xeen/xeen.cpp
index ed94426..3c2b7a2 100644
--- a/engines/xeen/xeen.cpp
+++ b/engines/xeen/xeen.cpp
@@ -94,7 +94,7 @@ void XeenEngine::initialize() {
 	_interface = new Interface(this);
 	_map = new Map(this);
 	_party = new Party(this);
-	_saves = new SavesManager(this, *_party, _roster);
+	_saves = new SavesManager(this, *_party);
 	_screen = new Screen(this);
 	_scripts = new Scripts(this);
 	_screen->setupWindows();
diff --git a/engines/xeen/xeen.h b/engines/xeen/xeen.h
index 4664998..c4f826d 100644
--- a/engines/xeen/xeen.h
+++ b/engines/xeen/xeen.h
@@ -152,7 +152,6 @@ public:
 	Mode _mode;
 	GameEvent _gameEvent;
 	Common::SeekableReadStream *_eventData;
-	Roster _roster;
 	int _quitMode;
 	bool _dangerSenseAllowed;
 	bool _noDirectionSense;


Commit: a612dd686c27303bdbe6b2dba89aef79bc8db8e0
    https://github.com/scummvm/scummvm/commit/a612dd686c27303bdbe6b2dba89aef79bc8db8e0
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-02-09T22:01:01-05:00

Commit Message:
XEEN: Further refactoring for party dialog setup

Changed paths:
    engines/xeen/dialogs_party.cpp
    engines/xeen/interface.cpp
    engines/xeen/interface.h
    engines/xeen/party.cpp
    engines/xeen/party.h
    engines/xeen/screen.cpp
    engines/xeen/screen.h



diff --git a/engines/xeen/dialogs_party.cpp b/engines/xeen/dialogs_party.cpp
index aa8d58f..3da4a2a 100644
--- a/engines/xeen/dialogs_party.cpp
+++ b/engines/xeen/dialogs_party.cpp
@@ -40,6 +40,7 @@ void PartyDialog::execute() {
 	Map &map = *_vm->_map;
 	Party &party = *_vm->_party;
 	Screen &screen = *_vm->_screen;
+	bool modeFlag = false;
 
 	loadButtons();
 	setupBackground();
@@ -73,10 +74,7 @@ void PartyDialog::execute() {
 		_iconSprites.draw(w, 10, Common::Point(192, 100));
 		screen.loadPalette("mm4.pal");
 
-	/*
-
-
-		if (flag) {
+		if (modeFlag) {
 			screen._windows[0].update();
 			events.setCursor(0);
 			screen.fadeIn(4);
@@ -94,7 +92,6 @@ void PartyDialog::execute() {
 			}
 		}
 
-		// TODO
 		bool breakFlag = false;
 		while (!_vm->shouldQuit() && !breakFlag) {
 			events.pollEventsAndWait();
@@ -105,13 +102,13 @@ void PartyDialog::execute() {
 			case Common::KEYCODE_SPACE:
 			case Common::KEYCODE_e:
 			case Common::KEYCODE_x:
-				if (_vm->_party->_partyCount == 0) {
+				if (party._partyCount == 0) {
 					ErrorScroll::show(_vm, NO_ONE_TO_ADVENTURE_WITH);
 				} else {
 					if (_vm->_mode != MODE_0) {
-						for (_intrIndex1 = 4; _intrIndex1 >= 0; --_intrIndex1) {
+						for (int idx = 4; idx >= 0; --idx) {
 							events.updateGameCounter();
-							drawViewBackground(_intrIndex1);
+							screen.frameWindow(idx);
 							w.update();
 
 							while (events.timeElapsed() < 1)
@@ -120,10 +117,10 @@ void PartyDialog::execute() {
 					}
 
 					w.close();
-					_vm->_party->_realPartyCount = _vm->_party->_partyCount;
-					_vm->_party->_mazeId = _vm->_party->_priorMazeId;
+					party._realPartyCount = party._partyCount;
+					party._mazeId = party._priorMazeId;
 
-					_vm->_party->copyPartyToRoster(_vm->_roster);
+					party.copyPartyToRoster();
 					_vm->_saves->writeCharFile();
 					breakFlag = true;
 					break;
@@ -143,18 +140,17 @@ void PartyDialog::execute() {
 				} else {
 					screen.fadeOut(4);
 					w.close();
-					moveCharacterToRoster();
+					party.copyPartyToRoster();
 					_vm->_saves->writeCharFile();
 					screen.fadeOut(4);
-					flag = true;
-					_buttonsLoaded = true;
-					goto start;
+					modeFlag = true;
+					breakFlag = true;
 				}
 				break;
 			case Common::KEYCODE_d:
 				break;
 			case Common::KEYCODE_r:
-				if (_vm->_party->_partyCount > 0) {
+				if (party._partyCount > 0) {
 					// TODO
 				}
 				break;
@@ -187,12 +183,6 @@ void PartyDialog::execute() {
 			}
 		}
 	}
-
-	for (int i = 0; i < TOTAL_CHARACTERS; ++i)
-		_charFaces[i].clear();
-		*/
-		// TODO
-	}
 }
 
 void PartyDialog::loadButtons() {
@@ -237,7 +227,7 @@ void PartyDialog::setupFaces(int charIndex, Common::Array<int> xeenSideChars, bo
 
 	for (posIndex = 0; posIndex < 4; ++posIndex) {
 		charId = xeenSideChars[charIndex];
-		bool isInParty = _vm->_party->isInParty(charId);
+		bool isInParty = party.isInParty(charId);
 
 		if (charId == 0xff) {
 			while ((int)_buttons.size() >(7 + posIndex))
diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp
index 8aa938b..13a12f0 100644
--- a/engines/xeen/interface.cpp
+++ b/engines/xeen/interface.cpp
@@ -85,7 +85,6 @@ void Interface::loadPartyIcons() {
 }
 
 void Interface::charIconsPrint(bool updateFlag) {
-	Resources &res = *_vm->_resources;
 	Screen &screen = *_vm->_screen;
 	bool stateFlag = _vm->_mode == MODE_COMBAT;
 	_restoreSprites.draw(screen, 0, Common::Point(8, 149));
@@ -153,27 +152,6 @@ void Interface::sortFaces() {
 	}
 }
 
-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::moveCharacterToRoster() {
-	error("TODO");
-}
-
 void Interface::startup() {
 	Screen &screen = *_vm->_screen;
 	_iconSprites.load("main.icn");
diff --git a/engines/xeen/interface.h b/engines/xeen/interface.h
index cce2eaa..3d496aa 100644
--- a/engines/xeen/interface.h
+++ b/engines/xeen/interface.h
@@ -57,10 +57,6 @@ private:
 
 	void setupBackground();
 
-	void drawViewBackground(int bgType);
-
-	void moveCharacterToRoster();
-
 	void setMainButtons();
 
 	void chargeStep();
diff --git a/engines/xeen/party.cpp b/engines/xeen/party.cpp
index 5cf5181..6bff8fd 100644
--- a/engines/xeen/party.cpp
+++ b/engines/xeen/party.cpp
@@ -231,9 +231,9 @@ bool Party::isInParty(int charId) {
 	return false;
 }
 
-void Party::copyPartyToRoster(Roster &r) {
+void Party::copyPartyToRoster() {
 	for (int i = 0; i < _partyCount; ++i) {
-		r[_partyMembers[i]] = _activeParty[i];
+		_roster[_partyMembers[i]] = _activeParty[i];
 	}
 }
 
diff --git a/engines/xeen/party.h b/engines/xeen/party.h
index 1382969..c37a673 100644
--- a/engines/xeen/party.h
+++ b/engines/xeen/party.h
@@ -138,7 +138,7 @@ public:
 
 	bool isInParty(int charId);
 
-	void copyPartyToRoster(Roster &r);
+	void copyPartyToRoster();
 
 	void changeTime(int numMinutes);
 
diff --git a/engines/xeen/screen.cpp b/engines/xeen/screen.cpp
index bb2f356..3b3ea69 100644
--- a/engines/xeen/screen.cpp
+++ b/engines/xeen/screen.cpp
@@ -481,5 +481,21 @@ void Screen::restoreBackground(int slot) {
 	_savedScreens[slot - 1].blitTo(*this);
 }
 
+void Screen::frameWindow(uint 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];
+		}
+	}
+}
 
 } // End of namespace Xeen
diff --git a/engines/xeen/screen.h b/engines/xeen/screen.h
index e3ced06..526fd6f 100644
--- a/engines/xeen/screen.h
+++ b/engines/xeen/screen.h
@@ -156,6 +156,8 @@ public:
 	void saveBackground(int slot = 1);
 
 	void restoreBackground(int slot = 1);
+
+	void frameWindow(uint bgType);
 };
 
 } // End of namespace Xeen


Commit: 8256f7c8dfcdefe7da352fd36b42dc0931a111f8
    https://github.com/scummvm/scummvm/commit/8256f7c8dfcdefe7da352fd36b42dc0931a111f8
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-02-10T08:42:59-05:00

Commit Message:
XEEN: Refacored face sprites loading into Roster and Character classes

Changed paths:
    engines/xeen/character.cpp
    engines/xeen/character.h
    engines/xeen/dialogs_dismiss.cpp
    engines/xeen/dialogs_exchange.cpp
    engines/xeen/dialogs_party.cpp
    engines/xeen/dialogs_party.h
    engines/xeen/interface.cpp
    engines/xeen/interface.h
    engines/xeen/party.cpp
    engines/xeen/party.h
    engines/xeen/resources.cpp
    engines/xeen/resources.h
    engines/xeen/xeen.cpp



diff --git a/engines/xeen/character.cpp b/engines/xeen/character.cpp
index fb1447d..dc193f4 100644
--- a/engines/xeen/character.cpp
+++ b/engines/xeen/character.cpp
@@ -734,6 +734,8 @@ void Character::clear() {
 	_armor.clear();
 	_accessories.clear();
 	_misc.clear();
+
+	_faceSprites = nullptr;
 }
 
 void Character::synchronize(Common::Serializer &s) {
diff --git a/engines/xeen/character.h b/engines/xeen/character.h
index 7fc13f1..53dee33 100644
--- a/engines/xeen/character.h
+++ b/engines/xeen/character.h
@@ -28,6 +28,7 @@
 #include "common/rect.h"
 #include "common/serializer.h"
 #include "xeen/combat.h"
+#include "xeen/sprites.h"
 
 namespace Xeen {
 
@@ -257,6 +258,8 @@ public:
 	uint32 _experience;
 	int _currentAdventuringSpell;
 	int _currentCombatSpell;
+
+	SpriteResource *_faceSprites;
 public:
 	Character();
 
diff --git a/engines/xeen/dialogs_dismiss.cpp b/engines/xeen/dialogs_dismiss.cpp
index 304c7a0..c387c28 100644
--- a/engines/xeen/dialogs_dismiss.cpp
+++ b/engines/xeen/dialogs_dismiss.cpp
@@ -72,7 +72,6 @@ void Dismiss::execute() {
 				} else {
 					Character tempChar = party._activeParty[_buttonValue];
 					int charIndex = party._partyMembers[_buttonValue];
-					intf._partyFaces[_buttonValue] = 0;
 
 					intf.sortFaces();
 //					party.sortParty();
diff --git a/engines/xeen/dialogs_exchange.cpp b/engines/xeen/dialogs_exchange.cpp
index 56a310a..c6a4522 100644
--- a/engines/xeen/dialogs_exchange.cpp
+++ b/engines/xeen/dialogs_exchange.cpp
@@ -54,7 +54,6 @@ void ExchangeDialog::execute(Character *&c, int &charIndex) {
 			if (_buttonValue < party._partyCount) {
 				SWAP(party._activeParty[charIndex], party._activeParty[_buttonValue]);
 				SWAP(party._partyMembers[charIndex], party._partyMembers[_buttonValue]);
-				SWAP(intf._partyFaces[charIndex], intf._partyFaces[_buttonValue]);
 
 				charIndex = _buttonValue;
 				c = &party._activeParty[charIndex];
diff --git a/engines/xeen/dialogs_party.cpp b/engines/xeen/dialogs_party.cpp
index 3da4a2a..c8689f0 100644
--- a/engines/xeen/dialogs_party.cpp
+++ b/engines/xeen/dialogs_party.cpp
@@ -21,6 +21,7 @@
  */
 
 #include "common/scummsys.h"
+#include "xeen/dialogs_char_info.h"
 #include "xeen/dialogs_party.h"
 #include "xeen/character.h"
 #include "xeen/events.h"
@@ -41,6 +42,7 @@ void PartyDialog::execute() {
 	Party &party = *_vm->_party;
 	Screen &screen = *_vm->_screen;
 	bool modeFlag = false;
+	int startingChar = 0;
 
 	loadButtons();
 	setupBackground();
@@ -62,7 +64,7 @@ void PartyDialog::execute() {
 
 		Window &w = screen._windows[11];
 		w.open();
-		setupFaces(0, xeenSideChars, false);
+		setupFaces(startingChar, xeenSideChars, false);
 		w.writeString(_displayText);
 		w.drawList(&_faceDrawStructs[0], 4);
 
@@ -122,18 +124,30 @@ void PartyDialog::execute() {
 
 					party.copyPartyToRoster();
 					_vm->_saves->writeCharFile();
-					breakFlag = true;
-					break;
+					return;
 				}
 				break;
-			case Common::KEYCODE_1:
+
+			case Common::KEYCODE_F1:
+			case Common::KEYCODE_F2:
+			case Common::KEYCODE_F3:
+			case Common::KEYCODE_F4:
+			case Common::KEYCODE_F5:
+			case Common::KEYCODE_F6:
+				// Show character info
+				_buttonValue -= Common::KEYCODE_F1;
+				if (_buttonValue < party._partyCount)
+					CharacterInfo::show(_vm, _buttonValue);
 				break;
+
+			case Common::KEYCODE_1:
 			case Common::KEYCODE_2:
-				break;
 			case Common::KEYCODE_3:
-				break;
 			case Common::KEYCODE_4:
+				_buttonValue -= Common::KEYCODE_1 - 7;
+				// TODO
 				break;
+
 			case Common::KEYCODE_c:
 				if (xeenSideChars.size() == 24) {
 					ErrorScroll::show(_vm, YOUR_ROSTER_IS_FULL);
@@ -154,28 +168,17 @@ void PartyDialog::execute() {
 					// 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:
+
+			case Common::KEYCODE_UP:
+			case Common::KEYCODE_KP8:
+				if (startingChar > 0) {
+					startingChar -= 4;
+					startingCharChanged(xeenSideChars, startingChar);
+				}
 				// TODO
 				break;
-			case 243:
+			case Common::KEYCODE_DOWN:
+			case Common::KEYCODE_KP2:
 				// TODO
 				break;
 			default:
@@ -215,7 +218,7 @@ void PartyDialog::setupBackground() {
 /**
  * Sets up the faces for display in the party dialog
  */
-void PartyDialog::setupFaces(int charIndex, Common::Array<int> xeenSideChars, bool updateFlag) {
+void PartyDialog::setupFaces(int firstDisplayChar, Common::Array<int> xeenSideChars, bool updateFlag) {
 	Party &party = *_vm->_party;
 	Resources &res = *_vm->_resources;
 	Common::String charNames[4];
@@ -226,10 +229,11 @@ void PartyDialog::setupFaces(int charIndex, Common::Array<int> xeenSideChars, bo
 	int charId;
 
 	for (posIndex = 0; posIndex < 4; ++posIndex) {
-		charId = xeenSideChars[charIndex];
+		charId = (firstDisplayChar + posIndex) >= xeenSideChars.size() ? -1 :
+			xeenSideChars[firstDisplayChar + posIndex];
 		bool isInParty = party.isInParty(charId);
 
-		if (charId == 0xff) {
+		if (charId == -1) {
 			while ((int)_buttons.size() >(7 + posIndex))
 				_buttons.remove_at(_buttons.size() - 1);
 			break;
@@ -237,7 +241,7 @@ void PartyDialog::setupFaces(int charIndex, Common::Array<int> xeenSideChars, bo
 
 		Common::Rect &b = _buttons[7 + posIndex]._bounds;
 		b.moveTo((posIndex & 1) ? 117 : 16, b.top);
-		Character &ps = party._roster[xeenSideChars[charIndex + posIndex]];
+		Character &ps = party._roster[xeenSideChars[firstDisplayChar + posIndex]];
 		charNames[posIndex] = isInParty ? IN_PARTY : ps._name;
 		charRaces[posIndex] = RACE_NAMES[ps._race];
 		charSex[posIndex] = SEX_NAMES[ps._sex];
@@ -247,14 +251,12 @@ void PartyDialog::setupFaces(int charIndex, Common::Array<int> xeenSideChars, bo
 	charIconsPrint(updateFlag);
 
 	// Set up the sprite set to use for each face
-	charId = xeenSideChars[charIndex];
-	_faceDrawStructs[0]._sprites = (charId == 0xff) ? (SpriteResource *)nullptr : &res._charFaces[charId];
-	charId = xeenSideChars[charIndex + 1];
-	_faceDrawStructs[1]._sprites = (charId == 0xff) ? (SpriteResource *)nullptr : &res._charFaces[charId];
-	charId = xeenSideChars[charIndex + 2];
-	_faceDrawStructs[2]._sprites = (charId == 0xff) ? (SpriteResource *)nullptr : &res._charFaces[charId];
-	charId = xeenSideChars[charIndex + 3];
-	_faceDrawStructs[3]._sprites = (charId == 0xff) ? (SpriteResource *)nullptr : &res._charFaces[charId];
+	for (int posIndex = 0; posIndex < 4; ++posIndex) {
+		if ((firstDisplayChar + posIndex) >= xeenSideChars.size())
+			_faceDrawStructs[posIndex]._sprites = nullptr;
+		else
+			_faceDrawStructs[posIndex]._sprites = party._roster[posIndex]._faceSprites;
+	}
 
 	_displayText = Common::String::format(PARTY_DETAILS,
 		charNames[0].c_str(), charRaces[0].c_str(), charSex[0].c_str(), charClasses[0].c_str(),
@@ -264,4 +266,9 @@ void PartyDialog::setupFaces(int charIndex, Common::Array<int> xeenSideChars, bo
 		);
 }
 
+void PartyDialog::startingCharChanged(Common::Array<int> &charList, int firstDisplayChar) {
+	Party &party = *_vm->_party;
+
+}
+
 } // End of namespace Xeen
diff --git a/engines/xeen/dialogs_party.h b/engines/xeen/dialogs_party.h
index c2768e9..4450f3f 100644
--- a/engines/xeen/dialogs_party.h
+++ b/engines/xeen/dialogs_party.h
@@ -23,6 +23,7 @@
 #ifndef XEEN_DIALOGS_PARTY_H
 #define XEEN_DIALOGS_PARTY_H
 
+#include "common/array.h"
 #include "xeen/dialogs.h"
 #include "xeen/screen.h"
 #include "xeen/sprites.h"
@@ -48,7 +49,9 @@ private:
 
 	void charIconsPrint(bool updateFlag);
 
-	void setupFaces(int charIndex, Common::Array<int> xeenSideChars, bool updateFlag);
+	void setupFaces(int firstDisplayChar, Common::Array<int> xeenSideChars, bool updateFlag);
+
+	void startingCharChanged(Common::Array<int> &charList, int firstDisplayChar);
 public:
 	static void show(XeenEngine *vm);
 };
diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp
index 13a12f0..15f19c5 100644
--- a/engines/xeen/interface.cpp
+++ b/engines/xeen/interface.cpp
@@ -34,7 +34,6 @@
 namespace Xeen {
 
 Interface::Interface(XeenEngine *vm) : ButtonContainer(), InterfaceMap(vm), _vm(vm) {
-	Common::fill(&_partyFaces[0], &_partyFaces[MAX_ACTIVE_PARTY], (SpriteResource *)nullptr);
 	_buttonsLoaded = false;
 	_hiliteChar = -1;
 	_intrIndex1 = 0;
@@ -76,14 +75,6 @@ void Interface::setup() {
 	party._newDay = party._minutes >= 300;
 }
 
-void Interface::loadPartyIcons() {
-	Party &party = *_vm->_party;
-	Resources &res = *_vm->_resources;
-
-	for (int i = 0; i < party._partyCount; ++i)
-		_partyFaces[i] = &res._charFaces[_vm->_party->_partyMembers[i]];
-}
-
 void Interface::charIconsPrint(bool updateFlag) {
 	Screen &screen = *_vm->_screen;
 	bool stateFlag = _vm->_mode == MODE_COMBAT;
@@ -97,7 +88,7 @@ void Interface::charIconsPrint(bool updateFlag) {
 		Condition charCondition = ps.worstCondition();
 		int charFrame = FACE_CONDITION_FRAMES[charCondition];
 		
-		SpriteResource *sprites = (charFrame > 4) ? &_dseFace : _partyFaces[charIndex];
+		SpriteResource *sprites = (charFrame > 4) ? &_dseFace : ps._faceSprites;
 		if (charFrame > 4)
 			charFrame -= 5;
 
@@ -139,17 +130,7 @@ void Interface::charIconsPrint(bool updateFlag) {
  * Removes any empty character entries from the faces list
  */
 void Interface::sortFaces() {
-	for (uint charIdx = 0; charIdx < MAX_ACTIVE_PARTY; ++charIdx) {
-		if (!_partyFaces[charIdx]) {
-			for (uint charIdx2 = charIdx + 1; charIdx2 < 8; ++charIdx2) {
-				if (_partyFaces[charIdx2]) {
-					_partyFaces[charIdx] = _partyFaces[charIdx2];
-					_partyFaces[charIdx2] = 0;
-					break;
-				}
-			}
-		}
-	}
+	// No implementation needed
 }
 
 void Interface::startup() {
diff --git a/engines/xeen/interface.h b/engines/xeen/interface.h
index 3d496aa..7dc1b53 100644
--- a/engines/xeen/interface.h
+++ b/engines/xeen/interface.h
@@ -69,7 +69,6 @@ private:
 public:
 	int _intrIndex1;
 	Common::String _interfaceText;
-	SpriteResource *_partyFaces[MAX_ACTIVE_PARTY];
 public:
 	Interface(XeenEngine *vm);
 
@@ -79,8 +78,6 @@ public:
 
 	void manageCharacters(bool soundPlayed);
 
-	void loadPartyIcons();
-
 	void startup();
 
 	void mainIconsPrint();
diff --git a/engines/xeen/party.cpp b/engines/xeen/party.cpp
index 6bff8fd..e011085 100644
--- a/engines/xeen/party.cpp
+++ b/engines/xeen/party.cpp
@@ -32,10 +32,22 @@
 
 namespace Xeen {
 
-void Roster::synchronize(Common::Serializer &s) {
-	if (s.isLoading())
-		resize(30);
+Roster::Roster() {
+	resize(TOTAL_CHARACTERS);
+
+	for (int idx = 0; idx < TOTAL_CHARACTERS; ++idx) {
+		if (idx < XEEN_TOTAL_CHARACTERS) {
+			// Load new character resource
+			Common::String name = Common::String::format("char%02d.fac", idx + 1);
+			_charFaces[idx].load(name);
+			operator[](idx)._faceSprites = &_charFaces[idx];
+		} else {
+			operator[](idx)._faceSprites = nullptr;
+		}
+	}
+}
 
+void Roster::synchronize(Common::Serializer &s) {
 	for (uint i = 0; i < 30; ++i)
 		(*this)[i].synchronize(s);
 }
diff --git a/engines/xeen/party.h b/engines/xeen/party.h
index c37a673..a91b398 100644
--- a/engines/xeen/party.h
+++ b/engines/xeen/party.h
@@ -50,7 +50,9 @@ enum Difficulty { ADVENTURER = 0, WARRIOR = 1 };
 
 class Roster: public Common::Array<Character> {
 public:
-	Roster() {}
+	SpriteResource _charFaces[TOTAL_CHARACTERS];
+public:
+	Roster();
 
 	void synchronize(Common::Serializer &s);
 };
diff --git a/engines/xeen/resources.cpp b/engines/xeen/resources.cpp
index 7067886..11b2092 100644
--- a/engines/xeen/resources.cpp
+++ b/engines/xeen/resources.cpp
@@ -31,12 +31,6 @@ Resources::Resources() {
 	while (f.pos() < f.size())
 		_maeNames.push_back(f.readString());
 	f.close();
-
-	for (int i = 0; i < XEEN_TOTAL_CHARACTERS; ++i) {
-		// Load new character resource
-		Common::String name = Common::String::format("char%02d.fac", i + 1);
-		_charFaces[i].load(name);
-	}
 }
 
 /*------------------------------------------------------------------------*/
diff --git a/engines/xeen/resources.h b/engines/xeen/resources.h
index dd3a775..de99c98 100644
--- a/engines/xeen/resources.h
+++ b/engines/xeen/resources.h
@@ -35,7 +35,6 @@ class Resources {
 public:
 	// Magic and equipment names
 	Common::StringArray _maeNames;
-	SpriteResource _charFaces[TOTAL_CHARACTERS];
 public:
 	Resources();
 };
diff --git a/engines/xeen/xeen.cpp b/engines/xeen/xeen.cpp
index 3c2b7a2..e0a2beb 100644
--- a/engines/xeen/xeen.cpp
+++ b/engines/xeen/xeen.cpp
@@ -295,7 +295,6 @@ void XeenEngine::play() {
 	_interface->setup();
 	_screen->loadBackground("back.raw");
 	_screen->loadPalette("mm4.pal");
-	_interface->loadPartyIcons();
 
 	if (getGameID() != GType_WorldOfXeen && !_map->_loadDarkSide) {
 		_map->_loadDarkSide = true;


Commit: e59617834503da077c27c5dff37f620bb1e9f0c1
    https://github.com/scummvm/scummvm/commit/e59617834503da077c27c5dff37f620bb1e9f0c1
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-02-10T19:28:45-05:00

Commit Message:
XEEN: Refactored drawing the party icons into a separate class

Changed paths:
    engines/xeen/dialogs_dismiss.cpp
    engines/xeen/dialogs_exchange.cpp
    engines/xeen/dialogs_items.cpp
    engines/xeen/dialogs_party.cpp
    engines/xeen/dialogs_party.h
    engines/xeen/dialogs_query.cpp
    engines/xeen/interface.cpp
    engines/xeen/interface.h
    engines/xeen/interface_map.cpp
    engines/xeen/interface_map.h
    engines/xeen/party.cpp
    engines/xeen/resources.cpp
    engines/xeen/resources.h
    engines/xeen/scripts.cpp
    engines/xeen/town.cpp



diff --git a/engines/xeen/dialogs_dismiss.cpp b/engines/xeen/dialogs_dismiss.cpp
index c387c28..b512b66 100644
--- a/engines/xeen/dialogs_dismiss.cpp
+++ b/engines/xeen/dialogs_dismiss.cpp
@@ -73,7 +73,6 @@ void Dismiss::execute() {
 					Character tempChar = party._activeParty[_buttonValue];
 					int charIndex = party._partyMembers[_buttonValue];
 
-					intf.sortFaces();
 //					party.sortParty();
 
 					// TODO
diff --git a/engines/xeen/dialogs_exchange.cpp b/engines/xeen/dialogs_exchange.cpp
index c6a4522..0418b40 100644
--- a/engines/xeen/dialogs_exchange.cpp
+++ b/engines/xeen/dialogs_exchange.cpp
@@ -65,7 +65,7 @@ void ExchangeDialog::execute(Character *&c, int &charIndex) {
 	}
 
 	w.close();
-	intf.charIconsPrint(true);
+	intf.drawParty(true);
 	intf.highlightChar(charIndex);
 }
 
diff --git a/engines/xeen/dialogs_items.cpp b/engines/xeen/dialogs_items.cpp
index 002a8fb..7b4e23e 100644
--- a/engines/xeen/dialogs_items.cpp
+++ b/engines/xeen/dialogs_items.cpp
@@ -505,7 +505,7 @@ Character *ItemsDialog::execute(Character *c, ItemsMode mode) {
 		}
 	}
 
-	intf.charIconsPrint(true);
+	intf.drawParty(true);
 	if (updateStock)
 		charData2BlackData();
 
diff --git a/engines/xeen/dialogs_party.cpp b/engines/xeen/dialogs_party.cpp
index c8689f0..9202187 100644
--- a/engines/xeen/dialogs_party.cpp
+++ b/engines/xeen/dialogs_party.cpp
@@ -220,7 +220,6 @@ void PartyDialog::setupBackground() {
  */
 void PartyDialog::setupFaces(int firstDisplayChar, Common::Array<int> xeenSideChars, bool updateFlag) {
 	Party &party = *_vm->_party;
-	Resources &res = *_vm->_resources;
 	Common::String charNames[4];
 	Common::String charRaces[4];
 	Common::String charSex[4];
@@ -229,7 +228,7 @@ void PartyDialog::setupFaces(int firstDisplayChar, Common::Array<int> xeenSideCh
 	int charId;
 
 	for (posIndex = 0; posIndex < 4; ++posIndex) {
-		charId = (firstDisplayChar + posIndex) >= xeenSideChars.size() ? -1 :
+		charId = (firstDisplayChar + posIndex) >= (int)xeenSideChars.size() ? -1 :
 			xeenSideChars[firstDisplayChar + posIndex];
 		bool isInParty = party.isInParty(charId);
 
@@ -248,11 +247,11 @@ void PartyDialog::setupFaces(int firstDisplayChar, Common::Array<int> xeenSideCh
 		charClasses[posIndex] = CLASS_NAMES[ps._class];
 	}
 
-	charIconsPrint(updateFlag);
+	drawParty(updateFlag);
 
 	// Set up the sprite set to use for each face
 	for (int posIndex = 0; posIndex < 4; ++posIndex) {
-		if ((firstDisplayChar + posIndex) >= xeenSideChars.size())
+		if ((firstDisplayChar + posIndex) >= (int)xeenSideChars.size())
 			_faceDrawStructs[posIndex]._sprites = nullptr;
 		else
 			_faceDrawStructs[posIndex]._sprites = party._roster[posIndex]._faceSprites;
@@ -268,7 +267,7 @@ void PartyDialog::setupFaces(int firstDisplayChar, Common::Array<int> xeenSideCh
 
 void PartyDialog::startingCharChanged(Common::Array<int> &charList, int firstDisplayChar) {
 	Party &party = *_vm->_party;
-
+	// TODO
 }
 
 } // End of namespace Xeen
diff --git a/engines/xeen/dialogs_party.h b/engines/xeen/dialogs_party.h
index 4450f3f..327c299 100644
--- a/engines/xeen/dialogs_party.h
+++ b/engines/xeen/dialogs_party.h
@@ -47,7 +47,7 @@ private:
 
 	void setupBackground();
 
-	void charIconsPrint(bool updateFlag);
+	void drawParty(bool updateFlag);
 
 	void setupFaces(int firstDisplayChar, Common::Array<int> xeenSideChars, bool updateFlag);
 
diff --git a/engines/xeen/dialogs_query.cpp b/engines/xeen/dialogs_query.cpp
index f226521..c982b8a 100644
--- a/engines/xeen/dialogs_query.cpp
+++ b/engines/xeen/dialogs_query.cpp
@@ -97,11 +97,12 @@ bool YesNo::show(XeenEngine *vm, bool type, bool townFlag) {
 }
 
 bool YesNo::execute(bool type, bool townFlag) {
-	Screen &screen = *_vm->_screen;
 	EventsManager &events = *_vm->_events;
 	Interface &intf = *_vm->_interface;
 	Map &map = *_vm->_map;
 	Party &party = *_vm->_party;
+	Resources &res = *_vm->_resources;
+	Screen &screen = *_vm->_screen;
 	Town &town = *_vm->_town;
 	SpriteResource confirmSprites;
 	int numFrames;
@@ -112,7 +113,7 @@ bool YesNo::execute(bool type, bool townFlag) {
 
 	if (!type) {
 		confirmSprites.load("confirm.icn");
-		intf._globalSprites.draw(screen, 7, Common::Point(232, 74));
+		res._globalSprites.draw(screen, 7, Common::Point(232, 74));
 		confirmSprites.draw(screen, 0, Common::Point(235, 75));
 		confirmSprites.draw(screen, 2, Common::Point(260, 75));
 		screen._windows[34].update();
diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp
index 15f19c5..7c9e8a3 100644
--- a/engines/xeen/interface.cpp
+++ b/engines/xeen/interface.cpp
@@ -33,9 +33,96 @@
 
 namespace Xeen {
 
-Interface::Interface(XeenEngine *vm) : ButtonContainer(), InterfaceMap(vm), _vm(vm) {
-	_buttonsLoaded = false;
+PartyDrawer::PartyDrawer(XeenEngine *vm): _vm(vm) {
+	_restoreSprites.load("restorex.icn");
+	_hpSprites.load("hpbars.icn");
+	_dseFace.load("dse.fac");
 	_hiliteChar = -1;
+}
+
+void PartyDrawer::drawParty(bool updateFlag) {
+	Party &party = *_vm->_party;
+	Resources &res = *_vm->_resources;
+	Screen &screen = *_vm->_screen;
+	bool inCombat = _vm->_mode == MODE_COMBAT;
+	_restoreSprites.draw(screen, 0, Common::Point(8, 149));
+
+	// Handle drawing the party faces
+	uint partyCount = inCombat ? party._combatParty.size() : party._activeParty.size();
+	for (uint idx = 0; idx < partyCount; ++idx) {
+		Character &ps = inCombat ? *party._combatParty[idx] : party._activeParty[idx];
+		Condition charCondition = ps.worstCondition();
+		int charFrame = FACE_CONDITION_FRAMES[charCondition];
+		
+		SpriteResource *sprites = (charFrame > 4) ? &_dseFace : ps._faceSprites;
+		if (charFrame > 4)
+			charFrame -= 5;
+
+		sprites->draw(screen, charFrame, Common::Point(CHAR_FACES_X[idx], 150));
+	}
+
+	for (uint idx = 0; idx < partyCount; ++idx) {
+		Character &ps = inCombat ? *party._combatParty[idx] : party._activeParty[idx];
+
+		// Draw the Hp bar
+		int maxHp = ps.getMaxHP();
+		int frame;
+		if (ps._currentHp < 1)
+			frame = 4;
+		else if (ps._currentHp > maxHp)
+			frame = 3;
+		else if (ps._currentHp == maxHp)
+			frame = 0;
+		else if (ps._currentHp < (maxHp / 4))
+			frame = 2;
+		else
+			frame = 1;
+
+		_hpSprites.draw(screen, frame, Common::Point(HP_BARS_X[idx], 182));
+	}
+
+	if (_hiliteChar != -1)
+		res._globalSprites.draw(screen, 8, Common::Point(CHAR_FACES_X[_hiliteChar] - 1, 149));
+
+	if (updateFlag)
+		screen._windows[33].update();
+}
+
+void PartyDrawer::highlightChar(int charId) {
+	Resources &res = *_vm->_resources;
+	Screen &screen = *_vm->_screen;
+
+	if (charId != _hiliteChar && _hiliteChar != HILIGHT_CHAR_DISABLED) {
+		// Handle deselecting any previusly selected char
+		if (_hiliteChar != -1) {
+			res._globalSprites.draw(screen, 9 + _hiliteChar,
+				Common::Point(CHAR_FACES_X[_hiliteChar] - 1, 149));
+		}
+
+		// Highlight new character
+		res._globalSprites.draw(screen, 8, Common::Point(CHAR_FACES_X[charId] - 1, 149));
+		_hiliteChar = charId;
+		screen._windows[33].update();
+	}
+}
+
+void PartyDrawer::unhighlightChar() {
+	Resources &res = *_vm->_resources;
+	Screen &screen = *_vm->_screen;
+
+	if (_hiliteChar != -1) {
+		res._globalSprites.draw(screen, _hiliteChar + 9,
+			Common::Point(CHAR_FACES_X[_hiliteChar] - 1, 149));
+		_hiliteChar = -1;
+		screen._windows[33].update();
+	}
+}
+
+/*------------------------------------------------------------------------*/
+
+Interface::Interface(XeenEngine *vm) : ButtonContainer(), InterfaceMap(vm), 
+		PartyDrawer(vm), _vm(vm) {
+	_buttonsLoaded = false;
 	_intrIndex1 = 0;
 	_steppingFX = 0;
 
@@ -65,75 +152,15 @@ void Interface::initDrawStructs() {
 
 void Interface::setup() {
 	InterfaceMap::setup();
-	_restoreSprites.load("restorex.icn");
-	_hpSprites.load("hpbars.icn");
 	_uiSprites.load("inn.icn");
-	_dseFace.load("dse.fac");
 
 	Party &party = *_vm->_party;
 	party.loadActiveParty();
 	party._newDay = party._minutes >= 300;
 }
 
-void Interface::charIconsPrint(bool updateFlag) {
-	Screen &screen = *_vm->_screen;
-	bool stateFlag = _vm->_mode == MODE_COMBAT;
-	_restoreSprites.draw(screen, 0, Common::Point(8, 149));
-
-	// Handle drawing the party faces
-	for (int idx = 0; idx < (stateFlag ? _vm->_party->_combatPartyCount : 
-			_vm->_party->_partyCount); ++idx) {
-		int charIndex = stateFlag ? _combatCharIds[idx] : idx;
-		Character &ps = _vm->_party->_activeParty[charIndex];
-		Condition charCondition = ps.worstCondition();
-		int charFrame = FACE_CONDITION_FRAMES[charCondition];
-		
-		SpriteResource *sprites = (charFrame > 4) ? &_dseFace : ps._faceSprites;
-		if (charFrame > 4)
-			charFrame -= 5;
-
-		sprites->draw(screen, charFrame, Common::Point(CHAR_FACES_X[idx], 150));
-	}
-
-	if (!_hpSprites.empty()) {
-		for (int idx = 0; idx < (stateFlag ? _vm->_party->_combatPartyCount :
-			_vm->_party->_partyCount); ++idx) {
-			int charIndex = stateFlag ? _combatCharIds[idx] : idx;
-			Character &ps = _vm->_party->_activeParty[charIndex];
-
-			// Draw the Hp bar
-			int maxHp = ps.getMaxHP();
-			int frame;
-			if (ps._currentHp < 1)
-				frame = 4;
-			else if (ps._currentHp > maxHp)
-				frame = 3;
-			else if (ps._currentHp == maxHp)
-				frame = 0;
-			else if (ps._currentHp < (maxHp / 4))
-				frame = 2;
-			else
-				frame = 1;
-
-			_hpSprites.draw(screen, frame, Common::Point(HP_BARS_X[idx], 182));
-		}
-	}
-
-	if (_hiliteChar != -1)
-		_globalSprites.draw(screen, 8, Common::Point(CHAR_FACES_X[_hiliteChar] - 1, 149));
-
-	if (updateFlag)
-		screen._windows[33].update();
-}
-
-/**
- * Removes any empty character entries from the faces list
- */
-void Interface::sortFaces() {
-	// No implementation needed
-}
-
 void Interface::startup() {
+	Resources &res = *_vm->_resources;
 	Screen &screen = *_vm->_screen;
 	_iconSprites.load("main.icn");
 
@@ -147,10 +174,10 @@ void Interface::startup() {
 	}
 	draw3d(false);
 
-	_globalSprites.draw(screen._windows[1], 5, Common::Point(232, 9));
-	charIconsPrint(false);
+	res._globalSprites.draw(screen._windows[1], 5, Common::Point(232, 9));
+	drawParty(false);
 
-	_mainList[0]._sprites = &_globalSprites;
+	_mainList[0]._sprites = &res._globalSprites;
 	for (int i = 1; i < 16; ++i)
 		_mainList[i]._sprites = &_iconSprites;
 
@@ -582,34 +609,6 @@ void Interface::doFalling() {
 	// TODO
 }
 
-void Interface::highlightChar(int charId) {
-	Screen &screen = *_vm->_screen;
-
-	if (charId != _hiliteChar && _hiliteChar != HILIGHT_CHAR_DISABLED) {
-		// Handle deselecting any previusly selected char
-		if (_hiliteChar != -1) {
-			_globalSprites.draw(screen, 9 + _hiliteChar,
-				Common::Point(CHAR_FACES_X[_hiliteChar] - 1, 149));
-		}
-
-		// Highlight new character
-		_globalSprites.draw(screen, 8, Common::Point(CHAR_FACES_X[charId] - 1, 149));
-		_hiliteChar = charId;
-		screen._windows[33].update();
-	}
-}
-
-void Interface::unhighlightChar() {
-	Screen &screen = *_vm->_screen;
-
-	if (_hiliteChar != -1) {
-		_globalSprites.draw(screen, _hiliteChar + 9,
-			Common::Point(CHAR_FACES_X[_hiliteChar] - 1, 149));
-		_hiliteChar = -1;
-		screen._windows[33].update();
-	}
-}
-
 bool Interface::checkMoveDirection(int key) {
 	Map &map = *_vm->_map;
 	Party &party = *_vm->_party;
@@ -738,7 +737,7 @@ void Interface::rest() {
 		for (uint charIdx = 0; charIdx < party._activeParty.size(); ++charIdx) {
 			party._activeParty[charIdx]._conditions[ASLEEP] = 1;
 		}
-		charIconsPrint(true);
+		drawParty(true);
 
 		Mode oldMode = _vm->_mode;
 		_vm->_mode = MODE_SLEEPING;
@@ -826,7 +825,7 @@ void Interface::rest() {
 			}
 		}
 
-		charIconsPrint(true);
+		drawParty(true);
 		_vm->_mode = oldMode;
 		doStepCode();
 		draw3d(true);
@@ -924,7 +923,7 @@ void Interface::bash(const Common::Point &pt, Direction direction) {
 
 	party.checkPartyDead();
 	events.ipause(2);
-	charIconsPrint(true);
+	drawParty(true);
 }
 
 
diff --git a/engines/xeen/interface.h b/engines/xeen/interface.h
index 7dc1b53..5980175 100644
--- a/engines/xeen/interface.h
+++ b/engines/xeen/interface.h
@@ -36,19 +36,38 @@ class XeenEngine;
 #define MINIMAP_SIZE 7
 #define HILIGHT_CHAR_DISABLED -2
 
-class Interface: public ButtonContainer, public InterfaceMap {
+/**
+ * Class responsible for drawing the images of the characters in the party
+ */
+class PartyDrawer {
 private:
 	XeenEngine *_vm;
-	SpriteResource _restoreSprites;
 	SpriteResource _dseFace;
 	SpriteResource _hpSprites;
+	SpriteResource _restoreSprites;
+	int _hiliteChar;
+public:
+	PartyDrawer(XeenEngine *vm);
+
+	void drawParty(bool updateFlag);
+
+	void highlightChar(int charId);
+
+	void unhighlightChar();
+};
+
+/**
+ * Implements the main in-game interface
+ */
+class Interface: public ButtonContainer, public InterfaceMap, public PartyDrawer {
+private:
+	XeenEngine *_vm;
 	SpriteResource _uiSprites;
 	SpriteResource _iconSprites;
 	DrawStruct _mainList[16];
 	int _combatCharIds[8];
 
 	bool _buttonsLoaded;
-	int _hiliteChar;
 	int _steppingFX;
 
 	void initDrawStructs();
@@ -82,16 +101,8 @@ public:
 
 	void mainIconsPrint();
 
-	void charIconsPrint(bool updateFlag);
-
-	void sortFaces();
-
 	void doFalling();
 
-	void highlightChar(int charId);
-
-	void unhighlightChar();
-
 	void perform();
 
 	void rest();
diff --git a/engines/xeen/interface_map.cpp b/engines/xeen/interface_map.cpp
index 42c5ff4..beaf241 100644
--- a/engines/xeen/interface_map.cpp
+++ b/engines/xeen/interface_map.cpp
@@ -399,7 +399,6 @@ InterfaceMap::InterfaceMap(XeenEngine *vm): _vm(vm) {
 }
 
 void InterfaceMap::setup() {
-	_globalSprites.load("global.icn");
 	_borderSprites.load("border.icn");
 	_spellFxSprites.load("spellfx.icn");
 	_fecpSprites.load("fecp.brd");
@@ -4490,10 +4489,11 @@ void InterfaceMap::moveMonsters() {
 }
 
 void InterfaceMap::assembleBorder() {
+	Resources &res = *_vm->_resources;
 	Screen &screen = *_vm->_screen;
 
 	// Draw the outer frame
-	_globalSprites.draw(screen._windows[0], 0, Common::Point(8, 8));
+	res._globalSprites.draw(screen._windows[0], 0, Common::Point(8, 8));
 
 	// Draw the animating bat character used to show when levitate is active
 	_borderSprites.draw(screen._windows[0], _vm->_party->_levitateActive ? _batUIFrame + 16 : 16,
@@ -4600,6 +4600,7 @@ void InterfaceMap::assembleBorder() {
 void InterfaceMap::drawMiniMap() {
 	Map &map = *_vm->_map;
 	Party &party = *_vm->_party;
+	Resources &res = *_vm->_resources;
 	Screen &screen = *_vm->_screen;
 	Window &window1 = screen._windows[1];
 
@@ -4607,7 +4608,7 @@ void InterfaceMap::drawMiniMap() {
 		return;
 	if (!party._automapOn && !party._wizardEyeActive) {
 		// Draw the Might & Magic logo
-		_globalSprites.draw(window1, 5, Common::Point(232, 9));
+		res._globalSprites.draw(window1, 5, Common::Point(232, 9));
 		return;
 	}
 
@@ -4618,7 +4619,7 @@ void InterfaceMap::drawMiniMap() {
 		party._wizardEyeActive = false;
 
 	if (map._isOutdoors) {
-		_globalSprites.draw(window1, 15, Common::Point(237, 12));
+		res._globalSprites.draw(window1, 15, Common::Point(237, 12));
 
 		for (int rowNum = 0, yp = 12, yDiff = 3; rowNum < MINIMAP_SIZE; ++rowNum, yp += 8, --yDiff) {
 			for (int colNum = 0, xp = 237, xDiff = -3; colNum < MINIMAP_SIZE; ++colNum, xp += 10, ++xDiff) {
@@ -4659,7 +4660,7 @@ void InterfaceMap::drawMiniMap() {
 		}
 		
 		// Draw the direction arrow
-		_globalSprites.draw(window1, party._mazeDirection + 1,
+		res._globalSprites.draw(window1, party._mazeDirection + 1,
 			Common::Point(267, 36));
 	} else {
 		frame2 = (frame2 + 2) % 8;
@@ -4844,7 +4845,7 @@ void InterfaceMap::drawMiniMap() {
 					++colNum, ++xDiff, xp += 10) {
 				if (colNum == 4 && rowNum == 4) {
 					// Center of the minimap. Draw the direction arrow
-					_globalSprites.draw(window1, party._mazeDirection + 1,
+					res._globalSprites.draw(window1, party._mazeDirection + 1,
 						Common::Point(272, 40));
 				}
 
@@ -4968,7 +4969,7 @@ void InterfaceMap::drawMiniMap() {
 	}
 
 	// Draw outer rectangle around the automap
-	_globalSprites.draw(window1, 6, Common::Point(223, 3));
+	res._globalSprites.draw(window1, 6, Common::Point(223, 3));
 	party._wizardEyeActive = eyeActive;
 }
 
diff --git a/engines/xeen/interface_map.h b/engines/xeen/interface_map.h
index 034d1a6..660213a 100644
--- a/engines/xeen/interface_map.h
+++ b/engines/xeen/interface_map.h
@@ -130,7 +130,6 @@ public:
 	OutdoorDrawList _outdoorList;
 	IndoorDrawList _indoorList;
 	SpriteResource _charPowSprites;
-	SpriteResource _globalSprites;
 	bool _upDoorText;
 	Common::String _screenText;
 	int _face1State, _face2State;
diff --git a/engines/xeen/party.cpp b/engines/xeen/party.cpp
index e011085..f14a0bf 100644
--- a/engines/xeen/party.cpp
+++ b/engines/xeen/party.cpp
@@ -349,7 +349,7 @@ void Party::changeTime(int numMinutes) {
 	}
 	
 	if (killed)
-		_vm->_interface->charIconsPrint(true);
+		_vm->_interface->drawParty(true);
 
 	if (_isNight != (_minutes < (5 * 60) || _minutes >= (21 * 60)))
 		_vm->_map->loadSky();
@@ -391,7 +391,7 @@ void Party::addTime(int numMinutes) {
 				ErrorScroll::show(_vm, THE_PARTY_NEEDS_REST, WT_NONFREEZED_WAIT);
 			}
 
-			_vm->_interface->charIconsPrint(true);
+			_vm->_interface->drawParty(true);
 		}
 
 		_newDay = false;
diff --git a/engines/xeen/resources.cpp b/engines/xeen/resources.cpp
index 11b2092..e917850 100644
--- a/engines/xeen/resources.cpp
+++ b/engines/xeen/resources.cpp
@@ -27,6 +27,8 @@
 namespace Xeen {
 
 Resources::Resources() {
+	_globalSprites.load("global.icn");
+
 	File f("mae.xen");
 	while (f.pos() < f.size())
 		_maeNames.push_back(f.readString());
diff --git a/engines/xeen/resources.h b/engines/xeen/resources.h
index de99c98..d4e1c11 100644
--- a/engines/xeen/resources.h
+++ b/engines/xeen/resources.h
@@ -33,8 +33,8 @@ namespace Xeen {
 
 class Resources {
 public:
-	// Magic and equipment names
-	Common::StringArray _maeNames;
+	SpriteResource _globalSprites;
+	Common::StringArray _maeNames;		// Magic and equipment names
 public:
 	Resources();
 };
diff --git a/engines/xeen/scripts.cpp b/engines/xeen/scripts.cpp
index 3837509..7ced6af 100644
--- a/engines/xeen/scripts.cpp
+++ b/engines/xeen/scripts.cpp
@@ -174,7 +174,7 @@ int Scripts::checkEvents() {
 	intf._face1State = intf._face2State = 2;
 	if (_refreshIcons) {
 		screen.closeWindows();
-		intf.charIconsPrint(true);
+		intf.drawParty(true);
 	}
 
 	// TODO
diff --git a/engines/xeen/town.cpp b/engines/xeen/town.cpp
index c12973c..25f332a 100644
--- a/engines/xeen/town.cpp
+++ b/engines/xeen/town.cpp
@@ -621,7 +621,7 @@ Character *Town::doTavernOptions(Character *c) {
 
 				if (_vm->getRandomNumber(100) < 26) {
 					++c->_conditions[DRUNK];
-					intf.charIconsPrint(true);
+					intf.drawParty(true);
 					sound.playFX(28);
 				}
 
@@ -823,7 +823,7 @@ Character *Town::doTempleOptions(Character *c) {
 				party._powerShield = amt;
 				party._blessed = amt;
 
-				intf.charIconsPrint(true);
+				intf.drawParty(true);
 				sound.playSample(nullptr, 0);
 				File f("ahh.voc");
 				sound.playSample(&f, 1);
@@ -854,7 +854,7 @@ Character *Town::doTempleOptions(Character *c) {
 			Common::fill(&c->_conditions[HEART_BROKEN], &c->_conditions[NO_CONDITION], 0);
 
 			_v1 = 1440;
-			intf.charIconsPrint(true);
+			intf.drawParty(true);
 			sound.playSample(nullptr, 0);
 			File f("ahh.voc");
 			sound.playSample(&f, 1);
@@ -871,7 +871,7 @@ Character *Town::doTempleOptions(Character *c) {
 			}
 
 			_v1 = 1440;
-			intf.charIconsPrint(true);
+			intf.drawParty(true);
 			sound.playSample(nullptr, 0);
 			File f("ahh.voc");
 			sound.playSample(&f, 1);
@@ -941,7 +941,7 @@ Character *Town::doTrainingOptions(Character *c) {
 				party.resetTemps();
 				c->_currentHp = c->getMaxHP();
 				c->_currentSp = c->getMaxSP();
-				intf.charIconsPrint(true);
+				intf.drawParty(true);
 			}
 		}
 		break;


Commit: 50ae4f95229e9a11b86884aa1fa1dffb6cfdc7a8
    https://github.com/scummvm/scummvm/commit/50ae4f95229e9a11b86884aa1fa1dffb6cfdc7a8
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-02-10T23:40:45-05:00

Commit Message:
XEEN: Refactored _partyCount and _partyMembers into the _activeParty array

Changed paths:
    engines/xeen/character.cpp
    engines/xeen/character.h
    engines/xeen/dialogs.cpp
    engines/xeen/dialogs_char_info.cpp
    engines/xeen/dialogs_dismiss.cpp
    engines/xeen/dialogs_exchange.cpp
    engines/xeen/dialogs_party.cpp
    engines/xeen/dialogs_party.h
    engines/xeen/dialogs_quick_ref.cpp
    engines/xeen/dialogs_spells.cpp
    engines/xeen/dialogs_whowill.cpp
    engines/xeen/interface.cpp
    engines/xeen/interface_map.cpp
    engines/xeen/party.cpp
    engines/xeen/party.h
    engines/xeen/resources.cpp
    engines/xeen/resources.h
    engines/xeen/scripts.cpp
    engines/xeen/town.cpp



diff --git a/engines/xeen/character.cpp b/engines/xeen/character.cpp
index dc193f4..e7b5d23 100644
--- a/engines/xeen/character.cpp
+++ b/engines/xeen/character.cpp
@@ -689,6 +689,8 @@ Character::Character():
 		_weapons(this), _armor(this), _accessories(this), _misc(this),
 		_items(_weapons, _armor, _accessories, _misc) {
 	clear();
+	_faceSprites = nullptr;
+	_rosterId = -1;
 }
 
 void Character::clear() {
@@ -734,8 +736,6 @@ void Character::clear() {
 	_armor.clear();
 	_accessories.clear();
 	_misc.clear();
-
-	_faceSprites = nullptr;
 }
 
 void Character::synchronize(Common::Serializer &s) {
diff --git a/engines/xeen/character.h b/engines/xeen/character.h
index 53dee33..59f4ba6 100644
--- a/engines/xeen/character.h
+++ b/engines/xeen/character.h
@@ -260,6 +260,7 @@ public:
 	int _currentCombatSpell;
 
 	SpriteResource *_faceSprites;
+	int _rosterId;
 public:
 	Character();
 
diff --git a/engines/xeen/dialogs.cpp b/engines/xeen/dialogs.cpp
index b25a8e1..ff4eaf6 100644
--- a/engines/xeen/dialogs.cpp
+++ b/engines/xeen/dialogs.cpp
@@ -33,6 +33,7 @@ namespace Xeen {
  */
 void ButtonContainer::saveButtons() {
 	_savedButtons.push(_buttons);
+	clearButtons();
 }
 
 /*
diff --git a/engines/xeen/dialogs_char_info.cpp b/engines/xeen/dialogs_char_info.cpp
index 36ca5bd..de16e95 100644
--- a/engines/xeen/dialogs_char_info.cpp
+++ b/engines/xeen/dialogs_char_info.cpp
@@ -282,7 +282,7 @@ void CharacterInfo::addButtons() {
 Common::String CharacterInfo::loadCharacterDetails(const Character &c) {
 	Condition condition = c.worstCondition();
 	Party &party = *_vm->_party;
-	int foodVal = party._food / party._partyCount / 3;
+	int foodVal = party._food / party._activeParty.size() / 3;
 
 	int totalResist =
 		c._fireResistence._permanent + c.itemScan(11) + c._fireResistence._temporary +
@@ -498,7 +498,7 @@ bool CharacterInfo::expandStat(int attrib, const Character &c) {
 
 	case 18: {
 		// Food
-		int food = (party._food / party._partyCount) / 3;
+		int food = (party._food / party._activeParty.size()) / 3;
 		msg = Common::String::format(FOOD_TEXT, STAT_NAMES[attrib],
 			party._food, food, food != 1 ? "s" : "");
 		break;
diff --git a/engines/xeen/dialogs_dismiss.cpp b/engines/xeen/dialogs_dismiss.cpp
index b512b66..0c28aff 100644
--- a/engines/xeen/dialogs_dismiss.cpp
+++ b/engines/xeen/dialogs_dismiss.cpp
@@ -71,7 +71,7 @@ void Dismiss::execute() {
 					w.open();
 				} else {
 					Character tempChar = party._activeParty[_buttonValue];
-					int charIndex = party._partyMembers[_buttonValue];
+					int charIndex = party._activeParty[_buttonValue]._rosterId;
 
 //					party.sortParty();
 
diff --git a/engines/xeen/dialogs_exchange.cpp b/engines/xeen/dialogs_exchange.cpp
index 0418b40..0b1e538 100644
--- a/engines/xeen/dialogs_exchange.cpp
+++ b/engines/xeen/dialogs_exchange.cpp
@@ -51,9 +51,8 @@ void ExchangeDialog::execute(Character *&c, int &charIndex) {
 
 		if (_buttonValue >= Common::KEYCODE_F1 && _buttonValue <= Common::KEYCODE_F6) {
 			_buttonValue -= Common::KEYCODE_F1;
-			if (_buttonValue < party._partyCount) {
+			if (_buttonValue < (int)party._activeParty.size()) {
 				SWAP(party._activeParty[charIndex], party._activeParty[_buttonValue]);
-				SWAP(party._partyMembers[charIndex], party._partyMembers[_buttonValue]);
 
 				charIndex = _buttonValue;
 				c = &party._activeParty[charIndex];
diff --git a/engines/xeen/dialogs_party.cpp b/engines/xeen/dialogs_party.cpp
index 9202187..618d297 100644
--- a/engines/xeen/dialogs_party.cpp
+++ b/engines/xeen/dialogs_party.cpp
@@ -30,7 +30,11 @@
 
 namespace Xeen {
 
-	void PartyDialog::show(XeenEngine *vm) {
+PartyDialog::PartyDialog(XeenEngine *vm) : ButtonContainer(), 
+		PartyDrawer(vm), _vm(vm) {
+}
+
+void PartyDialog::show(XeenEngine *vm) {
 	PartyDialog *dlg = new PartyDialog(vm);
 	dlg->execute();
 	delete dlg;
@@ -41,6 +45,7 @@ void PartyDialog::execute() {
 	Map &map = *_vm->_map;
 	Party &party = *_vm->_party;
 	Screen &screen = *_vm->_screen;
+	SoundManager &sound = *_vm->_sound;
 	bool modeFlag = false;
 	int startingChar = 0;
 
@@ -49,31 +54,29 @@ void PartyDialog::execute() {
 
 	while (!_vm->shouldQuit()) {
 		_vm->_mode = MODE_1;
-		Common::Array<int> xeenSideChars;
-
-		party.loadActiveParty();
 
 		// Build up a list of characters on the same Xeen side being loaded
+		_charList.clear();
 		for (int i = 0; i < XEEN_TOTAL_CHARACTERS; ++i) {
 			Character &player = party._roster[i];
 			if (player._name.empty() || player._xeenSide != (map._loadDarkSide ? 1 : 0))
 				continue;
 
-			xeenSideChars.push_back(i);
+			_charList.push_back(i);
 		}
 
 		Window &w = screen._windows[11];
 		w.open();
-		setupFaces(startingChar, xeenSideChars, false);
+		setupFaces(startingChar, false);
 		w.writeString(_displayText);
 		w.drawList(&_faceDrawStructs[0], 4);
 
-		_iconSprites.draw(w, 0, Common::Point(16, 100));
-		_iconSprites.draw(w, 2, Common::Point(52, 100));
-		_iconSprites.draw(w, 4, Common::Point(87, 100));
-		_iconSprites.draw(w, 6, Common::Point(122, 100));
-		_iconSprites.draw(w, 8, Common::Point(157, 100));
-		_iconSprites.draw(w, 10, Common::Point(192, 100));
+		_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 (modeFlag) {
@@ -104,7 +107,7 @@ void PartyDialog::execute() {
 			case Common::KEYCODE_SPACE:
 			case Common::KEYCODE_e:
 			case Common::KEYCODE_x:
-				if (party._partyCount == 0) {
+				if (party._activeParty.size() == 0) {
 					ErrorScroll::show(_vm, NO_ONE_TO_ADVENTURE_WITH);
 				} else {
 					if (_vm->_mode != MODE_0) {
@@ -119,7 +122,6 @@ void PartyDialog::execute() {
 					}
 
 					w.close();
-					party._realPartyCount = party._partyCount;
 					party._mazeId = party._priorMazeId;
 
 					party.copyPartyToRoster();
@@ -136,7 +138,7 @@ void PartyDialog::execute() {
 			case Common::KEYCODE_F6:
 				// Show character info
 				_buttonValue -= Common::KEYCODE_F1;
-				if (_buttonValue < party._partyCount)
+				if (_buttonValue < (int)party._activeParty.size())
 					CharacterInfo::show(_vm, _buttonValue);
 				break;
 
@@ -145,15 +147,49 @@ void PartyDialog::execute() {
 			case Common::KEYCODE_3:
 			case Common::KEYCODE_4:
 				_buttonValue -= Common::KEYCODE_1 - 7;
+				if ((_buttonValue - 7 + startingChar) < (int)_charList.size()) {
+					// Check if the selected character is already in the party
+					uint idx = 0;
+					for (; idx < party._activeParty.size(); ++idx) {
+						if (_charList[_buttonValue - 7 + startingChar] ==
+							party._activeParty[idx]._rosterId)
+							break;
+					}
+
+					if (idx == party._activeParty.size()) {
+						sound.playFX(21);
+						ErrorScroll::show(_vm, YOUR_PARTY_IS_FULL);
+					} else {
+						party._activeParty.push_back(party._roster[
+							_charList[_buttonValue - 7 + startingChar]]);
+						error("TODO");
+					}
+				}
+				// TODO
+				break;
+
+			case Common::KEYCODE_UP:
+			case Common::KEYCODE_KP8:
+				if (startingChar > 0) {
+					startingChar -= 4;
+					startingCharChanged(startingChar);
+				}
+				break;
+			case Common::KEYCODE_DOWN:
+			case Common::KEYCODE_KP2:
 				// TODO
 				break;
 
 			case Common::KEYCODE_c:
-				if (xeenSideChars.size() == 24) {
+				// Create
+				if (_charList.size() == XEEN_TOTAL_CHARACTERS) {
 					ErrorScroll::show(_vm, YOUR_ROSTER_IS_FULL);
 				} else {
 					screen.fadeOut(4);
 					w.close();
+
+					createChar();
+
 					party.copyPartyToRoster();
 					_vm->_saves->writeCharFile();
 					screen.fadeOut(4);
@@ -162,25 +198,20 @@ void PartyDialog::execute() {
 				}
 				break;
 			case Common::KEYCODE_d:
+				// Delete character
 				break;
 			case Common::KEYCODE_r:
-				if (party._partyCount > 0) {
-					// TODO
-				}
-				break;
-
-			case Common::KEYCODE_UP:
-			case Common::KEYCODE_KP8:
-				if (startingChar > 0) {
-					startingChar -= 4;
-					startingCharChanged(xeenSideChars, startingChar);
+				// Remove character
+				if (party._activeParty.size() > 0) {
+					int charButtonValue = selectCharacter(false, startingChar);
+					if (charButtonValue != 0) {
+						party.copyPartyToRoster();
+						party._activeParty.remove_at(charButtonValue - Common::KEYCODE_F1);
+					}
+					startingCharChanged(startingChar);
 				}
-				// TODO
-				break;
-			case Common::KEYCODE_DOWN:
-			case Common::KEYCODE_KP2:
-				// TODO
 				break;
+		
 			default:
 				break;
 			}
@@ -189,18 +220,18 @@ void PartyDialog::execute() {
 }
 
 void PartyDialog::loadButtons() {
-	_iconSprites.load("inn.icn");
-	addButton(Common::Rect(16, 100, 40, 120), Common::KEYCODE_UP, &_iconSprites);
-	addButton(Common::Rect(52, 100, 76, 120), Common::KEYCODE_DOWN, &_iconSprites);
-	addButton(Common::Rect(87, 100, 111, 120), Common::KEYCODE_d, &_iconSprites);
-	addButton(Common::Rect(122, 100, 146, 120), Common::KEYCODE_r, &_iconSprites);
-	addButton(Common::Rect(157, 100, 181, 120), Common::KEYCODE_c, &_iconSprites);
-	addButton(Common::Rect(192, 100, 116, 120), Common::KEYCODE_x, &_iconSprites);
-	addButton(Common::Rect(0, 0, 0, 0), Common::KEYCODE_ESCAPE, &_iconSprites, false);
-	addButton(Common::Rect(16, 16, 48, 48), Common::KEYCODE_1, &_iconSprites, false);
-	addButton(Common::Rect(117, 16, 149, 48), Common::KEYCODE_2, &_iconSprites, false);
-	addButton(Common::Rect(59, 59, 91, 91), Common::KEYCODE_3, &_iconSprites, false);
-	addButton(Common::Rect(117, 59, 151, 91), Common::KEYCODE_4, &_iconSprites, false);
+	_uiSprites.load("inn.icn");
+	addButton(Common::Rect(16, 100, 40, 120), Common::KEYCODE_UP, &_uiSprites);
+	addButton(Common::Rect(52, 100, 76, 120), Common::KEYCODE_DOWN, &_uiSprites);
+	addButton(Common::Rect(87, 100, 111, 120), Common::KEYCODE_d, &_uiSprites);
+	addButton(Common::Rect(122, 100, 146, 120), Common::KEYCODE_r, &_uiSprites);
+	addButton(Common::Rect(157, 100, 181, 120), Common::KEYCODE_c, &_uiSprites);
+	addButton(Common::Rect(192, 100, 116, 120), Common::KEYCODE_x, &_uiSprites);
+	addButton(Common::Rect(0, 0, 0, 0), Common::KEYCODE_ESCAPE, &_uiSprites, false);
+	addButton(Common::Rect(16, 16, 48, 48), Common::KEYCODE_1, &_uiSprites, false);
+	addButton(Common::Rect(117, 16, 149, 48), Common::KEYCODE_2, &_uiSprites, false);
+	addButton(Common::Rect(59, 59, 91, 91), Common::KEYCODE_3, &_uiSprites, false);
+	addButton(Common::Rect(117, 59, 151, 91), Common::KEYCODE_4, &_uiSprites, false);
 }
 
 void PartyDialog::initDrawStructs() {
@@ -218,7 +249,7 @@ void PartyDialog::setupBackground() {
 /**
  * Sets up the faces for display in the party dialog
  */
-void PartyDialog::setupFaces(int firstDisplayChar, Common::Array<int> xeenSideChars, bool updateFlag) {
+void PartyDialog::setupFaces(int firstDisplayChar, bool updateFlag) {
 	Party &party = *_vm->_party;
 	Common::String charNames[4];
 	Common::String charRaces[4];
@@ -228,8 +259,8 @@ void PartyDialog::setupFaces(int firstDisplayChar, Common::Array<int> xeenSideCh
 	int charId;
 
 	for (posIndex = 0; posIndex < 4; ++posIndex) {
-		charId = (firstDisplayChar + posIndex) >= (int)xeenSideChars.size() ? -1 :
-			xeenSideChars[firstDisplayChar + posIndex];
+		charId = (firstDisplayChar + posIndex) >= (int)_charList.size() ? -1 :
+			_charList[firstDisplayChar + posIndex];
 		bool isInParty = party.isInParty(charId);
 
 		if (charId == -1) {
@@ -240,7 +271,7 @@ void PartyDialog::setupFaces(int firstDisplayChar, Common::Array<int> xeenSideCh
 
 		Common::Rect &b = _buttons[7 + posIndex]._bounds;
 		b.moveTo((posIndex & 1) ? 117 : 16, b.top);
-		Character &ps = party._roster[xeenSideChars[firstDisplayChar + posIndex]];
+		Character &ps = party._roster[_charList[firstDisplayChar + posIndex]];
 		charNames[posIndex] = isInParty ? IN_PARTY : ps._name;
 		charRaces[posIndex] = RACE_NAMES[ps._race];
 		charSex[posIndex] = SEX_NAMES[ps._sex];
@@ -251,7 +282,7 @@ void PartyDialog::setupFaces(int firstDisplayChar, Common::Array<int> xeenSideCh
 
 	// Set up the sprite set to use for each face
 	for (int posIndex = 0; posIndex < 4; ++posIndex) {
-		if ((firstDisplayChar + posIndex) >= (int)xeenSideChars.size())
+		if ((firstDisplayChar + posIndex) >= (int)_charList.size())
 			_faceDrawStructs[posIndex]._sprites = nullptr;
 		else
 			_faceDrawStructs[posIndex]._sprites = party._roster[posIndex]._faceSprites;
@@ -265,9 +296,91 @@ void PartyDialog::setupFaces(int firstDisplayChar, Common::Array<int> xeenSideCh
 		);
 }
 
-void PartyDialog::startingCharChanged(Common::Array<int> &charList, int firstDisplayChar) {
+void PartyDialog::startingCharChanged(int firstDisplayChar) {
+	Window &w = _vm->_screen->_windows[11];
+
+	setupFaces(firstDisplayChar, true);
+	w.writeString(_displayText);
+	w.drawList(_faceDrawStructs, 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));
+
+	w.update();
+}
+
+void PartyDialog::createChar() {
+	error("TODO: createChar");
+}
+
+int PartyDialog::selectCharacter(bool isDelete, int firstDisplayChar) {
+	EventsManager &events = *_vm->_events;
 	Party &party = *_vm->_party;
-	// TODO
+	Screen &screen = *_vm->_screen;
+	Window &w = screen._windows[28];
+
+	SpriteResource iconSprites;
+	iconSprites.load("esc.icn");
+
+	w.setBounds(Common::Rect(50, isDelete ? 112 : 76, 266, isDelete ? 148 : 112));
+	w.open();
+	w.writeString(Common::String::format(REMOVE_OR_DELETE_WHICH,
+		REMOVE_DELETE[isDelete ? 1 : 0]));
+	iconSprites.draw(w, 0, Common::Point(225, isDelete ? 120 : 84));
+	w.update();
+
+	saveButtons();
+	addButton(Common::Rect(225, isDelete ? 120 : 84, 249, isDelete ? 140 : 104), 
+		Common::KEYCODE_ESCAPE, &iconSprites);
+	addButton(Common::Rect(16, 16, 48, 48), Common::KEYCODE_1, &iconSprites, false);
+	addButton(Common::Rect(117, 16, 149, 48), Common::KEYCODE_2, &iconSprites, false);
+	addButton(Common::Rect(16, 59, 48, 91), Common::KEYCODE_3, &iconSprites, false);
+	addButton(Common::Rect(117, 59, 149, 91), Common::KEYCODE_4, &iconSprites, false);
+
+	int result = -1, v;
+	while (!_vm->shouldQuit() && result == -1) {
+		_buttonValue = 0;
+		while (!_vm->shouldQuit() && !_buttonValue) {
+			events.pollEventsAndWait();
+			checkEvents(_vm);
+		}
+
+		switch (_buttonValue) {
+		case Common::KEYCODE_ESCAPE:
+			result = 0;
+			break;
+
+		case Common::KEYCODE_F1:
+		case Common::KEYCODE_F2:
+		case Common::KEYCODE_F3:
+		case Common::KEYCODE_F4:
+		case Common::KEYCODE_F5:
+		case Common::KEYCODE_F6:
+			v = _buttonValue - Common::KEYCODE_F1;
+			if (v < (int)party._activeParty.size())
+				result = _buttonValue;
+			break;
+
+		case Common::KEYCODE_1:
+		case Common::KEYCODE_2:
+		case Common::KEYCODE_3:
+		case Common::KEYCODE_4:
+			v = _buttonValue - Common::KEYCODE_1;
+			if ((firstDisplayChar + v) < (int)_charList.size())
+				result = _buttonValue;
+
+		default:
+			break;
+		}
+	} 
+
+	w.close();
+	restoreButtons();
+	return result == -1 ? 0 : result;
 }
 
 } // End of namespace Xeen
diff --git a/engines/xeen/dialogs_party.h b/engines/xeen/dialogs_party.h
index 327c299..082c43b 100644
--- a/engines/xeen/dialogs_party.h
+++ b/engines/xeen/dialogs_party.h
@@ -25,19 +25,21 @@
 
 #include "common/array.h"
 #include "xeen/dialogs.h"
+#include "xeen/interface.h"
 #include "xeen/screen.h"
 #include "xeen/sprites.h"
 
 namespace Xeen {
 
-class PartyDialog : public ButtonContainer {
+class PartyDialog : public ButtonContainer, public PartyDrawer {
 private:
 	XeenEngine *_vm;
-	SpriteResource _iconSprites;
+	SpriteResource _uiSprites;
 	DrawStruct _faceDrawStructs[4];
 	Common::String _displayText;
+	Common::Array<int> _charList;
 
-	PartyDialog(XeenEngine *vm) : ButtonContainer(), _vm(vm) {}
+	PartyDialog(XeenEngine *vm);
 
 	void execute();
 
@@ -49,9 +51,13 @@ private:
 
 	void drawParty(bool updateFlag);
 
-	void setupFaces(int firstDisplayChar, Common::Array<int> xeenSideChars, bool updateFlag);
+	void setupFaces(int firstDisplayChar, bool updateFlag);
 
-	void startingCharChanged(Common::Array<int> &charList, int firstDisplayChar);
+	void startingCharChanged(int firstDisplayChar);
+
+	void createChar();
+
+	int selectCharacter(bool isDelete, int firstDisplayChar);
 public:
 	static void show(XeenEngine *vm);
 };
diff --git a/engines/xeen/dialogs_quick_ref.cpp b/engines/xeen/dialogs_quick_ref.cpp
index 6c8da5e..f4066a0 100644
--- a/engines/xeen/dialogs_quick_ref.cpp
+++ b/engines/xeen/dialogs_quick_ref.cpp
@@ -42,7 +42,7 @@ void QuickReferenceDialog::execute() {
 	events.setCursor(0);
 
 	for (uint idx = 0; idx < (combat._globalCombat == 2 ? party._combatParty.size() :
-			party._partyCount); ++idx) {
+			party._activeParty.size()); ++idx) {
 		Character &c = combat._globalCombat == 2 ? *party._combatParty[idx] :
 			party._activeParty[idx];
 		Condition condition = c.worstCondition();
@@ -59,7 +59,7 @@ void QuickReferenceDialog::execute() {
 		);
 	}
 
-	int food = (party._food / party._partyCount) / 3;
+	int food = (party._food / party._activeParty.size()) / 3;
 	Common::String msg = Common::String::format(QUICK_REFERENCE,
 		lines[0].c_str(), lines[1].c_str(), lines[2].c_str(),
 		lines[3].c_str(), lines[4].c_str(), lines[5].c_str(),
diff --git a/engines/xeen/dialogs_spells.cpp b/engines/xeen/dialogs_spells.cpp
index dc05be6..0ce0259 100644
--- a/engines/xeen/dialogs_spells.cpp
+++ b/engines/xeen/dialogs_spells.cpp
@@ -111,7 +111,7 @@ Character *SpellsScroll::execute(Character *c, int v2) {
 		case Common::KEYCODE_F6:
 			if (_vm->_mode != MODE_COMBAT) {
 				_buttonValue -= Common::KEYCODE_F1;
-				if (_buttonValue < party._partyCount) {
+				if (_buttonValue < (int)party._activeParty.size()) {
 					c = &party._activeParty[_buttonValue];
 					spells._lastCaster = _buttonValue;
 					intf.highlightChar(_buttonValue);
diff --git a/engines/xeen/dialogs_whowill.cpp b/engines/xeen/dialogs_whowill.cpp
index fb845a6..10bbae2 100644
--- a/engines/xeen/dialogs_whowill.cpp
+++ b/engines/xeen/dialogs_whowill.cpp
@@ -44,7 +44,7 @@ int WhoWill::execute(int message, int action, bool type) {
 	Town &town = *_vm->_town;
 	int numFrames;
 
-	if (party._partyCount <= 1)
+	if (party._activeParty.size() <= 1)
 		// Unless there's at least two characters, just return the first one
 		return 1;
 
@@ -53,7 +53,7 @@ int WhoWill::execute(int message, int action, bool type) {
 
 	Common::String actionStr = type ? map._events._text[action] : WHO_WILL_ACTIONS[action];
 	Common::String msg = Common::String::format(WHO_WILL, actionStr.c_str(),
-		WHO_ACTIONS[message], party._partyCount);
+		WHO_ACTIONS[message], party._activeParty.size());
 
 	screen._windows[36].open();
 	screen._windows[36].writeString(msg);
@@ -86,7 +86,7 @@ int WhoWill::execute(int message, int action, bool type) {
 			break;
 		} else if (_buttonValue >= 201 && _buttonValue <= 206) {
 			_buttonValue -= 201;
-			if (_buttonValue > party._partyCount)
+			if (_buttonValue > (int)party._activeParty.size())
 				continue;
 
 			if (party._activeParty[_buttonValue - 1].noActions())
diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp
index 7c9e8a3..b88b64a 100644
--- a/engines/xeen/interface.cpp
+++ b/engines/xeen/interface.cpp
@@ -433,7 +433,7 @@ void Interface::perform() {
 	case Common::KEYCODE_F5:
 	case Common::KEYCODE_F6:
 		_buttonValue -= Common::KEYCODE_F1;
-		if (_buttonValue < party._partyCount) {
+		if (_buttonValue < (int)party._activeParty.size()) {
 			CharacterInfo::show(_vm, _buttonValue);
 			if (party._stepped)
 				moveMonsters();
diff --git a/engines/xeen/interface_map.cpp b/engines/xeen/interface_map.cpp
index beaf241..ad53b7c 100644
--- a/engines/xeen/interface_map.cpp
+++ b/engines/xeen/interface_map.cpp
@@ -4397,8 +4397,8 @@ void InterfaceMap::drawIndoors() {
 
 	// Check for any character shooting
 	_isShooting = false;
-	for (int i = 0; i < _vm->_party->_partyCount; ++i) {
-		if (_vm->_combat->_shooting[i])
+	for (uint idx = 0; idx < _vm->_party->_activeParty.size(); ++idx) {
+		if (_vm->_combat->_shooting[idx])
 			_isShooting = true;
 	}
 	
@@ -4475,8 +4475,8 @@ void InterfaceMap::drawOutdoors() {
 
 	// Check for any character shooting
 	_isShooting = false;
-	for (int i = 0; i < _vm->_party->_partyCount; ++i) {
-		if (_vm->_combat->_shooting[i])
+	for (uint idx = 0; idx < _vm->_party->_activeParty.size(); ++idx) {
+		if (_vm->_combat->_shooting[idx])
 			_isShooting = true;
 	}
 
diff --git a/engines/xeen/party.cpp b/engines/xeen/party.cpp
index f14a0bf..cd1dc21 100644
--- a/engines/xeen/party.cpp
+++ b/engines/xeen/party.cpp
@@ -36,6 +36,9 @@ Roster::Roster() {
 	resize(TOTAL_CHARACTERS);
 
 	for (int idx = 0; idx < TOTAL_CHARACTERS; ++idx) {
+		// Set the index of the character in the roster list
+		operator[](idx)._rosterId = idx;
+
 		if (idx < XEEN_TOTAL_CHARACTERS) {
 			// Load new character resource
 			Common::String name = Common::String::format("char%02d.fac", idx + 1);
@@ -48,7 +51,7 @@ Roster::Roster() {
 }
 
 void Roster::synchronize(Common::Serializer &s) {
-	for (uint i = 0; i < 30; ++i)
+	for (uint i = 0; i < TOTAL_CHARACTERS; ++i)
 		(*this)[i].synchronize(s);
 }
 
@@ -58,9 +61,6 @@ XeenEngine *Party::_vm;
 
 Party::Party(XeenEngine *vm) {
 	_vm = vm;
-	_partyCount = 0;
-	_realPartyCount = 0;
-	Common::fill(&_partyMembers[0], &_partyMembers[8], 0);
 	_mazeDirection = DIR_NORTH;
 	_mazeId = _priorMazeId = 0;
 	_levitateActive = false;
@@ -120,11 +120,25 @@ Party::Party(XeenEngine *vm) {
 void Party::synchronize(Common::Serializer &s) {
 	byte dummy[30];
 	Common::fill(&dummy[0], &dummy[30], 0);
+	int partyCount = _activeParty.size();
+
+	int8 partyMembers[MAX_PARTY_COUNT];
+	if (s.isSaving()) {
+		Common::fill(&partyMembers[0], &partyMembers[8], -1);
+		for (uint idx = 0; idx < _activeParty.size(); ++idx)
+			partyMembers[idx] = _activeParty[idx]._rosterId;
+	} else {
+		_activeParty.clear();
+	}
+
+	s.syncAsByte(partyCount);	// Party count
+	s.syncAsByte(partyCount);	// Real party count
+	for (int idx = 0; idx < MAX_PARTY_COUNT; ++idx) {
+		s.syncAsByte(partyMembers[idx]);
+		if (s.isLoading() && idx < partyCount && partyMembers[idx] != -1)
+			_activeParty.push_back(_roster[partyMembers[idx]]);
+	}
 
-	s.syncAsByte(_partyCount);
-	s.syncAsByte(_realPartyCount);
-	for (int i = 0; i < 8; ++i)
-		s.syncAsByte(_partyMembers[i]);
 	s.syncAsByte(_mazeDirection);
 	s.syncAsByte(_mazePosition.x);
 	s.syncAsByte(_mazePosition.y);
@@ -199,10 +213,7 @@ void Party::synchronize(Common::Serializer &s) {
 }
 
 void Party::loadActiveParty() {
-	_activeParty.resize(_partyCount);
-	for (int i = 0; i < _partyCount; ++i) {
-		_activeParty[i] = _roster[_partyMembers[i]];
-	}
+	// No implementation needed
 }
 
 bool Party::checkSkill(Skill skillId) {
@@ -235,17 +246,20 @@ bool Party::checkSkill(Skill skillId) {
 }
 
 bool Party::isInParty(int charId) {
-	for (int i = 0; i < 8; ++i) {
-		if (_partyMembers[i] == charId)
+	for (uint i = 0; i < _activeParty.size(); ++i) {
+		if (_activeParty[i]._rosterId == charId)
 			return true;
 	}
 
 	return false;
 }
 
+/**
+ * Copy the currently active party characters' data back to the roster
+ */
 void Party::copyPartyToRoster() {
-	for (int i = 0; i < _partyCount; ++i) {
-		_roster[_partyMembers[i]] = _activeParty[i];
+	for (uint i = 0; i < _activeParty.size(); ++i) {
+		_roster[_activeParty[i]._rosterId] = _activeParty[i];
 	}
 }
 
@@ -257,7 +271,7 @@ void Party::changeTime(int numMinutes) {
 	bool killed = false;
 
 	if (((_minutes + numMinutes) / 480) != (_minutes / 480)) {
-		for (int idx = 0; idx < _partyCount; ++idx) {
+		for (int idx = 0; idx < (int)_activeParty.size(); ++idx) {
 			Character &player = _activeParty[idx];
 
 			if (!player._conditions[DEAD] && !player._conditions[STONED] &&
@@ -333,7 +347,7 @@ void Party::changeTime(int numMinutes) {
 	// Increment the time
 	addTime(numMinutes);
 
-	for (int idx = 0; idx < _partyCount; ++idx) {
+	for (int idx = 0; idx < (int)_activeParty.size(); ++idx) {
 		Character &player = _activeParty[idx];
 
 		if (player._conditions[CONFUSED] && _vm->getRandomNumber(2) == 1) {
@@ -383,7 +397,7 @@ void Party::addTime(int numMinutes) {
 			if (_rested || _vm->_mode == MODE_SLEEPING) {
 				_rested = false;
 			} else {
-				for (int idx = 0; idx < _partyCount; ++idx) {
+				for (int idx = 0; idx < (int)_activeParty.size(); ++idx) {
 					if (_activeParty[idx]._conditions[WEAK] >= 0)
 						_activeParty[idx]._conditions[WEAK]++;
 				}
@@ -399,7 +413,7 @@ void Party::addTime(int numMinutes) {
 }
 
 void Party::resetTemps() {
-	for (int idx = 0; idx < _partyCount; ++idx) {
+	for (int idx = 0; idx < (int)_activeParty.size(); ++idx) {
 		Character &player = _activeParty[idx];
 
 		player._magicResistence._temporary = 0;
diff --git a/engines/xeen/party.h b/engines/xeen/party.h
index a91b398..58bfbd2 100644
--- a/engines/xeen/party.h
+++ b/engines/xeen/party.h
@@ -44,6 +44,7 @@ enum Difficulty { ADVENTURER = 0, WARRIOR = 1 };
 #define TOTAL_CHARACTERS 30
 #define XEEN_TOTAL_CHARACTERS 24
 #define MAX_ACTIVE_PARTY 6
+#define MAX_PARTY_COUNT 8
 #define TOTAL_STATS 7
 #define TOTAL_QUEST_ITEMS 85
 #define TOTAL_QUEST_FLAGS 56
@@ -64,9 +65,6 @@ private:
 	static XeenEngine *_vm;
 public:
 	// Dynamic data that's saved
-	int _partyCount;
-	int _realPartyCount;
-	int _partyMembers[8];
 	Direction _mazeDirection;
 	Common::Point _mazePosition;
 	int _mazeId;
diff --git a/engines/xeen/resources.cpp b/engines/xeen/resources.cpp
index e917850..d309fe9 100644
--- a/engines/xeen/resources.cpp
+++ b/engines/xeen/resources.cpp
@@ -1436,4 +1436,10 @@ const char *const SOME_CHARS_MAY_DIE = "Some Chars may die. Rest anyway?";
 
 const char *const CANT_DISMISS_LAST_CHAR = "You cannot dismiss your last character!";
 
+const char *const REMOVE_DELETE[2] = { "Remove", "Delete" };
+
+const char *const REMOVE_OR_DELETE_WHICH = "\x3l\t010\v005%s which character?";
+
+const char *const YOUR_PARTY_IS_FULL = "\v007Your party is full!";
+
 } // End of namespace Xeen
diff --git a/engines/xeen/resources.h b/engines/xeen/resources.h
index d4e1c11..a1734ce 100644
--- a/engines/xeen/resources.h
+++ b/engines/xeen/resources.h
@@ -495,6 +495,11 @@ extern const char *const SOME_CHARS_MAY_DIE;
 
 extern const char *const CANT_DISMISS_LAST_CHAR;
 
+extern const char *const REMOVE_DELETE[2];
+extern const char *const REMOVE_OR_DELETE_WHICH;
+
+extern const char *const YOUR_PARTY_IS_FULL;
+
 } // End of namespace Xeen
 
 #endif	/* XEEN_RESOURCES_H */
diff --git a/engines/xeen/scripts.cpp b/engines/xeen/scripts.cpp
index 7ced6af..6ab4c1f 100644
--- a/engines/xeen/scripts.cpp
+++ b/engines/xeen/scripts.cpp
@@ -426,7 +426,7 @@ void Scripts::cmdIf(Common::Array<byte> &params) {
 		result = ifProc(params[0], mask, _event->_opcode - 8, _charIndex - 1);
 	} else {
 		result = false;
-		for (int idx = 0; idx < party._partyCount && !result; ++idx) {
+		for (int idx = 0; idx < (int)party._activeParty.size() && !result; ++idx) {
 			if (_charIndex == 0 || (_charIndex == 8 && idx != _v2)) {
 				result = ifProc(params[0], mask, _event->_opcode - 8, idx);
 			}
@@ -488,7 +488,7 @@ void Scripts::cmdSetChar(Common::Array<byte> &params) {
 			return;
 		}
 	} else {
-		_charIndex = _vm->getRandomNumber(1, _vm->_party->_partyCount);
+		_charIndex = _vm->getRandomNumber(1, _vm->_party->_activeParty.size());
 	}
 
 	_v2 = 1;
@@ -576,7 +576,7 @@ void Scripts::cmdGiveExtended(Common::Array<byte> &params) {
 		result = ifProc(params[0], mask, _event->_opcode - OP_If1, _charIndex - 1);
 	} else {
 		result = false;
-		for (int idx = 0; idx < party._partyCount && !result; ++idx) {
+		for (int idx = 0; idx < (int)party._activeParty.size() && !result; ++idx) {
 			if (_charIndex == 0 || (_charIndex == 8 && _v2 != idx)) {
 				result = ifProc(params[0], mask, _event->_opcode - OP_If1, idx);
 			}
@@ -726,7 +726,7 @@ void Scripts::cmdSetVar(Common::Array<byte> &params) {
 		party._activeParty[_charIndex - 1].setValue(params[0], val);
 	} else {
 		// Set value for entire party
-		for (int idx = 0; idx < party._partyCount; ++idx) {
+		for (int idx = 0; idx < (int)party._activeParty.size(); ++idx) {
 			if (_charIndex == 0 || (_charIndex == 8 && _v2 != idx)) {
 				party._activeParty[idx].setValue(params[0], val);
 			}
@@ -870,7 +870,7 @@ void Scripts::doEndGame2() {
 	Party &party = *_vm->_party;
 	int v2 = 0;
 
-	for (int idx = 0; idx < party._partyCount; ++idx) {
+	for (uint idx = 0; idx < party._activeParty.size(); ++idx) {
 		Character &player = party._activeParty[idx];
 		if (player.hasAward(77)) {
 			v2 = 2;
diff --git a/engines/xeen/town.cpp b/engines/xeen/town.cpp
index 25f332a..f68a554 100644
--- a/engines/xeen/town.cpp
+++ b/engines/xeen/town.cpp
@@ -532,7 +532,7 @@ Character *Town::doBlacksmithOptions(Character *c) {
 	if (_buttonValue >= Common::KEYCODE_F1 && _buttonValue <= Common::KEYCODE_F6) {
 		// Switch character
 		_buttonValue -= Common::KEYCODE_F1;
-		if (_buttonValue < party._partyCount) {
+		if (_buttonValue < (int)party._activeParty.size()) {
 			c = &party._activeParty[_buttonValue];
 			intf.highlightChar(_buttonValue);
 		}
@@ -554,7 +554,7 @@ Character *Town::doGuildOptions(Character *c) {
 	if (_buttonValue >= Common::KEYCODE_F1 && _buttonValue <= Common::KEYCODE_F6) {
 		// Switch character
 		_buttonValue -= Common::KEYCODE_F1;
-		if (_buttonValue < party._partyCount) {
+		if (_buttonValue < (int)party._activeParty.size()) {
 			c = &party._activeParty[_buttonValue];
 			intf.highlightChar(_buttonValue);
 
@@ -598,7 +598,7 @@ Character *Town::doTavernOptions(Character *c) {
 	case Common::KEYCODE_F6:
 		// Switch character
 		_buttonValue -= Common::KEYCODE_F1;
-		if (_buttonValue < party._partyCount) {
+		if (_buttonValue < (int)party._activeParty.size()) {
 			c = &party._activeParty[_buttonValue];
 			intf.highlightChar(_buttonValue);
 			_v21 = 0;
@@ -632,27 +632,27 @@ Character *Town::doTavernOptions(Character *c) {
 	case Common::KEYCODE_f: {
 		// Food
 		if (party._mazeId == (isDarkCc ? 29 : 28)) {
-			_v22 = party._partyCount * 15;
+			_v22 = party._activeParty.size() * 15;
 			_v23 = 10;
 			idx = 0;
 		} else if (isDarkCc && party._mazeId == 31) {
-			_v22 = party._partyCount * 60;
+			_v22 = party._activeParty.size() * 60;
 			_v23 = 100;
 			idx = 1;
 		} else if (!isDarkCc && party._mazeId == 30) {
-			_v22 = party._partyCount * 50;
+			_v22 = party._activeParty.size() * 50;
 			_v23 = 50;
 			idx = 1;
 		} else if (isDarkCc) {
-			_v22 = party._partyCount * 120;
+			_v22 = party._activeParty.size() * 120;
 			_v23 = 250;
 			idx = 2;
 		} else if (party._mazeId == 49) {
-			_v22 = party._partyCount * 120;
+			_v22 = party._activeParty.size() * 120;
 			_v23 = 100;
 			idx = 2;
 		} else {
-			_v22 = party._partyCount * 15;
+			_v22 = party._activeParty.size() * 15;
 			_v23 = 10;
 			idx = 0;
 		}
@@ -717,7 +717,7 @@ Character *Town::doTavernOptions(Character *c) {
 			party._mazeDirection = DIR_SOUTH;
 
 		party._priorMazeId = party._mazeId;
-		for (int idx = 0; idx < party._partyCount; ++idx) {
+		for (uint idx = 0; idx < party._activeParty.size(); ++idx) {
 			party._activeParty[idx]._savedMazeId = party._mazeId;
 			party._activeParty[idx]._xeenSide = map._loadDarkSide;
 		}
@@ -799,7 +799,7 @@ Character *Town::doTempleOptions(Character *c) {
 	case Common::KEYCODE_F6:
 		// Switch character
 		_buttonValue -= Common::KEYCODE_F1;
-		if (_buttonValue < party._partyCount) {
+		if (_buttonValue < (int)party._activeParty.size()) {
 			c = &party._activeParty[_buttonValue];
 			intf.highlightChar(_buttonValue);
 			_dayOfWeek = 0;
@@ -900,7 +900,7 @@ Character *Town::doTrainingOptions(Character *c) {
 	case Common::KEYCODE_F6:
 		// Switch character
 		_buttonValue -= Common::KEYCODE_F1;
-		if (_buttonValue < party._partyCount) {
+		if (_buttonValue < (int)party._activeParty.size()) {
 			_v2 = _buttonValue;
 			c = &party._activeParty[_buttonValue];
 			intf.highlightChar(_buttonValue);


Commit: 2f39bd5cd259cd5af16543338f4bb6a930191786
    https://github.com/scummvm/scummvm/commit/2f39bd5cd259cd5af16543338f4bb6a930191786
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-02-11T20:04:38-05:00

Commit Message:
XEEN: Fixes for display of party dialog

Changed paths:
    engines/xeen/dialogs_party.cpp
    engines/xeen/dialogs_party.h
    engines/xeen/interface.cpp
    engines/xeen/resources.cpp
    engines/xeen/resources.h



diff --git a/engines/xeen/dialogs_party.cpp b/engines/xeen/dialogs_party.cpp
index 618d297..9de0346 100644
--- a/engines/xeen/dialogs_party.cpp
+++ b/engines/xeen/dialogs_party.cpp
@@ -32,6 +32,7 @@ namespace Xeen {
 
 PartyDialog::PartyDialog(XeenEngine *vm) : ButtonContainer(), 
 		PartyDrawer(vm), _vm(vm) {
+	initDrawStructs();
 }
 
 void PartyDialog::show(XeenEngine *vm) {
@@ -68,7 +69,7 @@ void PartyDialog::execute() {
 		Window &w = screen._windows[11];
 		w.open();
 		setupFaces(startingChar, false);
-		w.writeString(_displayText);
+		w.writeString(Common::String::format(PARTY_DIALOG_TEXT, _partyDetails.c_str()));
 		w.drawList(&_faceDrawStructs[0], 4);
 
 		_uiSprites.draw(w, 0, Common::Point(16, 100));
@@ -99,8 +100,10 @@ void PartyDialog::execute() {
 
 		bool breakFlag = false;
 		while (!_vm->shouldQuit() && !breakFlag) {
-			events.pollEventsAndWait();
-			checkEvents(_vm);
+			do {
+				events.pollEventsAndWait();
+				checkEvents(_vm);
+			} while (!_vm->shouldQuit() && !_buttonValue);
 
 			switch (_buttonValue) {
 			case Common::KEYCODE_ESCAPE:
@@ -226,7 +229,7 @@ void PartyDialog::loadButtons() {
 	addButton(Common::Rect(87, 100, 111, 120), Common::KEYCODE_d, &_uiSprites);
 	addButton(Common::Rect(122, 100, 146, 120), Common::KEYCODE_r, &_uiSprites);
 	addButton(Common::Rect(157, 100, 181, 120), Common::KEYCODE_c, &_uiSprites);
-	addButton(Common::Rect(192, 100, 116, 120), Common::KEYCODE_x, &_uiSprites);
+	addButton(Common::Rect(192, 100, 216, 120), Common::KEYCODE_x, &_uiSprites);
 	addButton(Common::Rect(0, 0, 0, 0), Common::KEYCODE_ESCAPE, &_uiSprites, false);
 	addButton(Common::Rect(16, 16, 48, 48), Common::KEYCODE_1, &_uiSprites, false);
 	addButton(Common::Rect(117, 16, 149, 48), Common::KEYCODE_2, &_uiSprites, false);
@@ -247,7 +250,7 @@ void PartyDialog::setupBackground() {
 }
 
 /**
- * Sets up the faces for display in the party dialog
+ * Sets up the faces from the avaialble roster for display in the party dialog
  */
 void PartyDialog::setupFaces(int firstDisplayChar, bool updateFlag) {
 	Party &party = *_vm->_party;
@@ -285,10 +288,11 @@ void PartyDialog::setupFaces(int firstDisplayChar, bool updateFlag) {
 		if ((firstDisplayChar + posIndex) >= (int)_charList.size())
 			_faceDrawStructs[posIndex]._sprites = nullptr;
 		else
-			_faceDrawStructs[posIndex]._sprites = party._roster[posIndex]._faceSprites;
+			_faceDrawStructs[posIndex]._sprites = party._roster[
+				_charList[firstDisplayChar + posIndex]]._faceSprites;
 	}
 
-	_displayText = Common::String::format(PARTY_DETAILS,
+	_partyDetails = Common::String::format(PARTY_DETAILS,
 		charNames[0].c_str(), charRaces[0].c_str(), charSex[0].c_str(), charClasses[0].c_str(),
 		charNames[1].c_str(), charRaces[1].c_str(), charSex[1].c_str(), charClasses[1].c_str(),
 		charNames[2].c_str(), charRaces[2].c_str(), charSex[2].c_str(), charClasses[2].c_str(),
@@ -300,7 +304,7 @@ void PartyDialog::startingCharChanged(int firstDisplayChar) {
 	Window &w = _vm->_screen->_windows[11];
 
 	setupFaces(firstDisplayChar, true);
-	w.writeString(_displayText);
+	w.writeString(_partyDetails);
 	w.drawList(_faceDrawStructs, 4);
 
 	_uiSprites.draw(w, 0, Common::Point(16, 100));
diff --git a/engines/xeen/dialogs_party.h b/engines/xeen/dialogs_party.h
index 082c43b..1510b76 100644
--- a/engines/xeen/dialogs_party.h
+++ b/engines/xeen/dialogs_party.h
@@ -36,7 +36,7 @@ private:
 	XeenEngine *_vm;
 	SpriteResource _uiSprites;
 	DrawStruct _faceDrawStructs[4];
-	Common::String _displayText;
+	Common::String _partyDetails;
 	Common::Array<int> _charList;
 
 	PartyDialog(XeenEngine *vm);
@@ -49,8 +49,6 @@ private:
 
 	void setupBackground();
 
-	void drawParty(bool updateFlag);
-
 	void setupFaces(int firstDisplayChar, bool updateFlag);
 
 	void startingCharChanged(int firstDisplayChar);
diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp
index b88b64a..b8e6437 100644
--- a/engines/xeen/interface.cpp
+++ b/engines/xeen/interface.cpp
@@ -31,6 +31,8 @@
 #include "xeen/resources.h"
 #include "xeen/xeen.h"
 
+#include "xeen/dialogs_party.h"
+
 namespace Xeen {
 
 PartyDrawer::PartyDrawer(XeenEngine *vm): _vm(vm) {
@@ -501,6 +503,9 @@ void Interface::perform() {
 		Quests::show(_vm);
 		break;
 
+	case Common::KEYCODE_x:
+		// ****DEBUG***
+		PartyDialog::show(_vm); //***DEBUG****
 	default:
 		break;
 	}
diff --git a/engines/xeen/resources.cpp b/engines/xeen/resources.cpp
index d309fe9..d79ef80 100644
--- a/engines/xeen/resources.cpp
+++ b/engines/xeen/resources.cpp
@@ -354,6 +354,9 @@ const char *const PARTY_DETAILS = "\015\003l\002\014""00"
 	"\013""052""\011""136%s" 
 	"\013""060""\011""136%s" 
 	"\013""068""\011""136%s";
+const char *const PARTY_DIALOG_TEXT =
+	"%s\x2\x3""c\v106\t013Up\t048Down\t083\f37D\fdel\t118\f37R\fdem"
+	"\t153\f37C\fdreate\t188E\f37x\fdit\x1";
 
 const int FACE_CONDITION_FRAMES[17] = { 
 	2, 2, 2, 1, 1, 4, 4, 4, 3, 2, 4, 3, 3, 5, 6, 7, 0 
diff --git a/engines/xeen/resources.h b/engines/xeen/resources.h
index a1734ce..0e90a29 100644
--- a/engines/xeen/resources.h
+++ b/engines/xeen/resources.h
@@ -105,6 +105,7 @@ extern const char *const HEROISM;
 extern const char *const IN_PARTY;
 
 extern const char *const PARTY_DETAILS;
+extern const char *const PARTY_DIALOG_TEXT;
 
 extern const int FACE_CONDITION_FRAMES[17];
 


Commit: 6548dd05e316588bde3eae5db10793f8c6effd7b
    https://github.com/scummvm/scummvm/commit/6548dd05e316588bde3eae5db10793f8c6effd7b
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-02-11T21:04:05-05:00

Commit Message:
XEEN: Fix removing and adding chars to party in Party dialog

Changed paths:
    engines/xeen/dialogs.cpp
    engines/xeen/dialogs.h
    engines/xeen/dialogs_error.cpp
    engines/xeen/dialogs_party.cpp



diff --git a/engines/xeen/dialogs.cpp b/engines/xeen/dialogs.cpp
index ff4eaf6..33eda14 100644
--- a/engines/xeen/dialogs.cpp
+++ b/engines/xeen/dialogs.cpp
@@ -51,6 +51,15 @@ void ButtonContainer::addButton(const Common::Rect &bounds, int val, SpriteResou
 	_buttons.push_back(UIButton(bounds, val, sprites, draw));
 }
 
+void ButtonContainer::addPartyButtons(XeenEngine *vm) {
+	Party &party = *vm->_party;
+
+	for (uint idx = 0; idx < party._activeParty.size(); ++idx) {
+		addButton(Common::Rect(CHAR_FACES_X[idx], 150, CHAR_FACES_X[idx] + 32, 182),
+			Common::KEYCODE_F1 + idx, nullptr, false);
+	}
+}
+
 bool ButtonContainer::checkEvents(XeenEngine *vm) {
 	EventsManager &events = *vm->_events;
 	_buttonValue = 0;
diff --git a/engines/xeen/dialogs.h b/engines/xeen/dialogs.h
index d8a9123..ba27fe9 100644
--- a/engines/xeen/dialogs.h
+++ b/engines/xeen/dialogs.h
@@ -67,6 +67,8 @@ public:
 	void restoreButtons();
 
 	void addButton(const Common::Rect &bounds, int val, SpriteResource *sprites, bool draw = true);
+
+	void addPartyButtons(XeenEngine *vm);
 };
 
 class SettingsBaseDialog : public ButtonContainer {
diff --git a/engines/xeen/dialogs_error.cpp b/engines/xeen/dialogs_error.cpp
index 4fe39db..db2603a 100644
--- a/engines/xeen/dialogs_error.cpp
+++ b/engines/xeen/dialogs_error.cpp
@@ -44,7 +44,7 @@ void ErrorDialog::execute(const Common::String &msg, ErrorWaitType waitType) {
 
 	switch (waitType) {
 	case WT_FREEZE_WAIT:
-		while (!_vm->shouldQuit() && !events.isKeyPending())
+		while (!_vm->shouldQuit() && !events.isKeyMousePressed())
 			events.pollEventsAndWait();
 
 		events.clearEvents();
@@ -71,6 +71,8 @@ void ErrorDialog::execute(const Common::String &msg, ErrorWaitType waitType) {
 	default:
 		break;
 	}
+
+	w.close();
 }
 
 /*------------------------------------------------------------------------*/
diff --git a/engines/xeen/dialogs_party.cpp b/engines/xeen/dialogs_party.cpp
index 9de0346..e1a6dbc 100644
--- a/engines/xeen/dialogs_party.cpp
+++ b/engines/xeen/dialogs_party.cpp
@@ -56,7 +56,8 @@ void PartyDialog::execute() {
 	while (!_vm->shouldQuit()) {
 		_vm->_mode = MODE_1;
 
-		// Build up a list of characters on the same Xeen side being loaded
+		// Build up a list of available characters in the Roster that are on the
+		// same side of Xeen as the player is currently on
 		_charList.clear();
 		for (int i = 0; i < XEEN_TOTAL_CHARACTERS; ++i) {
 			Character &player = party._roster[i];
@@ -159,28 +160,37 @@ void PartyDialog::execute() {
 							break;
 					}
 
+					// Only add the character if they're not already in the party
 					if (idx == party._activeParty.size()) {
-						sound.playFX(21);
-						ErrorScroll::show(_vm, YOUR_PARTY_IS_FULL);
-					} else {
-						party._activeParty.push_back(party._roster[
-							_charList[_buttonValue - 7 + startingChar]]);
-						error("TODO");
+						if (party._activeParty.size() == MAX_ACTIVE_PARTY) {
+							sound.playFX(21);
+							ErrorScroll::show(_vm, YOUR_PARTY_IS_FULL);
+						} else {
+							// Add the character to the active party
+							party._activeParty.push_back(party._roster[
+								_charList[_buttonValue - 7 + startingChar]]);
+								startingCharChanged(startingChar);
+						}
 					}
 				}
-				// TODO
 				break;
 
 			case Common::KEYCODE_UP:
 			case Common::KEYCODE_KP8:
+				// Up arrow
 				if (startingChar > 0) {
 					startingChar -= 4;
 					startingCharChanged(startingChar);
 				}
 				break;
+
 			case Common::KEYCODE_DOWN:
 			case Common::KEYCODE_KP2:
-				// TODO
+				// Down arrow
+				if (startingChar < (_charList.size() - 4)) {
+					startingChar += 4;
+					startingCharChanged(startingChar);
+				}
 				break;
 
 			case Common::KEYCODE_c:
@@ -231,10 +241,6 @@ void PartyDialog::loadButtons() {
 	addButton(Common::Rect(157, 100, 181, 120), Common::KEYCODE_c, &_uiSprites);
 	addButton(Common::Rect(192, 100, 216, 120), Common::KEYCODE_x, &_uiSprites);
 	addButton(Common::Rect(0, 0, 0, 0), Common::KEYCODE_ESCAPE, &_uiSprites, false);
-	addButton(Common::Rect(16, 16, 48, 48), Common::KEYCODE_1, &_uiSprites, false);
-	addButton(Common::Rect(117, 16, 149, 48), Common::KEYCODE_2, &_uiSprites, false);
-	addButton(Common::Rect(59, 59, 91, 91), Common::KEYCODE_3, &_uiSprites, false);
-	addButton(Common::Rect(117, 59, 151, 91), Common::KEYCODE_4, &_uiSprites, false);
 }
 
 void PartyDialog::initDrawStructs() {
@@ -261,6 +267,15 @@ void PartyDialog::setupFaces(int firstDisplayChar, bool updateFlag) {
 	int posIndex;
 	int charId;
 
+	// Reset the button areas for the display character images
+	while (_buttons.size() > 7)
+		_buttons.remove_at(7);
+	addButton(Common::Rect(16, 16, 48, 48), Common::KEYCODE_1, &_uiSprites, false);
+	addButton(Common::Rect(117, 16, 149, 48), Common::KEYCODE_2, &_uiSprites, false);
+	addButton(Common::Rect(59, 59, 91, 91), Common::KEYCODE_3, &_uiSprites, false);
+	addButton(Common::Rect(117, 59, 151, 91), Common::KEYCODE_4, &_uiSprites, false);
+
+
 	for (posIndex = 0; posIndex < 4; ++posIndex) {
 		charId = (firstDisplayChar + posIndex) >= (int)_charList.size() ? -1 :
 			_charList[firstDisplayChar + posIndex];
@@ -304,7 +319,7 @@ void PartyDialog::startingCharChanged(int firstDisplayChar) {
 	Window &w = _vm->_screen->_windows[11];
 
 	setupFaces(firstDisplayChar, true);
-	w.writeString(_partyDetails);
+	w.writeString(Common::String::format(PARTY_DIALOG_TEXT, _partyDetails.c_str()));
 	w.drawList(_faceDrawStructs, 4);
 
 	_uiSprites.draw(w, 0, Common::Point(16, 100));
@@ -344,6 +359,7 @@ int PartyDialog::selectCharacter(bool isDelete, int firstDisplayChar) {
 	addButton(Common::Rect(117, 16, 149, 48), Common::KEYCODE_2, &iconSprites, false);
 	addButton(Common::Rect(16, 59, 48, 91), Common::KEYCODE_3, &iconSprites, false);
 	addButton(Common::Rect(117, 59, 149, 91), Common::KEYCODE_4, &iconSprites, false);
+	addPartyButtons(_vm);
 
 	int result = -1, v;
 	while (!_vm->shouldQuit() && result == -1) {
@@ -364,18 +380,23 @@ int PartyDialog::selectCharacter(bool isDelete, int firstDisplayChar) {
 		case Common::KEYCODE_F4:
 		case Common::KEYCODE_F5:
 		case Common::KEYCODE_F6:
-			v = _buttonValue - Common::KEYCODE_F1;
-			if (v < (int)party._activeParty.size())
-				result = _buttonValue;
+			if (!isDelete) {
+				v = _buttonValue - Common::KEYCODE_F1;
+				if (v < (int)party._activeParty.size())
+					result = _buttonValue;
+			}
 			break;
 
 		case Common::KEYCODE_1:
 		case Common::KEYCODE_2:
 		case Common::KEYCODE_3:
 		case Common::KEYCODE_4:
-			v = _buttonValue - Common::KEYCODE_1;
-			if ((firstDisplayChar + v) < (int)_charList.size())
-				result = _buttonValue;
+			if (isDelete) {
+				v = _buttonValue - Common::KEYCODE_1;
+				if ((firstDisplayChar + v) < (int)_charList.size())
+					result = _buttonValue;
+			}
+			break;
 
 		default:
 			break;


Commit: a39b0b24a1dccec3e91f45deb047fa027372d84f
    https://github.com/scummvm/scummvm/commit/a39b0b24a1dccec3e91f45deb047fa027372d84f
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-02-11T21:09:07-05:00

Commit Message:
XEEN: Fix changing selected character with mouse in various dialogs

Changed paths:
    engines/xeen/dialogs.cpp
    engines/xeen/dialogs_char_info.cpp
    engines/xeen/dialogs_items.cpp
    engines/xeen/interface.cpp



diff --git a/engines/xeen/dialogs.cpp b/engines/xeen/dialogs.cpp
index 33eda14..a2535fd 100644
--- a/engines/xeen/dialogs.cpp
+++ b/engines/xeen/dialogs.cpp
@@ -54,7 +54,7 @@ void ButtonContainer::addButton(const Common::Rect &bounds, int val, SpriteResou
 void ButtonContainer::addPartyButtons(XeenEngine *vm) {
 	Party &party = *vm->_party;
 
-	for (uint idx = 0; idx < party._activeParty.size(); ++idx) {
+	for (uint idx = 0; idx < MAX_ACTIVE_PARTY; ++idx) {
 		addButton(Common::Rect(CHAR_FACES_X[idx], 150, CHAR_FACES_X[idx] + 32, 182),
 			Common::KEYCODE_F1 + idx, nullptr, false);
 	}
diff --git a/engines/xeen/dialogs_char_info.cpp b/engines/xeen/dialogs_char_info.cpp
index de16e95..df4b699 100644
--- a/engines/xeen/dialogs_char_info.cpp
+++ b/engines/xeen/dialogs_char_info.cpp
@@ -274,6 +274,7 @@ void CharacterInfo::addButtons() {
 	addButton(Common::Rect(285, 43, 309, 63), Common::KEYCODE_q, &_iconSprites);
 	addButton(Common::Rect(285, 75, 309, 95), Common::KEYCODE_e, &_iconSprites);
 	addButton(Common::Rect(285, 107, 309, 127), Common::KEYCODE_ESCAPE, &_iconSprites);
+	addPartyButtons(_vm);
 }
 
 /**
diff --git a/engines/xeen/dialogs_items.cpp b/engines/xeen/dialogs_items.cpp
index 7b4e23e..d37d124 100644
--- a/engines/xeen/dialogs_items.cpp
+++ b/engines/xeen/dialogs_items.cpp
@@ -557,6 +557,7 @@ void ItemsDialog::loadButtons(ItemsMode mode, Character *&c) {
 		addButton(Common::Rect(8, 74, 263, 82), Common::KEYCODE_7, &_iconSprites, false);
 		addButton(Common::Rect(8, 83, 263, 91), Common::KEYCODE_8, &_iconSprites, false);
 		addButton(Common::Rect(8, 92, 263, 100), Common::KEYCODE_9, &_iconSprites, false);
+		addPartyButtons(_vm);
 	}
 
 	if (mode == ITEMMODE_BLACKSMITH) {
diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp
index b8e6437..0916abe 100644
--- a/engines/xeen/interface.cpp
+++ b/engines/xeen/interface.cpp
@@ -219,6 +219,7 @@ void Interface::setMainButtons() {
 	addButton(Common::Rect(239,  27, 312,  37),  Common::KEYCODE_1, &_iconSprites, false);
 	addButton(Common::Rect(239, 37, 312, 47), Common::KEYCODE_2, &_iconSprites, false);
 	addButton(Common::Rect(239, 47, 312, 57), Common::KEYCODE_3, &_iconSprites, false);
+	addPartyButtons(_vm);
 }
 
 /**


Commit: 2772cd33c1f62d0e0ea41507f6b809704d569254
    https://github.com/scummvm/scummvm/commit/2772cd33c1f62d0e0ea41507f6b809704d569254
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-02-11T23:37:03-05:00

Commit Message:
XEEN: Implemented code for deleting characters in Party dialog

Changed paths:
    engines/xeen/character.cpp
    engines/xeen/character.h
    engines/xeen/dialogs_party.cpp
    engines/xeen/resources.cpp
    engines/xeen/resources.h



diff --git a/engines/xeen/character.cpp b/engines/xeen/character.cpp
index e7b5d23..ac25b32 100644
--- a/engines/xeen/character.cpp
+++ b/engines/xeen/character.cpp
@@ -1787,5 +1787,14 @@ void Character::subtractHitPoints(int amount) {
 	}
 }
 
+bool Character::hasSpecialItem() const {
+	for (uint idx = 0; idx < INV_ITEMS_TOTAL; ++idx) {
+		if (_weapons[idx]._id == 34)
+			// Character has Xeen Slayer sword
+			return true;
+	}
+
+	return false;
+}
 
 } // End of namespace Xeen
diff --git a/engines/xeen/character.h b/engines/xeen/character.h
index 59f4ba6..492e5e2 100644
--- a/engines/xeen/character.h
+++ b/engines/xeen/character.h
@@ -315,6 +315,8 @@ public:
 	int makeItem(int p1, int itemIndex, int p3);
 
 	void subtractHitPoints(int amount);
+
+	bool hasSpecialItem() const;
 };
 
 } // End of namespace Xeen
diff --git a/engines/xeen/dialogs_party.cpp b/engines/xeen/dialogs_party.cpp
index e1a6dbc..eece1e3 100644
--- a/engines/xeen/dialogs_party.cpp
+++ b/engines/xeen/dialogs_party.cpp
@@ -23,6 +23,7 @@
 #include "common/scummsys.h"
 #include "xeen/dialogs_char_info.h"
 #include "xeen/dialogs_party.h"
+#include "xeen/dialogs_query.h"
 #include "xeen/character.h"
 #include "xeen/events.h"
 #include "xeen/party.h"
@@ -187,7 +188,7 @@ void PartyDialog::execute() {
 			case Common::KEYCODE_DOWN:
 			case Common::KEYCODE_KP2:
 				// Down arrow
-				if (startingChar < (_charList.size() - 4)) {
+				if (startingChar < ((int)_charList.size() - 4)) {
 					startingChar += 4;
 					startingCharChanged(startingChar);
 				}
@@ -210,9 +211,47 @@ void PartyDialog::execute() {
 					breakFlag = true;
 				}
 				break;
+
 			case Common::KEYCODE_d:
 				// Delete character
+				if (_charList.size() > 0) {
+					int charButtonValue = selectCharacter(true, startingChar);
+					if (charButtonValue != 0) {
+						int charIndex = charButtonValue - Common::KEYCODE_1 + startingChar;
+						Character &c = party._roster[_charList[charIndex]];
+						if (c.hasSpecialItem()) {
+							ErrorScroll::show(_vm, HAS_SLAYER_SWORD);
+						} else {
+							Common::String msg = Common::String::format(SURE_TO_DELETE_CHAR,
+								c._name.c_str(), CLASS_NAMES[c._class]);
+							if (Confirm::show(_vm, msg)) {
+								// If the character is in the party, remove it
+								for (uint idx = 0; idx < party._activeParty.size(); ++idx) {
+									if (party._activeParty[idx]._rosterId == c._rosterId) {
+										party._activeParty.remove_at(idx);
+										break;
+									}
+								}
+
+								// Empty the character in the roster
+								c.clear();
+
+								// Rebuild the character list
+								_charList.clear();
+								for (int idx = 0; idx < XEEN_TOTAL_CHARACTERS; ++idx) {
+									Character &c = party._roster[idx];
+									if (!c._name.empty() && c._savedMazeId == party._priorMazeId) {
+										_charList.push_back(idx);
+									}
+								}
+
+								startingCharChanged(startingChar);
+							}
+						}
+					}
+				}
 				break;
+
 			case Common::KEYCODE_r:
 				// Remove character
 				if (party._activeParty.size() > 0) {
diff --git a/engines/xeen/resources.cpp b/engines/xeen/resources.cpp
index d79ef80..8f14753 100644
--- a/engines/xeen/resources.cpp
+++ b/engines/xeen/resources.cpp
@@ -1445,4 +1445,9 @@ const char *const REMOVE_OR_DELETE_WHICH = "\x3l\t010\v005%s which character?";
 
 const char *const YOUR_PARTY_IS_FULL = "\v007Your party is full!";
 
+const char *const HAS_SLAYER_SWORD =
+	"\v000\t000This character has the Xeen Slayer Sword and cannot be deleted!";
+const char *const SURE_TO_DELETE_CHAR = 
+	"Are you sure you want to delete %s the %s?";
+
 } // End of namespace Xeen
diff --git a/engines/xeen/resources.h b/engines/xeen/resources.h
index 0e90a29..2ca9dbb 100644
--- a/engines/xeen/resources.h
+++ b/engines/xeen/resources.h
@@ -501,6 +501,9 @@ extern const char *const REMOVE_OR_DELETE_WHICH;
 
 extern const char *const YOUR_PARTY_IS_FULL;
 
+extern const char *const HAS_SLAYER_SWORD;
+extern const char *const SURE_TO_DELETE_CHAR;
+
 } // End of namespace Xeen
 
 #endif	/* XEEN_RESOURCES_H */


Commit: e16ecd110b2f607621773e13df8f972c9c7e979a
    https://github.com/scummvm/scummvm/commit/e16ecd110b2f607621773e13df8f972c9c7e979a
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-02-12T23:16:20-05:00

Commit Message:
XEEN: Implementing create chracter dialog

Changed paths:
    engines/xeen/character.h
    engines/xeen/dialogs_party.cpp
    engines/xeen/dialogs_party.h
    engines/xeen/resources.cpp
    engines/xeen/resources.h



diff --git a/engines/xeen/character.h b/engines/xeen/character.h
index 492e5e2..9e8687d 100644
--- a/engines/xeen/character.h
+++ b/engines/xeen/character.h
@@ -49,13 +49,13 @@ enum Race { HUMAN = 0, ELF = 1, DWARF = 2, GNOME = 3, HALF_ORC = 4 };
 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_DRUID = 8, CLASS_RANGER = 9, TOTAL_CLASSES = 10,
 	CLASS_12 = 12, CLASS_15 = 15, CLASS_16 = 16
 };
 
 enum Attribute {
 	MIGHT = 0, INTELLECT = 1, PERSONALITY = 2, ENDURANCE = 3, SPEED = 4,
-	ACCURACY = 5, LUCK = 6
+	ACCURACY = 5, LUCK = 6, TOTAL_ATTRIBUTES = 7
 };
 
 enum Skill {
diff --git a/engines/xeen/dialogs_party.cpp b/engines/xeen/dialogs_party.cpp
index eece1e3..ff59363 100644
--- a/engines/xeen/dialogs_party.cpp
+++ b/engines/xeen/dialogs_party.cpp
@@ -372,7 +372,136 @@ void PartyDialog::startingCharChanged(int firstDisplayChar) {
 }
 
 void PartyDialog::createChar() {
-	error("TODO: createChar");
+	EventsManager &events = *_vm->_events;
+	Party &party = *_vm->_party;
+	Screen &screen = *_vm->_screen;
+	SpriteResource dice, icons;
+	Mode oldMode = _vm->_mode;
+	Common::Array<int> freeCharList;
+	int selectedClass = 0;
+	bool hasFadedIn = false;
+
+	dice.load("dice.vga");
+	icons.load("create.raw");
+
+	// Add buttons
+	saveButtons();
+	addButton(Common::Rect(132, 98, 156, 118), Common::KEYCODE_r, &icons);
+	addButton(Common::Rect(132, 128, 156, 148), Common::KEYCODE_c, &icons);
+	addButton(Common::Rect(132, 158, 156, 178), Common::KEYCODE_ESCAPE, &icons);
+	addButton(Common::Rect(86, 98, 110, 118), Common::KEYCODE_UP, &icons);
+	addButton(Common::Rect(86, 120, 110, 140), Common::KEYCODE_DOWN, &icons);
+	addButton(Common::Rect(168, 19, 192, 39), Common::KEYCODE_n, nullptr);
+	addButton(Common::Rect(168, 43, 192, 63), Common::KEYCODE_i, nullptr);
+	addButton(Common::Rect(168, 67, 192, 87), Common::KEYCODE_p, nullptr);
+	addButton(Common::Rect(168, 91, 192, 111), Common::KEYCODE_e, nullptr);
+	addButton(Common::Rect(168, 115, 192, 135), Common::KEYCODE_s, nullptr);
+	addButton(Common::Rect(168, 139, 192, 159), Common::KEYCODE_a, nullptr);
+	addButton(Common::Rect(168, 163, 192, 183), Common::KEYCODE_l, nullptr);
+	addButton(Common::Rect(227, 19, 139, 29), 1000, nullptr);
+	addButton(Common::Rect(227, 30, 139, 40), 1001, nullptr);
+	addButton(Common::Rect(227, 41, 139, 51), 1002, nullptr);
+	addButton(Common::Rect(227, 52, 139, 62), 1003, nullptr);
+	addButton(Common::Rect(227, 63, 139, 73), 1004, nullptr);
+	addButton(Common::Rect(227, 74, 139, 84), 1005, nullptr);
+	addButton(Common::Rect(227, 85, 139, 95), 1006, nullptr);
+	addButton(Common::Rect(227, 96, 139, 106), 1007, nullptr);
+	addButton(Common::Rect(227, 107, 139, 117), 1008, nullptr);
+	addButton(Common::Rect(227, 118, 139, 128), 1009, nullptr);
+
+	// Load the background
+	screen.loadBackground("create.raw");
+	events.setCursor(0);
+
+	while (!_vm->shouldQuit()) {
+		int classId = -1;
+
+		// Build up list of roster slot indexes that are free
+		freeCharList.clear();
+		for (uint idx = 0; idx < XEEN_TOTAL_CHARACTERS; ++idx) {
+			if (party._roster[idx]._name.empty())
+				freeCharList.push_back(idx);
+		}		
+		int charIndex = 0;
+		//bool flag9 = true;
+
+		if (freeCharList.size() == XEEN_TOTAL_CHARACTERS)
+			break;
+
+		// Get and race and sex for the given character
+		Race race = (Race)((freeCharList[charIndex] / 4) % 5);
+		Sex sex = (Sex)(freeCharList[charIndex] & 1);
+
+		// Randomly determine attributes, and which classes they allow
+		uint attribs[TOTAL_ATTRIBUTES];
+		bool allowedClasses[TOTAL_CLASSES];
+		throwDice(attribs, allowedClasses);
+
+		// Set up display of the rolled character details
+		Common::String msg;
+		selectedClass = newCharDetails(attribs, allowedClasses,
+			race, sex, classId, selectedClass, msg);
+
+		// Draw the screen
+		Window &w = screen._windows[0];
+		icons.draw(w, 10, Common::Point(168, 19));
+		icons.draw(w, 12, Common::Point(168, 43));
+		icons.draw(w, 14, Common::Point(168, 67));
+		icons.draw(w, 16, Common::Point(168, 91));
+		icons.draw(w, 18, Common::Point(168, 115));
+		icons.draw(w, 20, Common::Point(168, 139));
+		icons.draw(w, 22, Common::Point(168, 163));
+		for (int idx = 0; idx < 9; ++idx)
+			icons.draw(w, 24 + idx * 2, Common::Point(227, 19 + 11 * idx));
+
+		for (int idx = 0; idx < 7; ++idx)
+			icons.draw(w, 50 + idx, Common::Point(195, 31 + 24 * idx));
+
+		icons.draw(w, 57, Common::Point(62, 148));
+		icons.draw(w, 58, Common::Point(62, 158));
+		icons.draw(w, 59, Common::Point(62, 168));
+		icons.draw(w, 61, Common::Point(220, 19));
+		icons.draw(w, 64, Common::Point(220, 155));
+		icons.draw(w, 65, Common::Point(220, 170));
+		
+		party._roster[freeCharList[charIndex]]._faceSprites->draw(
+			w, 0, Common::Point(27, 102));
+
+		icons.draw(w, 0, Common::Point(132, 98));
+		icons.draw(w, 2, Common::Point(132, 128));
+		icons.draw(w, 4, Common::Point(132, 158));
+		icons.draw(w, 6, Common::Point(86, 98));
+		icons.draw(w, 8, Common::Point(86, 120));
+
+		w.writeString(msg);
+		w.update();
+
+		// Draw the arrow for the selected class, if applicable
+		if (selectedClass != -1)
+			printSelectionArrow(icons, selectedClass);
+
+		// Draw the dice
+		drawDice(dice);
+		if (!hasFadedIn) {
+			screen.fadeIn(4);
+			hasFadedIn = true;
+		}
+
+		// Key handling loop
+		while (!_vm->shouldQuit()) {
+			// Animate the dice until a user action occurs
+			_buttonValue = 0;
+			while (!_vm->shouldQuit() && !_buttonValue)
+				drawDice(dice);
+
+			// TODO
+		}
+		
+		// TODO: More
+		error("TODO: createChar");
+	}
+
+	_vm->_mode = oldMode;
 }
 
 int PartyDialog::selectCharacter(bool isDelete, int firstDisplayChar) {
@@ -447,4 +576,119 @@ int PartyDialog::selectCharacter(bool isDelete, int firstDisplayChar) {
 	return result == -1 ? 0 : result;
 }
 
+/**
+ * Roll up some random values for the attributes, and return both them as
+ * well as a list of classes that the attributes meet the requirements for
+ */
+void PartyDialog::throwDice(uint attribs[TOTAL_ATTRIBUTES], bool allowedClasses[TOTAL_CLASSES]) {
+	bool repeat = true;
+	do {
+		// Default all the attributes to zero
+		Common::fill(&attribs[0], &attribs[TOTAL_ATTRIBUTES], 0);
+
+		// Assign random amounts to each attribute
+		for (int idx1 = 0; idx1 < 3; ++idx1) {
+			for (int idx2 = 0; idx2 < TOTAL_ATTRIBUTES; ++idx2) {
+				attribs[idx1] += _vm->getRandomNumber(10, 79) / 10;
+			}
+		}
+
+		// Check which classes are allowed based on the rolled attributes
+		checkClass(attribs, allowedClasses);
+
+		// Only exit if the attributes allow for at least one class
+		for (int idx = 0; idx < TOTAL_CLASSES; ++idx) {
+			if (allowedClasses[idx])
+				repeat = false;
+		}
+	} while (repeat);
+}
+
+/**
+ * Set a list of flags for which classes the passed attribute set meet the
+ * minimum requirements of
+ */
+void PartyDialog::checkClass(const uint attribs[TOTAL_ATTRIBUTES], bool allowedClasses[TOTAL_CLASSES]) {
+	allowedClasses[CLASS_KNIGHT] = attribs[MIGHT] >= 15;
+	allowedClasses[CLASS_PALADIN] = attribs[MIGHT] >= 13
+		&& attribs[PERSONALITY] >= 13 && attribs[ENDURANCE] >= 13;
+	allowedClasses[CLASS_ARCHER] = attribs[INTELLECT] >= 13 && attribs[ACCURACY] >= 13;
+	allowedClasses[CLASS_CLERIC] = attribs[PERSONALITY] >= 13;
+	allowedClasses[CLASS_SORCERER] = attribs[INTELLECT] >= 13;
+	allowedClasses[CLASS_ROBBER] = attribs[LUCK] >= 13;
+	allowedClasses[CLASS_NINJA] = attribs[SPEED] >= 13 && attribs[ACCURACY] >= 13;
+	allowedClasses[CLASS_BARBARIAN] = attribs[ENDURANCE] >= 15;
+	allowedClasses[CLASS_DRUID] = attribs[INTELLECT] >= 15 && attribs[PERSONALITY] >= 15;
+	allowedClasses[CLASS_RANGER] = attribs[INTELLECT] >= 12 && attribs[PERSONALITY] >= 12
+		&& attribs[ENDURANCE] >= 12 && attribs[SPEED] >= 12;
+}
+
+/**
+ * Return details of the generated character
+ */
+int PartyDialog::newCharDetails(const uint attribs[TOTAL_ATTRIBUTES],
+		bool allowedClasses[TOTAL_CLASSES], Race race, Sex sex, int classId, 
+		int selectedClass, Common::String &msg) {
+	int foundClass = -1;
+	Common::String skillStr, classStr, raceSkillStr;
+
+	// If a selected class is provided, set the default skill for that class
+	if (classId != -1 && NEW_CHAR_SKILLS[classId] != -1) {
+		const char *skillP = SKILL_NAMES[NEW_CHAR_SKILLS[classId]];
+		skillStr = Common::String(skillP, skillP + NEW_CHAR_SKILLS_LEN[classId]);
+	}
+
+	// If a class is provided, set the class name
+	if (classId != -1) {
+		classStr = Common::String::format("\t062\v168%s", CLASS_NAMES[classId]);
+	}
+
+	// Set up default skill for the race, if any
+	if (NEW_CHAR_RACE_SKILLS[race] != -1) {
+		raceSkillStr = SKILL_NAMES[NEW_CHAR_RACE_SKILLS[race]];
+	}
+
+	// Set up color to use for each skill string to be displayed, based
+	// on whether each class is allowed or not for the given attributes
+	int classColors[TOTAL_CLASSES];
+	Common::fill(&classColors[0], &classColors[TOTAL_CLASSES], 0);
+	for (int classNum = CLASS_KNIGHT; classNum <= CLASS_RANGER; ++classNum) {
+		if (allowedClasses[classNum]) {
+			if (classId == -1 && (foundClass == -1 || foundClass < classNum))
+				foundClass = classNum;
+			classColors[classNum] = 4;
+		}
+	}
+
+	// Return stats details and character class
+	msg = Common::String::format(NEW_CHAR_STATS, RACE_NAMES[race], SEX_NAMES[sex],
+		attribs[MIGHT], attribs[INTELLECT], attribs[PERSONALITY],
+		attribs[ENDURANCE], attribs[SPEED], attribs[ACCURACY], attribs[LUCK],
+		classColors[CLASS_KNIGHT], classColors[CLASS_PALADIN],
+		classColors[CLASS_ARCHER], classColors[CLASS_CLERIC],
+		classColors[CLASS_SORCERER], classColors[CLASS_ROBBER],
+		classColors[CLASS_NINJA], classColors[CLASS_BARBARIAN],
+		classColors[CLASS_DRUID], classColors[CLASS_RANGER],
+		skillStr.c_str(), raceSkillStr.c_str(), classStr.c_str()
+	);
+	return classId == -1 ? foundClass : selectedClass;
+}
+
+/**
+ * Print the selection arrow to indicate the selected class
+ */
+void PartyDialog::printSelectionArrow(SpriteResource &icons, int selectedClass) {
+	Window &w = _vm->_screen->_windows[0];
+	icons.draw(w, 61, Common::Point(220, 19));
+	icons.draw(w, 63, Common::Point(220, selectedClass * 11 + 21));
+	w.update();
+}
+
+/**
+ * Print the dice animation
+ */
+void PartyDialog::drawDice(SpriteResource &dice) {
+	error("TODO: drawDice");
+}
+
 } // End of namespace Xeen
diff --git a/engines/xeen/dialogs_party.h b/engines/xeen/dialogs_party.h
index 1510b76..e9b06ae 100644
--- a/engines/xeen/dialogs_party.h
+++ b/engines/xeen/dialogs_party.h
@@ -56,6 +56,18 @@ private:
 	void createChar();
 
 	int selectCharacter(bool isDelete, int firstDisplayChar);
+
+	void throwDice(uint attribs[TOTAL_ATTRIBUTES], bool allowedClasses[TOTAL_CLASSES]);
+
+	void checkClass(const uint attribs[TOTAL_ATTRIBUTES], bool allowedClasses[TOTAL_CLASSES]);
+
+	int newCharDetails(const uint attribs[TOTAL_ATTRIBUTES], 
+		bool allowedClasses[TOTAL_CLASSES], Race race, Sex sex, int classId,
+		int selectedClass, Common::String &msg);
+
+	void printSelectionArrow(SpriteResource &icons, int selectedClass);
+
+	void drawDice(SpriteResource &dice);
 public:
 	static void show(XeenEngine *vm);
 };
diff --git a/engines/xeen/resources.cpp b/engines/xeen/resources.cpp
index 8f14753..b11db9f 100644
--- a/engines/xeen/resources.cpp
+++ b/engines/xeen/resources.cpp
@@ -1450,4 +1450,25 @@ const char *const HAS_SLAYER_SWORD =
 const char *const SURE_TO_DELETE_CHAR = 
 	"Are you sure you want to delete %s the %s?";
 
+const char *const CREATE_CHAR_DETAILS = 
+	"\f04\x3""c\x2\t144\v119\f37R\f04oll\t144\v149\f37C\f04reate"
+	"\t144\v179\f37ESC\f04\x3l\x1\t195\v021\f37M\f04gt"
+	"\t195\v045\f37I\f04nt\t195\v069\f37P\f04er\t195\v093\f37E\f04nd"
+	"\t195\v116\f37S\f04pd\t195\v140\f37A\f04cy\t195\v164\f37L\f04ck%s";
+
+const char *const NEW_CHAR_STATS =
+	"\f04\x3l\t022\v148Race\t055: %s\n"
+	"\t022Sex\t055: %s\n"
+	"\t022Class\t055:\n"
+	"\x3r\t215\v031%d\t215\v055%d\t215\v079%d\t215\v103%d\t215\v127%d"
+	"\t215\v151%d\t215\v175%d\x3l\t242\v020\f%2dKnight\t242\v031\f%2d"
+	"Paladin\t242\v042\f%2dArcher\t242\v053\f%2dCleric\t242\v064\f%2d"
+	"Sorcerer\t242\v075\f%2dRobber\t242\v086\f%2dNinja\t242\v097\f%2d"
+	"Barbarian\t242\v108\f%2dDruid\t242\v119\f%2dRanger\f04\x3""c"
+	"\t265\v142Skills\x3l\t223\v155%s\t223\v170%s%s";
+
+const int NEW_CHAR_SKILLS[10] = { 1, 5, -1, -1, 4, 0, 0, -1, 6, 11 };
+const int NEW_CHAR_SKILLS_LEN[10] = { 11, 8, 0, 0, 12, 8, 8, 0, 9, 11 };
+const int NEW_CHAR_RACE_SKILLS[10] = { 14, -1, 17, 16, -1, 0, 0, 0, 0, 0 };
+
 } // End of namespace Xeen
diff --git a/engines/xeen/resources.h b/engines/xeen/resources.h
index 2ca9dbb..3c1ae9d 100644
--- a/engines/xeen/resources.h
+++ b/engines/xeen/resources.h
@@ -504,6 +504,13 @@ extern const char *const YOUR_PARTY_IS_FULL;
 extern const char *const HAS_SLAYER_SWORD;
 extern const char *const SURE_TO_DELETE_CHAR;
 
+extern const char *const CREATE_CHAR_DETAILS;
+
+extern const char *const NEW_CHAR_STATS;
+extern const int NEW_CHAR_SKILLS[10];
+extern const int NEW_CHAR_SKILLS_LEN[10];
+extern const int NEW_CHAR_RACE_SKILLS[10];
+
 } // End of namespace Xeen
 
 #endif	/* XEEN_RESOURCES_H */


Commit: d225bc4cb3364b2cc8fc0fcab96347cc91e93866
    https://github.com/scummvm/scummvm/commit/d225bc4cb3364b2cc8fc0fcab96347cc91e93866
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-02-13T23:20:23-05:00

Commit Message:
XEEN: Implemented saveCharacter

Changed paths:
    engines/xeen/dialogs.cpp
    engines/xeen/dialogs_input.cpp
    engines/xeen/dialogs_input.h
    engines/xeen/dialogs_party.cpp
    engines/xeen/dialogs_party.h
    engines/xeen/resources.cpp
    engines/xeen/resources.h
    engines/xeen/xeen.h



diff --git a/engines/xeen/dialogs.cpp b/engines/xeen/dialogs.cpp
index a2535fd..8bb0af0 100644
--- a/engines/xeen/dialogs.cpp
+++ b/engines/xeen/dialogs.cpp
@@ -52,8 +52,6 @@ void ButtonContainer::addButton(const Common::Rect &bounds, int val, SpriteResou
 }
 
 void ButtonContainer::addPartyButtons(XeenEngine *vm) {
-	Party &party = *vm->_party;
-
 	for (uint idx = 0; idx < MAX_ACTIVE_PARTY; ++idx) {
 		addButton(Common::Rect(CHAR_FACES_X[idx], 150, CHAR_FACES_X[idx] + 32, 182),
 			Common::KEYCODE_F1 + idx, nullptr, false);
@@ -80,7 +78,15 @@ bool ButtonContainer::checkEvents(XeenEngine *vm) {
 		Common::KeyState keyState;
 		events.getKey(keyState);
 		
-		_buttonValue = keyState.keycode | (keyState.flags << 8);
+		_buttonValue = keyState.keycode;
+		if (_buttonValue == Common::KEYCODE_KP8)
+			_buttonValue = Common::KEYCODE_UP;
+		else if (_buttonValue == Common::KEYCODE_KP2)
+			_buttonValue = Common::KEYCODE_DOWN;
+		else if (_buttonValue == Common::KEYCODE_KP_ENTER)
+			_buttonValue = Common::KEYCODE_RETURN;
+
+		_buttonValue |= (keyState.flags << 8);
 		if (_buttonValue)
 			return true;
 	}
diff --git a/engines/xeen/dialogs_input.cpp b/engines/xeen/dialogs_input.cpp
index 1394379..042fabf 100644
--- a/engines/xeen/dialogs_input.cpp
+++ b/engines/xeen/dialogs_input.cpp
@@ -26,6 +26,15 @@
 
 namespace Xeen {
 
+int Input::show(XeenEngine *vm, Window *window, Common::String &line, 
+		uint maxLen, int maxWidth, bool isNumeric) {
+	Input *dlg = new Input(vm, window);
+	int result = dlg->getString(line, maxLen, maxWidth, isNumeric);
+	delete dlg;
+
+	return result;
+}
+
 /**
  * Allows the user to enter a string
  */
diff --git a/engines/xeen/dialogs_input.h b/engines/xeen/dialogs_input.h
index c6d832c..30e4cb2 100644
--- a/engines/xeen/dialogs_input.h
+++ b/engines/xeen/dialogs_input.h
@@ -39,6 +39,9 @@ protected:
 	int getString(Common::String &line, uint maxLen, int maxWidth, bool isNumeric);
 
 	Input(XeenEngine *vm, Window *window) : _vm(vm), _window(window) {}
+public:
+	static int show(XeenEngine *vm, Window *window, Common::String &line, 
+		uint maxLen, int maxWidth, bool isNumeric = false);
 };
 
 class StringInput : public Input {
diff --git a/engines/xeen/dialogs_party.cpp b/engines/xeen/dialogs_party.cpp
index ff59363..058ead4 100644
--- a/engines/xeen/dialogs_party.cpp
+++ b/engines/xeen/dialogs_party.cpp
@@ -23,6 +23,7 @@
 #include "common/scummsys.h"
 #include "xeen/dialogs_char_info.h"
 #include "xeen/dialogs_party.h"
+#include "xeen/dialogs_input.h"
 #include "xeen/dialogs_query.h"
 #include "xeen/character.h"
 #include "xeen/events.h"
@@ -375,12 +376,22 @@ void PartyDialog::createChar() {
 	EventsManager &events = *_vm->_events;
 	Party &party = *_vm->_party;
 	Screen &screen = *_vm->_screen;
+	Window &w = screen._windows[0];
 	SpriteResource dice, icons;
-	Mode oldMode = _vm->_mode;
 	Common::Array<int> freeCharList;
+	int classId;
 	int selectedClass = 0;
 	bool hasFadedIn = false;
+	bool restartFlag = true;
+	uint attribs[TOTAL_ATTRIBUTES];
+	bool allowedClasses[TOTAL_CLASSES];
+	Race race;
+	Sex sex;
+	Common::String msg;
+	int charIndex;
 
+	Mode oldMode = _vm->_mode;
+	_vm->_mode = MODE_4;
 	dice.load("dice.vga");
 	icons.load("create.raw");
 
@@ -414,93 +425,261 @@ void PartyDialog::createChar() {
 	events.setCursor(0);
 
 	while (!_vm->shouldQuit()) {
-		int classId = -1;
-
-		// Build up list of roster slot indexes that are free
-		freeCharList.clear();
-		for (uint idx = 0; idx < XEEN_TOTAL_CHARACTERS; ++idx) {
-			if (party._roster[idx]._name.empty())
-				freeCharList.push_back(idx);
-		}		
-		int charIndex = 0;
-		//bool flag9 = true;
-
-		if (freeCharList.size() == XEEN_TOTAL_CHARACTERS)
-			break;
+		classId = -1;
+
+		if (restartFlag) {
+			// Build up list of roster slot indexes that are free
+			freeCharList.clear();
+			for (uint idx = 0; idx < XEEN_TOTAL_CHARACTERS; ++idx) {
+				if (party._roster[idx]._name.empty())
+					freeCharList.push_back(idx);
+			}
+			charIndex = 0;
+			//bool flag9 = true;
 
-		// Get and race and sex for the given character
-		Race race = (Race)((freeCharList[charIndex] / 4) % 5);
-		Sex sex = (Sex)(freeCharList[charIndex] & 1);
-
-		// Randomly determine attributes, and which classes they allow
-		uint attribs[TOTAL_ATTRIBUTES];
-		bool allowedClasses[TOTAL_CLASSES];
-		throwDice(attribs, allowedClasses);
-
-		// Set up display of the rolled character details
-		Common::String msg;
-		selectedClass = newCharDetails(attribs, allowedClasses,
-			race, sex, classId, selectedClass, msg);
-
-		// Draw the screen
-		Window &w = screen._windows[0];
-		icons.draw(w, 10, Common::Point(168, 19));
-		icons.draw(w, 12, Common::Point(168, 43));
-		icons.draw(w, 14, Common::Point(168, 67));
-		icons.draw(w, 16, Common::Point(168, 91));
-		icons.draw(w, 18, Common::Point(168, 115));
-		icons.draw(w, 20, Common::Point(168, 139));
-		icons.draw(w, 22, Common::Point(168, 163));
-		for (int idx = 0; idx < 9; ++idx)
-			icons.draw(w, 24 + idx * 2, Common::Point(227, 19 + 11 * idx));
-
-		for (int idx = 0; idx < 7; ++idx)
-			icons.draw(w, 50 + idx, Common::Point(195, 31 + 24 * idx));
-
-		icons.draw(w, 57, Common::Point(62, 148));
-		icons.draw(w, 58, Common::Point(62, 158));
-		icons.draw(w, 59, Common::Point(62, 168));
-		icons.draw(w, 61, Common::Point(220, 19));
-		icons.draw(w, 64, Common::Point(220, 155));
-		icons.draw(w, 65, Common::Point(220, 170));
-		
-		party._roster[freeCharList[charIndex]]._faceSprites->draw(
-			w, 0, Common::Point(27, 102));
+			if (freeCharList.size() == XEEN_TOTAL_CHARACTERS)
+				break;
+
+			// Get and race and sex for the given character
+			race = (Race)((freeCharList[charIndex] / 4) % 5);
+			sex = (Sex)(freeCharList[charIndex] & 1);
+
+			// Randomly determine attributes, and which classes they allow
+			throwDice(attribs, allowedClasses);
+
+			// Set up display of the rolled character details
+			selectedClass = newCharDetails(attribs, allowedClasses,
+				race, sex, classId, selectedClass, msg);
+
+			// Draw the screen
+			icons.draw(w, 10, Common::Point(168, 19));
+			icons.draw(w, 12, Common::Point(168, 43));
+			icons.draw(w, 14, Common::Point(168, 67));
+			icons.draw(w, 16, Common::Point(168, 91));
+			icons.draw(w, 18, Common::Point(168, 115));
+			icons.draw(w, 20, Common::Point(168, 139));
+			icons.draw(w, 22, Common::Point(168, 163));
+			for (int idx = 0; idx < 9; ++idx)
+				icons.draw(w, 24 + idx * 2, Common::Point(227, 19 + 11 * idx));
+
+			for (int idx = 0; idx < 7; ++idx)
+				icons.draw(w, 50 + idx, Common::Point(195, 31 + 24 * idx));
+
+			icons.draw(w, 57, Common::Point(62, 148));
+			icons.draw(w, 58, Common::Point(62, 158));
+			icons.draw(w, 59, Common::Point(62, 168));
+			icons.draw(w, 61, Common::Point(220, 19));
+			icons.draw(w, 64, Common::Point(220, 155));
+			icons.draw(w, 65, Common::Point(220, 170));
+
+			party._roster[freeCharList[charIndex]]._faceSprites->draw(
+				w, 0, Common::Point(27, 102));
+
+			icons.draw(w, 0, Common::Point(132, 98));
+			icons.draw(w, 2, Common::Point(132, 128));
+			icons.draw(w, 4, Common::Point(132, 158));
+			icons.draw(w, 6, Common::Point(86, 98));
+			icons.draw(w, 8, Common::Point(86, 120));
+
+			w.writeString(msg);
+			w.update();
+
+			// Draw the arrow for the selected class, if applicable
+			if (selectedClass != -1)
+				printSelectionArrow(icons, selectedClass);
+
+			// Draw the dice
+			drawDice(dice);
+			if (!hasFadedIn) {
+				screen.fadeIn(4);
+				hasFadedIn = true;
+			}
+
+			restartFlag = false;
+		}
+
+		// Animate the dice until a user action occurs
+		_buttonValue = 0;
+		while (!_vm->shouldQuit() && !_buttonValue)
+			drawDice(dice);
+
+		// Handling for different actions
+		switch (_buttonValue) {
+		case Common::KEYCODE_UP:
+			if (charIndex == 0)
+				continue;
+
+			race = (Race)((freeCharList[charIndex] / 4) % 5);
+			sex = (Sex)(freeCharList[charIndex] & 1);
+			break;
 
-		icons.draw(w, 0, Common::Point(132, 98));
-		icons.draw(w, 2, Common::Point(132, 128));
-		icons.draw(w, 4, Common::Point(132, 158));
-		icons.draw(w, 6, Common::Point(86, 98));
-		icons.draw(w, 8, Common::Point(86, 120));
+		case Common::KEYCODE_DOWN:
+			if (++charIndex == (int)freeCharList.size()) {
+				--charIndex;
+				continue;
+			} else {
+				race = (Race)((freeCharList[charIndex] / 4) % 5);
+				sex = (Sex)(freeCharList[charIndex] & 1);
+			}
+			break;
 
-		w.writeString(msg);
-		w.update();
+		case Common::KEYCODE_PAGEUP:
+			for (int tempClass = selectedClass - 1; tempClass >= 0; --tempClass) {
+				if (allowedClasses[tempClass]) {
+					selectedClass = tempClass;
+					break;
+				}
+			}
 
-		// Draw the arrow for the selected class, if applicable
-		if (selectedClass != -1)
 			printSelectionArrow(icons, selectedClass);
+			continue;
 
-		// Draw the dice
-		drawDice(dice);
-		if (!hasFadedIn) {
-			screen.fadeIn(4);
-			hasFadedIn = true;
+		case Common::KEYCODE_PAGEDOWN:
+			break;
+
+		case Common::KEYCODE_m:
+		case Common::KEYCODE_i:
+		case Common::KEYCODE_p:
+		case Common::KEYCODE_e:
+		case Common::KEYCODE_s:
+		case Common::KEYCODE_a:
+		case Common::KEYCODE_l: {
+			Attribute srcAttrib, destAttrib;
+			if (_buttonValue == Common::KEYCODE_m)
+				srcAttrib = MIGHT;
+			else if (_buttonValue == Common::KEYCODE_i)
+				srcAttrib = INTELLECT;
+			else if (_buttonValue == Common::KEYCODE_p)
+				srcAttrib = PERSONALITY;
+			else if (_buttonValue == Common::KEYCODE_e)
+				srcAttrib = ENDURANCE;
+			else if (_buttonValue == Common::KEYCODE_s)
+				srcAttrib = SPEED;
+			else if (_buttonValue == Common::KEYCODE_a)
+				srcAttrib = ACCURACY;
+			else
+				srcAttrib = LUCK;
+
+			_vm->_mode = MODE_86;
+			icons.draw(w, srcAttrib * 2 + 11, Common::Point(
+				_buttons[srcAttrib + 5]._bounds.left, _buttons[srcAttrib + 5]._bounds.top));
+			w.update();
+
+			int destAttribVal = exchangeAttribute(srcAttrib + 1);
+			if (destAttribVal) {
+				destAttrib = (Attribute)(destAttribVal - 1);
+				icons.draw(w, destAttrib * 2 + 11, Common::Point(
+					_buttons[destAttrib + 10]._bounds.left,
+					_buttons[destAttrib + 10]._bounds.top));
+				w.update();
+				
+				SWAP(attribs[srcAttrib], attribs[destAttrib]);
+				checkClass(attribs, allowedClasses);
+				classId = -1;
+				selectedClass = newCharDetails(attribs, allowedClasses, 
+					race, sex, classId, selectedClass, msg);
+			} else {
+				icons.draw(w, srcAttrib * 2 + 10, Common::Point(
+					_buttons[srcAttrib + 5]._bounds.left,
+					_buttons[srcAttrib + 5]._bounds.top));
+				w.update();
+				_vm->_mode = MODE_SLEEPING;
+				continue;
+			}
+			break;
 		}
 
-		// Key handling loop
-		while (!_vm->shouldQuit()) {
-			// Animate the dice until a user action occurs
-			_buttonValue = 0;
-			while (!_vm->shouldQuit() && !_buttonValue)
-				drawDice(dice);
+		case 1000:
+		case 1001:
+		case 1002:
+		case 1003:
+		case 1004:
+		case 1005:
+		case 1006:
+		case 1007:
+		case 1008:
+		case 1009:
+			if (allowedClasses[_buttonValue - 1000]) {
+				selectedClass = classId = _buttonValue - 1000;
+			}
+			break;
+
+		case Common::KEYCODE_c: {
+			_vm->_mode = MODE_FF;
+			bool result = saveCharacter(party._roster[freeCharList[charIndex]],
+				(CharacterClass)classId, race, sex, attribs);
+			_vm->_mode = MODE_4;
 
-			// TODO
+			if (result)
+				restartFlag = true;
+			continue;
 		}
-		
-		// TODO: More
-		error("TODO: createChar");
-	}
 
+		case Common::KEYCODE_RETURN:
+			classId = selectedClass;
+			break;
+
+		case Common::KEYCODE_SPACE:
+		case Common::KEYCODE_r:
+			// Re-roll the attributes
+			throwDice(attribs, allowedClasses);
+			classId = -1;
+			break;
+
+		default:
+			// For all other keypresses, skip the code below the switch
+			// statement, and go to wait for the next key
+			continue;
+		}
+
+		if (_buttonValue != Common::KEYCODE_PAGEDOWN) {
+			selectedClass = newCharDetails(attribs, allowedClasses,
+				race, sex, classId, selectedClass, msg);
+			
+			for (int idx = 0; idx < 7; ++idx)
+				icons.draw(w, 10 + idx * 2, Common::Point(168, 19 + idx * 24));
+			for (int idx = 0; idx < 10; ++idx)
+				icons.draw(w, 24 + idx * 2, Common::Point(227, 19 + idx * 11));
+			for (int idx = 0; idx < 8; ++idx)
+				icons.draw(w, 50 + idx, Common::Point(195, 31 + idx * 24));
+
+			icons.draw(w, 57, Common::Point(62, 148));
+			icons.draw(w, 58, Common::Point(62, 158));
+			icons.draw(w, 59, Common::Point(62, 168));
+			icons.draw(w, 61, Common::Point(220, 19));
+			icons.draw(w, 64, Common::Point(220, 155));
+			icons.draw(w, 65, Common::Point(220, 170));
+			
+			party._roster[freeCharList[charIndex]]._faceSprites->draw(w, 0,
+				Common::Point(27, 102));
+
+			icons.draw(w, 0, Common::Point(132, 98));
+			icons.draw(w, 2, Common::Point(132, 128));
+			icons.draw(w, 4, Common::Point(132, 158));
+			icons.draw(w, 6, Common::Point(86, 98));
+			icons.draw(w, 8, Common::Point(86, 120));
+
+			w.writeString(msg);
+			w.update();
+
+			if (selectedClass != -1) {
+				printSelectionArrow(icons, selectedClass);
+				continue;
+			}
+		}
+
+		// Move to next available class, or if the code block above resulted in 
+		// selectedClass being -1, move to select the first available class
+		for (int tempClass = selectedClass + 1; tempClass <= CLASS_RANGER; ++tempClass) {
+			if (allowedClasses[tempClass]) {
+				selectedClass = tempClass;
+				break;
+			}
+		}
+
+		printSelectionArrow(icons, selectedClass);
+	} while (!_vm->shouldQuit() && _buttonValue != Common::KEYCODE_ESCAPE);
+		
 	_vm->_mode = oldMode;
 }
 
@@ -691,4 +870,88 @@ void PartyDialog::drawDice(SpriteResource &dice) {
 	error("TODO: drawDice");
 }
 
+/**
+ * Exchanging two attributes for the character being rolled
+ */
+int PartyDialog::exchangeAttribute(int srcAttr) {
+	error("TODO: exchangeAttribute");
+}
+
+bool PartyDialog::saveCharacter(Character &c, CharacterClass classId,
+		Race race, Sex sex, uint attribs[TOTAL_ATTRIBUTES]) {
+	if (classId == -1) {
+		ErrorScroll::show(_vm, SELECT_CLASS_BEFORE_SAVING);
+		return false;
+	}
+
+	Map &map = *_vm->_map;
+	Party &party = *_vm->_party;
+	Screen &screen = *_vm->_screen;
+	Window &w = screen._windows[6];
+	Common::String name;
+	int result;
+	bool isDarkCc = _vm->_files->_isDarkCc;
+
+	saveButtons();
+	w.writeString(NAME_FOR_NEW_CHARACTER);
+
+	result = Input::show(_vm, &w, name, 10, 200);
+	w.close();
+	restoreButtons();
+	if (!result)
+		return false;
+
+	// Save new character details
+	c.clear();
+	c._name = name;
+	c._savedMazeId = party._priorMazeId;
+	c._xeenSide = map._loadDarkSide;
+	c._sex = sex;
+	c._race = race;
+	c._class = classId;
+	c._level._permanent = isDarkCc ? 5 : 1;
+
+	c._might._permanent = attribs[MIGHT];
+	c._intellect._permanent = attribs[INTELLECT];
+	c._personality._permanent = attribs[PERSONALITY];
+	c._endurance._permanent = attribs[ENDURANCE];
+	c._speed._permanent = attribs[SPEED];
+	c._accuracy._permanent = attribs[ACCURACY];
+	c._luck._permanent = attribs[LUCK];
+
+	c._magicResistence._permanent = RACE_MAGIC_RESISTENCES[race];
+	c._fireResistence._permanent = RACE_FIRE_RESISTENCES[race];
+	c._electricityResistence._permanent = RACE_ELECTRIC_RESISTENCES[race];
+	c._coldResistence._permanent = RACE_COLD_RESISTENCES[race];
+	c._energyResistence._permanent = RACE_ENERGY_RESISTENCES[race];
+	c._poisonResistence._permanent = RACE_POISON_RESISTENCES[race];
+
+	c._birthYear = party._year - 18;
+	c._birthDay = party._day;
+	c._hasSpells = false;
+	c._currentSpell = -1;
+
+	// Set up any default spells for the character's class
+	for (int idx = 0; idx < 4; ++idx) {
+		if (NEW_CHARACTER_SPELLS[c._class][idx] != -1) {
+			c._hasSpells = true;
+			c._currentSpell = NEW_CHARACTER_SPELLS[c._class][idx];
+			c._spells[c._currentSpell] = 1;
+		}
+	}
+
+	int classSkill = NEW_CHAR_SKILLS[c._class];
+	if (classSkill != -1)
+		c._skills[classSkill] = 1;
+
+	int raceSkill = NEW_CHAR_RACE_SKILLS[c._race];
+	if (raceSkill != -1)
+		c._skills[raceSkill] = 1;
+
+	c._currentHp = c.getMaxHP();
+	c._currentSp = c.getMaxSP();
+	return true;
+}
+
+
 } // End of namespace Xeen
diff --git a/engines/xeen/dialogs_party.h b/engines/xeen/dialogs_party.h
index e9b06ae..178a5c4 100644
--- a/engines/xeen/dialogs_party.h
+++ b/engines/xeen/dialogs_party.h
@@ -68,6 +68,11 @@ private:
 	void printSelectionArrow(SpriteResource &icons, int selectedClass);
 
 	void drawDice(SpriteResource &dice);
+
+	int exchangeAttribute(int srcAttr);
+
+	bool saveCharacter(Character &c, CharacterClass classId, Race race,
+		Sex sex, uint attribs[TOTAL_ATTRIBUTES]);
 public:
 	static void show(XeenEngine *vm);
 };
diff --git a/engines/xeen/resources.cpp b/engines/xeen/resources.cpp
index b11db9f..c9c377d 100644
--- a/engines/xeen/resources.cpp
+++ b/engines/xeen/resources.cpp
@@ -1467,8 +1467,31 @@ const char *const NEW_CHAR_STATS =
 	"Barbarian\t242\v108\f%2dDruid\t242\v119\f%2dRanger\f04\x3""c"
 	"\t265\v142Skills\x3l\t223\v155%s\t223\v170%s%s";
 
+const char *const NAME_FOR_NEW_CHARACTER =
+	"\x3""cEnter a Name for this Character";
+const char *const SELECT_CLASS_BEFORE_SAVING =
+	"\v006\x3""cSelect a Class before saving.\x3l";
 const int NEW_CHAR_SKILLS[10] = { 1, 5, -1, -1, 4, 0, 0, -1, 6, 11 };
 const int NEW_CHAR_SKILLS_LEN[10] = { 11, 8, 0, 0, 12, 8, 8, 0, 9, 11 };
 const int NEW_CHAR_RACE_SKILLS[10] = { 14, -1, 17, 16, -1, 0, 0, 0, 0, 0 };
 
+const int RACE_MAGIC_RESISTENCES[5] = { 7, 5, 20, 0, 0 };
+const int RACE_FIRE_RESISTENCES[5] = { 7, 0, 2, 5, 10 };
+const int RACE_ELECTRIC_RESISTENCES[5] = { 7, 0, 2, 5, 10 };
+const int RACE_COLD_RESISTENCES[5] = { 7, 0, 2, 5, 10 };
+const int RACE_ENERGY_RESISTENCES[5] = { 7, 5, 2, 5, 0 };
+const int RACE_POISON_RESISTENCES[5] = { 7, 0, 2, 20, 0 };
+const int NEW_CHARACTER_SPELLS[10][4] = {
+	{ -1, -1, -1, -1 },
+	{ 21, -1, -1, -1 },
+	{ 22, -1, -1, -1 },
+	{ 21, 1, 14, -1 },
+	{ 22, 0, 25, -1 },
+	{ -1, -1, -1, -1 },
+	{ -1, -1, -1, -1 },
+	{ -1, -1, -1, -1 },
+	{ 20, 1, 11, 23 },
+	{ 20, 1, -1, -1 }
+};
+
 } // End of namespace Xeen
diff --git a/engines/xeen/resources.h b/engines/xeen/resources.h
index 3c1ae9d..3c6df78 100644
--- a/engines/xeen/resources.h
+++ b/engines/xeen/resources.h
@@ -507,10 +507,20 @@ extern const char *const SURE_TO_DELETE_CHAR;
 extern const char *const CREATE_CHAR_DETAILS;
 
 extern const char *const NEW_CHAR_STATS;
+extern const char *const NAME_FOR_NEW_CHARACTER;
+extern const char *const SELECT_CLASS_BEFORE_SAVING;
 extern const int NEW_CHAR_SKILLS[10];
 extern const int NEW_CHAR_SKILLS_LEN[10];
 extern const int NEW_CHAR_RACE_SKILLS[10];
 
+extern const int RACE_MAGIC_RESISTENCES[5];
+extern const int RACE_FIRE_RESISTENCES[5];
+extern const int RACE_ELECTRIC_RESISTENCES[5];
+extern const int RACE_COLD_RESISTENCES[5];
+extern const int RACE_ENERGY_RESISTENCES[5];
+extern const int RACE_POISON_RESISTENCES[5];
+extern const int NEW_CHARACTER_SPELLS[10][4];
+
 } // End of namespace Xeen
 
 #endif	/* XEEN_RESOURCES_H */
diff --git a/engines/xeen/xeen.h b/engines/xeen/xeen.h
index c4f826d..2d85335 100644
--- a/engines/xeen/xeen.h
+++ b/engines/xeen/xeen.h
@@ -88,7 +88,8 @@ enum Mode {
 	MODE_9 = 9,
 	MODE_CHARACTER_INFO = 10,
 	MODE_12 = 12,
-	MODE_17 = 17
+	MODE_17 = 17,
+	MODE_86 = 86
 };
 
 struct XeenGameDescription;


Commit: 9b0b0cd9e747780ec32a3589343f0172c0237aa0
    https://github.com/scummvm/scummvm/commit/9b0b0cd9e747780ec32a3589343f0172c0237aa0
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-02-13T23:48:02-05:00

Commit Message:
XEEN: Implemented exchangeAttribute

Changed paths:
    engines/xeen/dialogs.h
    engines/xeen/dialogs_party.cpp
    engines/xeen/resources.cpp
    engines/xeen/resources.h



diff --git a/engines/xeen/dialogs.h b/engines/xeen/dialogs.h
index ba27fe9..02e945b 100644
--- a/engines/xeen/dialogs.h
+++ b/engines/xeen/dialogs.h
@@ -66,7 +66,8 @@ public:
 
 	void restoreButtons();
 
-	void addButton(const Common::Rect &bounds, int val, SpriteResource *sprites, bool draw = true);
+	void addButton(const Common::Rect &bounds, int val, 
+		SpriteResource *sprites = nullptr, bool draw = true);
 
 	void addPartyButtons(XeenEngine *vm);
 };
diff --git a/engines/xeen/dialogs_party.cpp b/engines/xeen/dialogs_party.cpp
index 058ead4..b570612 100644
--- a/engines/xeen/dialogs_party.cpp
+++ b/engines/xeen/dialogs_party.cpp
@@ -874,9 +874,83 @@ void PartyDialog::drawDice(SpriteResource &dice) {
  * Exchanging two attributes for the character being rolled
  */
 int PartyDialog::exchangeAttribute(int srcAttr) {
-	error("TODO: exchangeAttribute");
+	EventsManager &events = *_vm->_events;
+	Screen &screen = *_vm->_screen;
+	SpriteResource icons;
+	icons.load("create2.icn");
+
+	saveButtons();
+	addButton(Common::Rect(118, 58, 142, 78), Common::KEYCODE_ESCAPE, &icons);
+	addButton(Common::Rect(168, 19, 192, 39), Common::KEYCODE_m);
+	addButton(Common::Rect(168, 43, 192, 63), Common::KEYCODE_i);
+	addButton(Common::Rect(168, 67, 192, 87), Common::KEYCODE_p);
+	addButton(Common::Rect(168, 91, 192, 111), Common::KEYCODE_e);
+	addButton(Common::Rect(168, 115, 192, 135), Common::KEYCODE_s);
+	addButton(Common::Rect(168, 139, 192, 159), Common::KEYCODE_a);
+	addButton(Common::Rect(168, 163, 192, 183), Common::KEYCODE_l);
+
+	Window &w = screen._windows[26];
+	w.open();
+	w.writeString(Common::String::format(EXCHANGE_ATTR_WITH, STAT_NAMES[srcAttr - 1]));
+	icons.draw(w, 0, Common::Point(118, 58));
+	w.update();
+
+	int result = 0;
+	bool breakFlag = false;
+	while (!_vm->shouldQuit() && !breakFlag) {
+		// Wait for an action
+		do {
+			events.pollEventsAndWait();
+			checkEvents(_vm);
+		} while (!_vm->shouldQuit() && !_buttonValue);
+
+		Attribute destAttr;
+		switch (_buttonValue) {
+		case Common::KEYCODE_m:
+			destAttr = MIGHT;
+			break;
+		case Common::KEYCODE_i:
+			destAttr = INTELLECT;
+			break;
+		case Common::KEYCODE_p:
+			destAttr = PERSONALITY;
+			break;
+		case Common::KEYCODE_e:
+			destAttr = ENDURANCE;
+			break;
+		case Common::KEYCODE_s:
+			destAttr = SPEED;
+			break;
+		case Common::KEYCODE_a:
+			destAttr = ACCURACY;
+			break;
+		case Common::KEYCODE_l:
+			destAttr = LUCK;
+			break;
+		case Common::KEYCODE_ESCAPE:
+			result = 0;
+			breakFlag = true;
+			continue;
+		default:
+			continue;
+		}
+
+		if ((srcAttr - 1) != destAttr) {
+			result = destAttr + 1;
+			break;
+		}
+	}
+
+	w.close();
+	_buttonValue = 0;
+	restoreButtons();
+
+	return result;
 }
 
+/**
+ * Saves the rolled character into the roster
+ */
 bool PartyDialog::saveCharacter(Character &c, CharacterClass classId,
 		Race race, Sex sex, uint attribs[TOTAL_ATTRIBUTES]) {
 	if (classId == -1) {
@@ -953,5 +1027,4 @@ bool PartyDialog::saveCharacter(Character &c, CharacterClass classId,
 	return true;
 }
 
-
 } // End of namespace Xeen
diff --git a/engines/xeen/resources.cpp b/engines/xeen/resources.cpp
index c9c377d..7dca04f 100644
--- a/engines/xeen/resources.cpp
+++ b/engines/xeen/resources.cpp
@@ -1471,6 +1471,8 @@ const char *const NAME_FOR_NEW_CHARACTER =
 	"\x3""cEnter a Name for this Character";
 const char *const SELECT_CLASS_BEFORE_SAVING =
 	"\v006\x3""cSelect a Class before saving.\x3l";
+const char *const EXCHANGE_ATTR_WITH = "Exchange %s with...";
+
 const int NEW_CHAR_SKILLS[10] = { 1, 5, -1, -1, 4, 0, 0, -1, 6, 11 };
 const int NEW_CHAR_SKILLS_LEN[10] = { 11, 8, 0, 0, 12, 8, 8, 0, 9, 11 };
 const int NEW_CHAR_RACE_SKILLS[10] = { 14, -1, 17, 16, -1, 0, 0, 0, 0, 0 };
diff --git a/engines/xeen/resources.h b/engines/xeen/resources.h
index 3c6df78..53c548f 100644
--- a/engines/xeen/resources.h
+++ b/engines/xeen/resources.h
@@ -509,6 +509,7 @@ extern const char *const CREATE_CHAR_DETAILS;
 extern const char *const NEW_CHAR_STATS;
 extern const char *const NAME_FOR_NEW_CHARACTER;
 extern const char *const SELECT_CLASS_BEFORE_SAVING;
+extern const char *const EXCHANGE_ATTR_WITH;
 extern const int NEW_CHAR_SKILLS[10];
 extern const int NEW_CHAR_SKILLS_LEN[10];
 extern const int NEW_CHAR_RACE_SKILLS[10];


Commit: b79d552c060b869a2f22727b4b7238294bc05943
    https://github.com/scummvm/scummvm/commit/b79d552c060b869a2f22727b4b7238294bc05943
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-02-14T07:32:38-05:00

Commit Message:
XEEN: Implemented drawDice

Changed paths:
    engines/xeen/dialogs_party.cpp
    engines/xeen/dialogs_party.h



diff --git a/engines/xeen/dialogs_party.cpp b/engines/xeen/dialogs_party.cpp
index b570612..7414ce3 100644
--- a/engines/xeen/dialogs_party.cpp
+++ b/engines/xeen/dialogs_party.cpp
@@ -395,6 +395,16 @@ void PartyDialog::createChar() {
 	dice.load("dice.vga");
 	icons.load("create.raw");
 
+	_dicePos[0] = Common::Point(20, 17);
+	_dicePos[1] = Common::Point(112, 35);
+	_dicePos[2] = Common::Point(61, 50);
+	_diceFrame[0] = 0;
+	_diceFrame[1] = 2;
+	_diceFrame[2] = 4;
+	_diceInc[0] = Common::Point(10, -10);
+	_diceInc[1] = Common::Point(-10, -10);
+	_diceInc[2] = Common::Point(-10, 10);
+
 	// Add buttons
 	saveButtons();
 	addButton(Common::Rect(132, 98, 156, 118), Common::KEYCODE_r, &icons);
@@ -867,7 +877,38 @@ void PartyDialog::printSelectionArrow(SpriteResource &icons, int selectedClass)
  * Print the dice animation
  */
 void PartyDialog::drawDice(SpriteResource &dice) {
-	error("TODO: drawDice");
+	EventsManager &events = *_vm->_events;
+	Window &w = _vm->_screen->_windows[32];
+	dice.draw(w, 7, Common::Point(12, 11));
+
+	for (int diceNum = 0; diceNum < 3; ++diceNum) {
+		_diceFrame[diceNum] = (_diceFrame[diceNum] + 1) % 7;
+		_dicePos[diceNum] += _diceInc[diceNum];
+
+		if (_dicePos[diceNum].x < 13) {
+			_dicePos[diceNum].x = 13;
+			_diceInc[diceNum].x *= -1;
+		} else if (_dicePos[diceNum].x >= 163) {
+			_dicePos[diceNum].x = 163;
+			_diceInc[diceNum].x *= -1;
+		}
+
+		if (_dicePos[diceNum].y < 12) {
+			_dicePos[diceNum].y = 12;
+			_diceInc[diceNum].y *= -1;
+		} else if (_dicePos[diceNum].y >= 93) {
+			_dicePos[diceNum].y = 93;
+			_diceInc[diceNum].y *= -1;
+		}
+
+		dice.draw(w, _diceFrame[diceNum], _dicePos[diceNum]);
+	}
+
+	w.update();
+
+	// Wait for keypress
+	events.wait(1, true);
+	checkEvents(_vm);
 }
 
 /**
diff --git a/engines/xeen/dialogs_party.h b/engines/xeen/dialogs_party.h
index 178a5c4..db2a3df 100644
--- a/engines/xeen/dialogs_party.h
+++ b/engines/xeen/dialogs_party.h
@@ -38,6 +38,9 @@ private:
 	DrawStruct _faceDrawStructs[4];
 	Common::String _partyDetails;
 	Common::Array<int> _charList;
+	int _diceFrame[3];
+	Common::Point _dicePos[3];
+	Common::Point _diceInc[3];
 
 	PartyDialog(XeenEngine *vm);
 


Commit: cad435d9a04ac16bc1203854e1616464a35f7f20
    https://github.com/scummvm/scummvm/commit/cad435d9a04ac16bc1203854e1616464a35f7f20
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-02-14T08:25:36-05:00

Commit Message:
XEEN: Fix default display of doors

Changed paths:
    engines/xeen/interface_map.cpp



diff --git a/engines/xeen/interface_map.cpp b/engines/xeen/interface_map.cpp
index ad53b7c..262c945 100644
--- a/engines/xeen/interface_map.cpp
+++ b/engines/xeen/interface_map.cpp
@@ -4314,7 +4314,7 @@ void InterfaceMap::drawIndoors() {
 
 	if (_wo[107]) {
 		_indoorList._fwl_1F1R._sprites = &map._wallSprites._fwl2;
-		if (_vm->_openDoor)
+		if (!_vm->_openDoor)
 			_indoorList._fwl_1F1R._frame = 0;
 		else
 			_indoorList._fwl_1F1R._frame = map.mazeData()._wallKind ? 1 : 10;


Commit: dae789369ed3ec4568e8149d9e5a3eca1d6b5d7b
    https://github.com/scummvm/scummvm/commit/dae789369ed3ec4568e8149d9e5a3eca1d6b5d7b
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-02-14T08:36:40-05:00

Commit Message:
XEEN: Fix _buttonValue check for moving through doorways

Changed paths:
    engines/xeen/interface.cpp



diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp
index 0916abe..dc35b21 100644
--- a/engines/xeen/interface.cpp
+++ b/engines/xeen/interface.cpp
@@ -698,7 +698,7 @@ bool Interface::checkMoveDirection(int key) {
 				sound.playFX(46);
 				return false;
 			} else {
-				if (_buttonValue == 242 && _wo[107]) {
+				if (_buttonValue == Common::KEYCODE_UP && _wo[107]) {
 					_vm->_openDoor = true;
 					sound.playFX(47);
 					draw3d(true);


Commit: cc9f62fcb936f86468566cd33602ff394040d33a
    https://github.com/scummvm/scummvm/commit/cc9f62fcb936f86468566cd33602ff394040d33a
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-02-15T12:01:04-05:00

Commit Message:
XEEN: Split up draw3d between Interface and InterfaceMap, start of fall code

Changed paths:
    engines/xeen/interface.cpp
    engines/xeen/interface.h
    engines/xeen/interface_map.cpp
    engines/xeen/interface_map.h



diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp
index dc35b21..51a59e1 100644
--- a/engines/xeen/interface.cpp
+++ b/engines/xeen/interface.cpp
@@ -932,5 +932,116 @@ void Interface::bash(const Common::Point &pt, Direction direction) {
 	drawParty(true);
 }
 
+void Interface::draw3d(bool updateFlag) {
+	Combat &combat = *_vm->_combat;
+	EventsManager &events = *_vm->_events;
+	Party &party = *_vm->_party;
+	Screen &screen = *_vm->_screen;
+	
+	if (screen._windows[11]._enabled)
+		return;
+
+	// Draw the map
+	drawMap(updateFlag);
+
+	// Draw the minimap
+	drawMiniMap();
+
+	if (party._falling == 1)
+		handleFalling();
+
+	if (party._falling == 2) {
+		screen.saveBackground(1);
+	}
+
+	assembleBorder();
+
+	// Draw any on-screen text if flagged to do so
+	if (_upDoorText && combat._attackMonsters[0] == -1) {
+		screen._windows[3].writeString(_screenText);
+	}
+
+	if (updateFlag) {
+		screen._windows[1].update();
+		screen._windows[3].update();
+	}
+
+	// TODO: more stuff
+
+	_vm->_party->_stepped = false;
+	if (_vm->_mode == MODE_9) {
+		// TODO
+	}
+
+	// TODO: Check use of updateFlag here. Original doesn't have it, but I
+	// wanted to ensure in places like the AutoMapDialog, that the draw3d
+	// doesn't result in the screen updating until the dialog has had
+	// a chance to full render itself
+	if (updateFlag)
+		events.wait(2);
+}
+
+void Interface::handleFalling() {
+	Party &party = *_vm->_party;
+	Screen &screen = *_vm->_screen;
+	SoundManager &sound = *_vm->_sound;
+	Window &w = screen._windows[3];
+	File voc1("scream.voc");
+	File voc2("unnh.voc");
+	saveFall();
+
+	for (uint idx = 0; idx < party._activeParty.size(); ++idx) {
+		party._activeParty[idx]._faceSprites->draw(screen._windows[0], 4,
+			Common::Point(CHAR_FACES_X[idx], 150));
+	}
+
+	screen._windows[33].update();
+	sound.playFX(11);
+	sound.playSample(&voc1, 0);
+
+	for (int idx = 0, incr = 2; idx < 133; ++incr, idx += incr) {
+		fall(idx);
+		assembleBorder();
+		w.update();
+	}
+
+	fall(132);
+	assembleBorder();
+	w.update();
+
+	sound.playSample(nullptr, 0);
+	sound.playSample(&voc2, 0);
+	sound.playFX(31);
+
+	fall(127);
+	assembleBorder();
+	w.update();
+
+	fall(132);
+	assembleBorder();
+	w.update();
+
+	fall(129);
+	assembleBorder();
+	w.update();
+
+	fall(132);
+	assembleBorder();
+	w.update();
+
+	shake();
+}
+
+void Interface::saveFall() {
+
+}
+
+void Interface::fall(int v) {
+
+}
+
+void Interface::shake() {
+
+}
 
 } // End of namespace Xeen
diff --git a/engines/xeen/interface.h b/engines/xeen/interface.h
index 5980175..57db3f2 100644
--- a/engines/xeen/interface.h
+++ b/engines/xeen/interface.h
@@ -85,6 +85,14 @@ private:
 	void doStepCode();
 
 	bool checkMoveDirection(int key);
+
+	void handleFalling();
+
+	void saveFall();
+
+	void fall(int v);
+
+	void shake();
 public:
 	int _intrIndex1;
 	Common::String _interfaceText;
@@ -108,6 +116,8 @@ public:
 	void rest();
 
 	void bash(const Common::Point &pt, Direction direction);
+
+	void draw3d(bool updateFlag);
 };
 
 } // End of namespace Xeen
diff --git a/engines/xeen/interface_map.cpp b/engines/xeen/interface_map.cpp
index 262c945..6893c71 100644
--- a/engines/xeen/interface_map.cpp
+++ b/engines/xeen/interface_map.cpp
@@ -406,12 +406,9 @@ void InterfaceMap::setup() {
 	_charPowSprites.load("charpow.icn");
 }
 
-void InterfaceMap::draw3d(bool updateFlag) {
+void InterfaceMap::drawMap(bool updateFlag) {
 	Combat &combat = *_vm->_combat;
-	EventsManager &events = *_vm->_events;
 	Map &map = *_vm->_map;
-	Party &party = *_vm->_party;
-	Screen &screen = *_vm->_screen;
 	Scripts &scripts = *_vm->_scripts;
 
 	const int COMBAT_POS_X[3][2] = { { 102, 134 }, { 36, 67 }, { 161, 161 } };
@@ -419,9 +416,6 @@ void InterfaceMap::draw3d(bool updateFlag) {
 	const int OUTDOOR_INDEXES[3] = { 119, 113, 116 };
 	const int COMBAT_OFFSET_X[4] = { 8, 6, 4, 2 };
 
-	if (screen._windows[11]._enabled)
-		return;
-
 	_flipUIFrame = (_flipUIFrame + 1) % 4;
 	if (_flipUIFrame == 0)
 		_flipWater = !_flipWater;
@@ -727,41 +721,6 @@ void InterfaceMap::draw3d(bool updateFlag) {
 	}
 
 	animate3d();
-	drawMiniMap();
-
-	if (party._falling == 1) {
-		error("TODO: Indoor falling");
-	}
-
-	if (party._falling == 2) {
-		screen.saveBackground(1);
-	}
-
-	assembleBorder();
-
-	// Draw any on-screen text if flagged to do so
-	if (_upDoorText && combat._attackMonsters[0] == -1) {
-		screen._windows[3].writeString(_screenText);
-	}
-
-	if (updateFlag) {
-		screen._windows[1].update();
-		screen._windows[3].update();
-	}
-
-	// TODO: more stuff
-
-	_vm->_party->_stepped = false;
-	if (_vm->_mode == MODE_9) {
-		// TODO
-	}
-
-	// TODO: Check use of updateFlag here. Original doesn't have it, but I
-	// wanted to ensure in places like the AutoMapDialog, that the draw3d
-	// doesn't result in the screen updating until the dialog has had
-	// a chance to full render itself
-	if (updateFlag)
-		events.wait(2);
 }
 
 /**
diff --git a/engines/xeen/interface_map.h b/engines/xeen/interface_map.h
index 660213a..b65b7d6 100644
--- a/engines/xeen/interface_map.h
+++ b/engines/xeen/interface_map.h
@@ -126,6 +126,8 @@ protected:
 	void drawMiniMap();
 
 	virtual void setup();
+
+	void drawMap(bool updateFlag);
 public:
 	OutdoorDrawList _outdoorList;
 	IndoorDrawList _indoorList;
@@ -146,8 +148,6 @@ public:
 
 	virtual ~InterfaceMap() {}
 
-	void draw3d(bool updateFlag);
-
 	void setIndoorsMonsters();
 
 	void setIndoorsObjects();


Commit: 6605a0c505b2e58bd458fab6865e4db1bf55972b
    https://github.com/scummvm/scummvm/commit/6605a0c505b2e58bd458fab6865e4db1bf55972b
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-02-15T12:20:44-05:00

Commit Message:
XEEN: Implemented more code from end of draw3d

Changed paths:
    engines/xeen/combat.cpp
    engines/xeen/combat.h
    engines/xeen/interface.cpp
    engines/xeen/interface.h
    engines/xeen/interface_map.cpp
    engines/xeen/interface_map.h



diff --git a/engines/xeen/combat.cpp b/engines/xeen/combat.cpp
index fec244b..4d0add1 100644
--- a/engines/xeen/combat.cpp
+++ b/engines/xeen/combat.cpp
@@ -22,6 +22,7 @@
 
 #include "xeen/combat.h"
 #include "common/algorithm.h"
+#include "common/textconsole.h"
 
 namespace Xeen {
 
@@ -42,4 +43,9 @@ void Combat::clear() {
 	Common::fill(&_attackMonsters[0], &_attackMonsters[26], -1);
 }
 
+void Combat::doCombat() {
+	error("TODO: doCombat");
+}
+
+
 } // End of namespace Xeen
diff --git a/engines/xeen/combat.h b/engines/xeen/combat.h
index ef82de5..c5c7f08 100644
--- a/engines/xeen/combat.h
+++ b/engines/xeen/combat.h
@@ -65,6 +65,8 @@ public:
 	Combat(XeenEngine *vm);
 
 	void clear();
+
+	void doCombat();
 };
 
 } // End of namespace Xeen
diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp
index 51a59e1..89747d1 100644
--- a/engines/xeen/interface.cpp
+++ b/engines/xeen/interface.cpp
@@ -937,12 +937,13 @@ void Interface::draw3d(bool updateFlag) {
 	EventsManager &events = *_vm->_events;
 	Party &party = *_vm->_party;
 	Screen &screen = *_vm->_screen;
+	Scripts &scripts = *_vm->_scripts;
 	
 	if (screen._windows[11]._enabled)
 		return;
 
 	// Draw the map
-	drawMap(updateFlag);
+	drawMap();
 
 	// Draw the minimap
 	drawMiniMap();
@@ -966,11 +967,20 @@ void Interface::draw3d(bool updateFlag) {
 		screen._windows[3].update();
 	}
 
-	// TODO: more stuff
+	if (combat._attackMonsters[0] != -1 || combat._attackMonsters[1] != -1
+			|| combat._attackMonsters[2] != -1) {
+		if ((_vm->_mode == MODE_1 || _vm->_mode == MODE_SLEEPING) && !_flag1
+				&& !_charsShooting && _vm->_moveMonsters) {
+			combat.doCombat();
+			if (scripts._eventSkipped)
+				scripts.checkEvents();
+		}
+	}
 
-	_vm->_party->_stepped = false;
+	party._stepped = false;
 	if (_vm->_mode == MODE_9) {
-		// TODO
+		// TODO: Save current scripts data?
+		error("TODO: save scripts?");
 	}
 
 	// TODO: Check use of updateFlag here. Original doesn't have it, but I
@@ -1029,7 +1039,7 @@ void Interface::handleFalling() {
 	assembleBorder();
 	w.update();
 
-	shake();
+	shake(10);
 }
 
 void Interface::saveFall() {
@@ -1040,7 +1050,7 @@ void Interface::fall(int v) {
 
 }
 
-void Interface::shake() {
+void Interface::shake(int time) {
 
 }
 
diff --git a/engines/xeen/interface.h b/engines/xeen/interface.h
index 57db3f2..660d1b1 100644
--- a/engines/xeen/interface.h
+++ b/engines/xeen/interface.h
@@ -92,7 +92,7 @@ private:
 
 	void fall(int v);
 
-	void shake();
+	void shake(int time);
 public:
 	int _intrIndex1;
 	Common::String _interfaceText;
diff --git a/engines/xeen/interface_map.cpp b/engines/xeen/interface_map.cpp
index 6893c71..a098800 100644
--- a/engines/xeen/interface_map.cpp
+++ b/engines/xeen/interface_map.cpp
@@ -406,7 +406,7 @@ void InterfaceMap::setup() {
 	_charPowSprites.load("charpow.icn");
 }
 
-void InterfaceMap::drawMap(bool updateFlag) {
+void InterfaceMap::drawMap() {
 	Combat &combat = *_vm->_combat;
 	Map &map = *_vm->_map;
 	Scripts &scripts = *_vm->_scripts;
diff --git a/engines/xeen/interface_map.h b/engines/xeen/interface_map.h
index b65b7d6..3fe851b 100644
--- a/engines/xeen/interface_map.h
+++ b/engines/xeen/interface_map.h
@@ -127,7 +127,7 @@ protected:
 
 	virtual void setup();
 
-	void drawMap(bool updateFlag);
+	void drawMap();
 public:
 	OutdoorDrawList _outdoorList;
 	IndoorDrawList _indoorList;


Commit: a90ad5b4c18ad067b0839f22a24a09db69570ac8
    https://github.com/scummvm/scummvm/commit/a90ad5b4c18ad067b0839f22a24a09db69570ac8
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-02-15T12:26:23-05:00

Commit Message:
XEEN: Move drawMiniMap to Interface class

Changed paths:
    engines/xeen/interface.cpp
    engines/xeen/interface.h
    engines/xeen/interface_map.cpp
    engines/xeen/interface_map.h



diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp
index 89747d1..f81e518 100644
--- a/engines/xeen/interface.cpp
+++ b/engines/xeen/interface.cpp
@@ -1054,4 +1054,381 @@ void Interface::shake(int time) {
 
 }
 
+void Interface::drawMiniMap() {
+	Map &map = *_vm->_map;
+	Party &party = *_vm->_party;
+	Resources &res = *_vm->_resources;
+	Screen &screen = *_vm->_screen;
+	Window &window1 = screen._windows[1];
+
+	if (screen._windows[2]._enabled || screen._windows[10]._enabled)
+		return;
+	if (!party._automapOn && !party._wizardEyeActive) {
+		// Draw the Might & Magic logo
+		res._globalSprites.draw(window1, 5, Common::Point(232, 9));
+		return;
+	}
+
+	int v, frame;
+	int frame2 = _overallFrame * 2;
+	bool eyeActive = party._wizardEyeActive;
+	if (party._automapOn)
+		party._wizardEyeActive = false;
+
+	if (map._isOutdoors) {
+		res._globalSprites.draw(window1, 15, Common::Point(237, 12));
+
+		for (int rowNum = 0, yp = 12, yDiff = 3; rowNum < MINIMAP_SIZE; ++rowNum, yp += 8, --yDiff) {
+			for (int colNum = 0, xp = 237, xDiff = -3; colNum < MINIMAP_SIZE; ++colNum, xp += 10, ++xDiff) {
+				v = map.mazeLookup(
+					Common::Point(party._mazePosition.x + xDiff, party._mazePosition.y + yDiff),
+					4);
+				frame = map.mazeDataCurrent()._surfaceTypes[v];
+
+				if (frame != -1 && (map._currentSteppedOn || party._wizardEyeActive)) {
+					map._tileSprites.draw(window1, frame, Common::Point(xp, yp));
+				}
+			}
+		}
+
+		for (int rowNum = 0, yp = 12, yDiff = 3; rowNum < MINIMAP_SIZE; ++rowNum, yp += 8, --yDiff) {
+			for (int colNum = 0, xp = 237, xDiff = -3; colNum < MINIMAP_SIZE; ++colNum, xp += 10, ++xDiff) {
+				v = map.mazeLookup(
+					Common::Point(party._mazePosition.x + xDiff, party._mazePosition.y + yDiff),
+					4);
+				frame = map.mazeData()._wallTypes[v];
+
+				if (frame != -1 && (map._currentSteppedOn || party._wizardEyeActive)) {
+					map._tileSprites.draw(window1, frame + 16, Common::Point(xp, yp));
+				}
+			}
+		}
+
+		for (int rowNum = 0, yp = 12, yDiff = 3; rowNum < MINIMAP_SIZE; ++rowNum, yp += 8, --yDiff) {
+			for (int colNum = 0, xp = 237, xDiff = -3; colNum < MINIMAP_SIZE; ++colNum, xp += 10, ++xDiff) {
+				v = map.mazeLookup(
+					Common::Point(party._mazePosition.x + xDiff, party._mazePosition.y + yDiff),
+					4);
+
+				if (v != -1 && (map._currentSteppedOn || party._wizardEyeActive)) {
+					map._tileSprites.draw(window1, v + 32, Common::Point(xp, yp));
+				}
+			}
+		}
+
+		// Draw the direction arrow
+		res._globalSprites.draw(window1, party._mazeDirection + 1,
+			Common::Point(267, 36));
+	}
+	else {
+		frame2 = (frame2 + 2) % 8;
+
+		// First draw the default surface bases for each cell to show
+		for (int rowNum = 0, yp = 12, yDiff = 3; rowNum < MINIMAP_SIZE; ++rowNum, yp += 8, --yDiff) {
+			for (int colNum = 0, xp = 237, xDiff = -3; colNum < MINIMAP_SIZE; ++colNum, xp += 10, ++xDiff) {
+				v = map.mazeLookup(
+					Common::Point(party._mazePosition.x + xDiff, party._mazePosition.y + yDiff),
+					0, 0xffff);
+
+				if (v != INVALID_CELL && (map._currentSteppedOn || party._wizardEyeActive)) {
+					map._tileSprites.draw(window1, 0, Common::Point(xp, yp));
+				}
+			}
+		}
+
+		// Draw correct surface bases for revealed tiles
+		for (int rowNum = 0, yp = 17, yDiff = 3; rowNum < MINIMAP_SIZE; ++rowNum, yp += 8, --yDiff) {
+			for (int colNum = 0, xp = 242, xDiff = -3; colNum < MINIMAP_SIZE; ++colNum, xp += 10, ++xDiff) {
+				v = map.mazeLookup(
+					Common::Point(party._mazePosition.x + xDiff, party._mazePosition.y + yDiff),
+					0, 0xffff);
+				int surfaceId = map.mazeData()._surfaceTypes[map._currentSurfaceId];
+
+				if (v != INVALID_CELL && map._currentSurfaceId &&
+					(map._currentSteppedOn || party._wizardEyeActive)) {
+					map._tileSprites.draw(window1, surfaceId + 36, Common::Point(xp, yp));
+				}
+			}
+		}
+
+		v = map.mazeLookup(Common::Point(party._mazePosition.x - 4, party._mazePosition.y + 4), 0xffff, 0);
+		if (v != INVALID_CELL && map._currentSurfaceId &&
+			(map._currentSteppedOn || party._wizardEyeActive)) {
+			map._tileSprites.draw(window1,
+				map.mazeData()._surfaceTypes[map._currentSurfaceId] + 36,
+				Common::Point(232, 9));
+		}
+
+		// Handle drawing surface sprites partially clipped at the left edge
+		for (int rowNum = 0, yp = 17, yDiff = 3; rowNum < MINIMAP_SIZE; ++rowNum, --yDiff, yp += 8) {
+			v = map.mazeLookup(
+				Common::Point(party._mazePosition.x - 4, party._mazePosition.y + yDiff),
+				0, 0xffff);
+
+			if (v != INVALID_CELL && map._currentSurfaceId &&
+				(map._currentSteppedOn || party._wizardEyeActive)) {
+				map._tileSprites.draw(window1,
+					map.mazeData()._surfaceTypes[map._currentSurfaceId] + 36,
+					Common::Point(232, yp));
+			}
+		}
+
+		// Handle drawing surface sprites partially clipped at the top edge
+		for (int colNum = 0, xp = 242, xDiff = -3; colNum < MINIMAP_SIZE; ++colNum, ++xDiff, xp += 8) {
+			v = map.mazeLookup(
+				Common::Point(party._mazePosition.x + xDiff, party._mazePosition.y + 4),
+				0, 0xffff);
+
+			if (v != INVALID_CELL && map._currentSurfaceId &&
+				(map._currentSteppedOn || party._wizardEyeActive)) {
+				map._tileSprites.draw(window1,
+					map.mazeData()._surfaceTypes[map._currentSurfaceId] + 36,
+					Common::Point(xp, 9));
+			}
+		}
+
+		//
+		for (int idx = 0, xp = 237, yp = 60, xDiff = -3; idx < MINIMAP_SIZE;
+			++idx, ++xDiff, xp += 10, yp -= 8) {
+			v = map.mazeLookup(
+				Common::Point(party._mazePosition.x - 4, party._mazePosition.y - 3 + idx),
+				12, 0xffff);
+
+			switch (v) {
+			case 1:
+				frame = 18;
+				break;
+			case 3:
+				frame = 22;
+				break;
+			case 4:
+			case 13:
+				frame = 16;
+				break;
+			case 5:
+			case 8:
+				frame = 2;
+				break;
+			case 6:
+				frame = 30;
+				break;
+			case 7:
+				frame = 32;
+				break;
+			case 9:
+				frame = 24;
+				break;
+			case 10:
+				frame = 28;
+				break;
+			case 11:
+				frame = 14;
+				break;
+			case 12:
+				frame = frame2 + 4;
+				break;
+			case 14:
+				frame = 24;
+				break;
+			case 15:
+				frame = 26;
+				break;
+			default:
+				frame = -1;
+				break;
+			}
+
+			if (frame != -1 && (map._currentSteppedOn || party._wizardEyeActive))
+				map._tileSprites.draw(window1, frame, Common::Point(222, yp));
+
+			v = map.mazeLookup(
+				Common::Point(party._mazePosition.x - 3 + idx, party._mazePosition.y + 4),
+				0);
+
+			switch (v) {
+			case 1:
+				frame = 19;
+				break;
+			case 2:
+				frame = 35;
+				break;
+			case 3:
+				frame = 23;
+				break;
+			case 4:
+			case 13:
+				frame = 17;
+				break;
+			case 5:
+			case 8:
+				frame = 3;
+				break;
+			case 6:
+				frame = 31;
+				break;
+			case 7:
+				frame = 33;
+				break;
+			case 9:
+				frame = 21;
+				break;
+			case 10:
+				frame = 29;
+				break;
+			case 11:
+				frame = 15;
+				break;
+			case 12:
+				frame = frame2 + 5;
+				break;
+			case 14:
+				frame = 25;
+				break;
+			case 15:
+				frame = 27;
+				break;
+			default:
+				frame = -1;
+				break;
+			}
+
+			if (frame != -1 && (map._currentSteppedOn || party._wizardEyeActive))
+				map._tileSprites.draw(window1, frame, Common::Point(xp, 4));
+		}
+
+		// Draw the front/back walls of cells in the minimap
+		for (int rowNum = 0, yp = 12, yDiff = 3; rowNum < MINIMAP_SIZE;
+			++rowNum, --yDiff, yp += 8) {
+			for (int colNum = 0, xp = 237, xDiff = -3; colNum < MINIMAP_SIZE;
+				++colNum, ++xDiff, xp += 10) {
+				if (colNum == 4 && rowNum == 4) {
+					// Center of the minimap. Draw the direction arrow
+					res._globalSprites.draw(window1, party._mazeDirection + 1,
+						Common::Point(272, 40));
+				}
+
+				v = map.mazeLookup(Common::Point(party._mazePosition.x + xDiff,
+					party._mazePosition.y + yDiff), 12, 0xffff);
+				switch (v) {
+				case 1:
+					frame = 18;
+					break;
+				case 3:
+					frame = 22;
+					break;
+				case 4:
+				case 13:
+					frame = 16;
+					break;
+				case 5:
+				case 8:
+					frame = 2;
+					break;
+				case 6:
+					frame = 30;
+					break;
+				case 7:
+					frame = 32;
+					break;
+				case 9:
+					frame = 20;
+					break;
+				case 10:
+					frame = 28;
+					break;
+				case 11:
+					frame = 14;
+					break;
+				case 12:
+					frame = frame2 + 4;
+					break;
+				case 14:
+					frame = 24;
+					break;
+				case 15:
+					frame = 26;
+					break;
+				default:
+					frame = -1;
+					break;
+				}
+
+				if (frame != -1 && (map._currentSteppedOn || party._wizardEyeActive)) {
+					map._tileSprites.draw(window1, frame, Common::Point(xp, yp));
+				}
+
+				v = map.mazeLookup(Common::Point(party._mazePosition.x + xDiff,
+					party._mazePosition.y + yDiff), 12, 0xffff);
+				switch (v) {
+				case 1:
+					frame = 19;
+					break;
+				case 2:
+					frame = 35;
+					break;
+				case 3:
+					frame = 23;
+					break;
+				case 4:
+				case 13:
+					frame = 17;
+					break;
+				case 5:
+				case 8:
+					frame = 3;
+					break;
+				case 6:
+					frame = 31;
+					break;
+				case 7:
+					frame = 33;
+					break;
+				case 9:
+					frame = 21;
+					break;
+				case 10:
+					frame = 29;
+					break;
+				case 11:
+					frame = 15;
+					break;
+				case 12:
+					frame = frame2 + 5;
+					break;
+				case 14:
+					frame = 25;
+					break;
+				case 15:
+					frame = 27;
+					break;
+				default:
+					frame = -1;
+					break;
+				}
+
+				if (v == -1 && (map._currentSteppedOn || party._wizardEyeActive)) {
+					map._tileSprites.draw(window1, frame, Common::Point(xp, yp));
+				}
+			}
+		}
+
+		// Draw the top of blocked/wall cells on the map
+		for (int rowNum = 0, yp = 12, yDiff = 3; rowNum < MINIMAP_SIZE; ++rowNum, yp += 8, --yDiff) {
+			for (int colNum = 0, xp = 237, xDiff = -3; colNum < MINIMAP_SIZE; ++colNum, xp += 10, ++xDiff) {
+				v = map.mazeLookup(
+					Common::Point(party._mazePosition.x + xDiff, party._mazePosition.y + yDiff),
+					0, 0xffff);
+
+				if (v == INVALID_CELL || (!map._currentSteppedOn && !party._wizardEyeActive)) {
+					map._tileSprites.draw(window1, 1, Common::Point(xp, yp));
+				}
+			}
+		}
+	}
+
+	// Draw outer rectangle around the automap
+	res._globalSprites.draw(window1, 6, Common::Point(223, 3));
+	party._wizardEyeActive = eyeActive;
+}
+
 } // End of namespace Xeen
diff --git a/engines/xeen/interface.h b/engines/xeen/interface.h
index 660d1b1..4435310 100644
--- a/engines/xeen/interface.h
+++ b/engines/xeen/interface.h
@@ -93,6 +93,8 @@ private:
 	void fall(int v);
 
 	void shake(int time);
+
+	void drawMiniMap();
 public:
 	int _intrIndex1;
 	Common::String _interfaceText;
diff --git a/engines/xeen/interface_map.cpp b/engines/xeen/interface_map.cpp
index a098800..4f408d1 100644
--- a/engines/xeen/interface_map.cpp
+++ b/engines/xeen/interface_map.cpp
@@ -4556,380 +4556,4 @@ void InterfaceMap::assembleBorder() {
 		screen._windows[12].frame();
 }
 
-void InterfaceMap::drawMiniMap() {
-	Map &map = *_vm->_map;
-	Party &party = *_vm->_party;
-	Resources &res = *_vm->_resources;
-	Screen &screen = *_vm->_screen;
-	Window &window1 = screen._windows[1];
-
-	if (screen._windows[2]._enabled || screen._windows[10]._enabled)
-		return;
-	if (!party._automapOn && !party._wizardEyeActive) {
-		// Draw the Might & Magic logo
-		res._globalSprites.draw(window1, 5, Common::Point(232, 9));
-		return;
-	}
-
-	int v, frame;
-	int frame2 = _overallFrame * 2;
-	bool eyeActive = party._wizardEyeActive;
-	if (party._automapOn)
-		party._wizardEyeActive = false;
-
-	if (map._isOutdoors) {
-		res._globalSprites.draw(window1, 15, Common::Point(237, 12));
-
-		for (int rowNum = 0, yp = 12, yDiff = 3; rowNum < MINIMAP_SIZE; ++rowNum, yp += 8, --yDiff) {
-			for (int colNum = 0, xp = 237, xDiff = -3; colNum < MINIMAP_SIZE; ++colNum, xp += 10, ++xDiff) {
-				v = map.mazeLookup(
-					Common::Point(party._mazePosition.x + xDiff, party._mazePosition.y + yDiff),
-					4);
-				frame = map.mazeDataCurrent()._surfaceTypes[v];
-
-				if (frame != -1 && (map._currentSteppedOn || party._wizardEyeActive)) {
-					map._tileSprites.draw(window1, frame, Common::Point(xp, yp));
-				}
-			}
-		}
-
-		for (int rowNum = 0, yp = 12, yDiff = 3; rowNum < MINIMAP_SIZE; ++rowNum, yp += 8, --yDiff) {
-			for (int colNum = 0, xp = 237, xDiff = -3; colNum < MINIMAP_SIZE; ++colNum, xp += 10, ++xDiff) {
-				v = map.mazeLookup(
-					Common::Point(party._mazePosition.x + xDiff, party._mazePosition.y + yDiff),
-					4);
-				frame = map.mazeData()._wallTypes[v];
-
-				if (frame != -1 && (map._currentSteppedOn || party._wizardEyeActive)) {
-					map._tileSprites.draw(window1, frame + 16, Common::Point(xp, yp));
-				}
-			}
-		}
-
-		for (int rowNum = 0, yp = 12, yDiff = 3; rowNum < MINIMAP_SIZE; ++rowNum, yp += 8, --yDiff) {
-			for (int colNum = 0, xp = 237, xDiff = -3; colNum < MINIMAP_SIZE; ++colNum, xp += 10, ++xDiff) {
-				v = map.mazeLookup(
-					Common::Point(party._mazePosition.x + xDiff, party._mazePosition.y + yDiff),
-					4);
-
-				if (v != -1 && (map._currentSteppedOn || party._wizardEyeActive)) {
-					map._tileSprites.draw(window1, v + 32, Common::Point(xp, yp));
-				}
-			}
-		}
-		
-		// Draw the direction arrow
-		res._globalSprites.draw(window1, party._mazeDirection + 1,
-			Common::Point(267, 36));
-	} else {
-		frame2 = (frame2 + 2) % 8;
-
-		// First draw the default surface bases for each cell to show
-		for (int rowNum = 0, yp = 12, yDiff = 3; rowNum < MINIMAP_SIZE; ++rowNum, yp += 8, --yDiff) {
-			for (int colNum = 0, xp = 237, xDiff = -3; colNum < MINIMAP_SIZE; ++colNum, xp += 10, ++xDiff) {
-				v = map.mazeLookup(
-					Common::Point(party._mazePosition.x + xDiff, party._mazePosition.y + yDiff),
-					0, 0xffff);
-
-				if (v != INVALID_CELL && (map._currentSteppedOn || party._wizardEyeActive)) {
-					map._tileSprites.draw(window1, 0, Common::Point(xp, yp));
-				}
-			}
-		}
-		
-		// Draw correct surface bases for revealed tiles
-		for (int rowNum = 0, yp = 17, yDiff = 3; rowNum < MINIMAP_SIZE; ++rowNum, yp += 8, --yDiff) {
-			for (int colNum = 0, xp = 242, xDiff = -3; colNum < MINIMAP_SIZE; ++colNum, xp += 10, ++xDiff) {
-				v = map.mazeLookup(
-					Common::Point(party._mazePosition.x + xDiff, party._mazePosition.y + yDiff),
-					0, 0xffff);
-				int surfaceId = map.mazeData()._surfaceTypes[map._currentSurfaceId];
-
-				if (v != INVALID_CELL && map._currentSurfaceId &&
-						(map._currentSteppedOn || party._wizardEyeActive)) {
-					map._tileSprites.draw(window1, surfaceId + 36, Common::Point(xp, yp));
-				}
-			}
-		}
-		
-		v = map.mazeLookup(Common::Point(party._mazePosition.x - 4, party._mazePosition.y + 4), 0xffff, 0);
-		if (v != INVALID_CELL && map._currentSurfaceId &&
-				(map._currentSteppedOn || party._wizardEyeActive)) {
-			map._tileSprites.draw(window1,
-				map.mazeData()._surfaceTypes[map._currentSurfaceId] + 36,
-				Common::Point(232, 9));
-		}
-		
-		// Handle drawing surface sprites partially clipped at the left edge
-		for (int rowNum = 0, yp = 17, yDiff = 3; rowNum < MINIMAP_SIZE; ++rowNum, --yDiff, yp += 8) {
-			v = map.mazeLookup(
-					Common::Point(party._mazePosition.x - 4, party._mazePosition.y + yDiff),
-					0, 0xffff);
-
-			if (v != INVALID_CELL && map._currentSurfaceId &&
-					(map._currentSteppedOn || party._wizardEyeActive)) {
-				map._tileSprites.draw(window1,
-					map.mazeData()._surfaceTypes[map._currentSurfaceId] + 36,
-					Common::Point(232, yp));
-			}
-		}
-
-		// Handle drawing surface sprites partially clipped at the top edge
-		for (int colNum = 0, xp = 242, xDiff = -3; colNum < MINIMAP_SIZE; ++colNum, ++xDiff, xp += 8) {
-			v = map.mazeLookup(
-				Common::Point(party._mazePosition.x + xDiff, party._mazePosition.y + 4),
-				0, 0xffff);
-
-			if (v != INVALID_CELL && map._currentSurfaceId &&
-					(map._currentSteppedOn || party._wizardEyeActive)) {
-				map._tileSprites.draw(window1,
-					map.mazeData()._surfaceTypes[map._currentSurfaceId] + 36,
-					Common::Point(xp, 9));
-			}
-		}
-		
-		//
-		for (int idx = 0, xp = 237, yp = 60, xDiff = -3; idx < MINIMAP_SIZE; 
-				++idx, ++xDiff, xp += 10, yp -= 8) {
-			v = map.mazeLookup(
-				Common::Point(party._mazePosition.x - 4, party._mazePosition.y - 3 + idx),
-				12, 0xffff);
-
-			switch (v) {
-			case 1:
-				frame = 18;
-				break;
-			case 3:
-				frame = 22;
-				break;
-			case 4:
-			case 13:
-				frame = 16;
-				break;
-			case 5:
-			case 8:
-				frame = 2;
-				break;
-			case 6:
-				frame = 30;
-				break;
-			case 7:
-				frame = 32;
-				break;
-			case 9:
-				frame = 24;
-				break;
-			case 10:
-				frame = 28;
-				break;
-			case 11:
-				frame = 14;
-				break;
-			case 12:
-				frame = frame2 + 4;
-				break;
-			case 14:
-				frame = 24;
-				break;
-			case 15:
-				frame = 26;
-				break;
-			default:
-				frame = -1;
-				break;
-			}
-
-			if (frame != -1 && (map._currentSteppedOn || party._wizardEyeActive))
-				map._tileSprites.draw(window1, frame, Common::Point(222, yp));
-
-			v = map.mazeLookup(
-				Common::Point(party._mazePosition.x - 3 + idx, party._mazePosition.y + 4),
-				0);
-
-			switch (v) {
-			case 1:
-				frame = 19;
-				break;
-			case 2:
-				frame = 35;
-				break;
-			case 3:
-				frame = 23;
-				break;
-			case 4:
-			case 13:
-				frame = 17;
-				break;
-			case 5:
-			case 8:
-				frame = 3;
-				break;
-			case 6:
-				frame = 31;
-				break;
-			case 7:
-				frame = 33;
-				break;
-			case 9:
-				frame = 21;
-				break;
-			case 10:
-				frame = 29;
-				break;
-			case 11:
-				frame = 15;
-				break;
-			case 12:
-				frame = frame2 + 5;
-				break;
-			case 14:
-				frame = 25;
-				break;
-			case 15:
-				frame = 27;
-				break;
-			default:
-				frame = -1;
-				break;
-			}
-
-			if (frame != -1 && (map._currentSteppedOn || party._wizardEyeActive))
-				map._tileSprites.draw(window1, frame, Common::Point(xp, 4));
-		}
-
-		// Draw the front/back walls of cells in the minimap
-		for (int rowNum = 0, yp = 12, yDiff = 3; rowNum < MINIMAP_SIZE;
-				++rowNum, --yDiff, yp += 8) {
-			for (int colNum = 0, xp = 237, xDiff = -3; colNum < MINIMAP_SIZE;
-					++colNum, ++xDiff, xp += 10) {
-				if (colNum == 4 && rowNum == 4) {
-					// Center of the minimap. Draw the direction arrow
-					res._globalSprites.draw(window1, party._mazeDirection + 1,
-						Common::Point(272, 40));
-				}
-
-				v = map.mazeLookup(Common::Point(party._mazePosition.x + xDiff,
-					party._mazePosition.y + yDiff), 12, 0xffff);
-				switch (v) {
-				case 1:
-					frame = 18;
-					break;
-				case 3:
-					frame = 22;
-					break;
-				case 4:
-				case 13:
-					frame = 16;
-					break;
-				case 5:
-				case 8:
-					frame = 2;
-					break;
-				case 6:
-					frame = 30;
-					break;
-				case 7:
-					frame = 32;
-					break;
-				case 9:
-					frame = 20;
-					break;
-				case 10:
-					frame = 28;
-					break;
-				case 11:
-					frame = 14;
-					break;
-				case 12:
-					frame = frame2 + 4;
-					break;
-				case 14:
-					frame = 24;
-					break;
-				case 15:
-					frame = 26;
-					break;
-				default:
-					frame = -1;
-					break;
-				}
-
-				if (frame != -1 && (map._currentSteppedOn || party._wizardEyeActive)) {
-					map._tileSprites.draw(window1, frame, Common::Point(xp, yp));
-				}
-
-				v = map.mazeLookup(Common::Point(party._mazePosition.x + xDiff,
-					party._mazePosition.y + yDiff), 12, 0xffff);
-				switch (v) {
-				case 1:
-					frame = 19;
-					break;
-				case 2:
-					frame = 35;
-					break;
-				case 3:
-					frame = 23;
-					break;
-				case 4:
-				case 13:
-					frame = 17;
-					break;
-				case 5:
-				case 8:
-					frame = 3;
-					break;
-				case 6:
-					frame = 31;
-					break;
-				case 7:
-					frame = 33;
-					break;
-				case 9:
-					frame = 21;
-					break;
-				case 10:
-					frame = 29;
-					break;
-				case 11:
-					frame = 15;
-					break;
-				case 12:
-					frame = frame2 + 5;
-					break;
-				case 14:
-					frame = 25;
-					break;
-				case 15:
-					frame = 27;
-					break;
-				default:
-					frame = -1;
-					break;
-				}
-
-				if (v == -1 && (map._currentSteppedOn || party._wizardEyeActive)) {
-					map._tileSprites.draw(window1, frame, Common::Point(xp, yp));
-				}
-			}
-		}
-
-		// Draw the top of blocked/wall cells on the map
-		for (int rowNum = 0, yp = 12, yDiff = 3; rowNum < MINIMAP_SIZE; ++rowNum, yp += 8, --yDiff) {
-			for (int colNum = 0, xp = 237, xDiff = -3; colNum < MINIMAP_SIZE; ++colNum, xp += 10, ++xDiff) {
-				v = map.mazeLookup(
-					Common::Point(party._mazePosition.x + xDiff, party._mazePosition.y + yDiff),
-					0, 0xffff);
-
-				if (v == INVALID_CELL || (!map._currentSteppedOn && !party._wizardEyeActive)) {
-					map._tileSprites.draw(window1, 1, Common::Point(xp, yp));
-				}
-			}
-		}
-	}
-
-	// Draw outer rectangle around the automap
-	res._globalSprites.draw(window1, 6, Common::Point(223, 3));
-	party._wizardEyeActive = eyeActive;
-}
-
 } // End of namespace Xeen
diff --git a/engines/xeen/interface_map.h b/engines/xeen/interface_map.h
index 3fe851b..a062624 100644
--- a/engines/xeen/interface_map.h
+++ b/engines/xeen/interface_map.h
@@ -123,8 +123,6 @@ protected:
 
 	void animate3d();
 
-	void drawMiniMap();
-
 	virtual void setup();
 
 	void drawMap();


Commit: 74b4d91f4a5b68b2aa0ec2a46f76131ccf897535
    https://github.com/scummvm/scummvm/commit/74b4d91f4a5b68b2aa0ec2a46f76131ccf897535
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-02-15T14:10:37-05:00

Commit Message:
XEEN: Implemented startFalling

Changed paths:
    engines/xeen/combat.cpp
    engines/xeen/combat.h
    engines/xeen/interface.cpp
    engines/xeen/interface.h
    engines/xeen/map.cpp
    engines/xeen/party.cpp
    engines/xeen/party.h
    engines/xeen/scripts.cpp
    engines/xeen/scripts.h



diff --git a/engines/xeen/combat.cpp b/engines/xeen/combat.cpp
index 4d0add1..582444d 100644
--- a/engines/xeen/combat.cpp
+++ b/engines/xeen/combat.cpp
@@ -47,5 +47,9 @@ void Combat::doCombat() {
 	error("TODO: doCombat");
 }
 
+void Combat::giveCharDamage(int damage, int v2, int v3) {
+	error("TODO: giveCharDamage");
+}
+
 
 } // End of namespace Xeen
diff --git a/engines/xeen/combat.h b/engines/xeen/combat.h
index c5c7f08..5058742 100644
--- a/engines/xeen/combat.h
+++ b/engines/xeen/combat.h
@@ -67,6 +67,8 @@ public:
 	void clear();
 
 	void doCombat();
+
+	void giveCharDamage(int damage, int v2, int v3);
 };
 
 } // End of namespace Xeen
diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp
index f81e518..8a35563 100644
--- a/engines/xeen/interface.cpp
+++ b/engines/xeen/interface.cpp
@@ -569,7 +569,7 @@ void Interface::doStepCode() {
 		// We can fly, we can.. oh wait, we can't!
 		damage = 100;
 		party._damageType = DT_PHYSICAL;
-		party._falling = true;
+		_falling = true;
 		break;
 	case SURFTYPE_DESERT:
 		// Without navigation skills, simulate getting lost by adding extra time
@@ -579,7 +579,7 @@ void Interface::doStepCode() {
 	case SURFTYPE_CLOUD:
 		if (!party._levitateActive) {
 			party._damageType = DT_PHYSICAL;
-			party._falling = true;
+			_falling = true;
 			damage = 100;
 		}
 		break;
@@ -588,10 +588,10 @@ void Interface::doStepCode() {
 	}
 
 	if (_vm->_files->_isDarkCc && party._gameFlags[374]) {
-		party._falling = false;
+		_falling = false;
 	} else {
-		if (party._falling)
-			doFalling();
+		if (_falling)
+			startFalling(false);
 
 		if ((party._mazePosition.x & 16) || (party._mazePosition.y & 16)) {
 			if (map._isOutdoors)
@@ -611,17 +611,233 @@ void Interface::doStepCode() {
 	}
 }
 
-void Interface::doFalling() {
-	// TODO
+/**
+ * Start the party falling
+ */
+void Interface::startFalling(bool flag) {
+	Combat &combat = *_vm->_combat;
+	Map &map = *_vm->_map;
+	Party &party = *_vm->_party;
+	Scripts &scripts = *_vm->_scripts;
+	bool isDarkCc = _vm->_files->_isDarkCc;
+
+	if (isDarkCc && party._gameFlags[374]) {
+		_falling = 0;
+		return;
+	}
+
+	_falling = false;
+	draw3d(true);
+	_falling = 2;
+	draw3d(false);
+
+	if (flag) {
+		if (!isDarkCc || party._fallMaze != 0) {
+			party._mazeId = party._fallMaze;
+			party._mazePosition = party._fallPosition;
+		}
+	}
+
+	_falling = true;
+	map.load(party._mazeId);
+	if (flag) {
+		if (((party._mazePosition.x & 16) || (party._mazePosition.y & 16)) &&
+				map._isOutdoors) {
+			map.getNewMaze();
+		}
+	} 
+	
+	if (isDarkCc) {
+		switch (party._mazeId - 25) {
+		case 0:
+		case 26:
+		case 27:
+		case 28:
+		case 29:
+			party._mazeId = 24;
+			party._mazePosition = Common::Point(11, 9);
+			break;
+		case 1:
+		case 30:
+		case 31:
+		case 32:
+		case 33:
+			party._mazeId = 12;
+			party._mazePosition = Common::Point(6, 15);
+			break;
+		case 2:
+		case 34:
+		case 35:
+		case 36:
+		case 37:
+		case 51:
+		case 52:
+		case 53:
+			party._mazeId = 15;
+			party._mazePosition = Common::Point(4, 12);
+			party._mazeDirection = DIR_SOUTH;
+			break;
+		case 40:
+		case 41:
+			party._mazeId = 14;
+			party._mazePosition = Common::Point(8, 3);
+			break;
+		case 44:
+		case 45:
+			party._mazeId = 1;
+			party._mazePosition = Common::Point(8, 7);
+			party._mazeDirection = DIR_NORTH;
+			break;
+		case 49:
+			party._mazeId = 12;
+			party._mazePosition = Common::Point(11, 13);
+			party._mazeDirection = DIR_SOUTH;
+			break;
+		case 57:
+		case 58:
+		case 59:
+			party._mazeId = 5;
+			party._mazePosition = Common::Point(12, 7);
+			party._mazeDirection = DIR_NORTH;
+			break;
+		case 60:
+			party._mazeId = 6;
+			party._mazePosition = Common::Point(12, 3);
+			party._mazeDirection = DIR_NORTH;
+			break;
+		default:
+			party._mazeId = 23;
+			party._mazePosition = Common::Point(12, 10);
+			party._mazeDirection = DIR_NORTH;
+			break;
+		}
+	} else {
+		if (party._mazeId > 89 && party._mazeId < 113) {
+			party._mazeId += 168;
+		} else {
+			switch (party._mazeId - 25) {
+			case 0:
+				party._mazeId = 89;
+				party._mazePosition = Common::Point(2, 14);
+				break;
+			case 1:
+				party._mazeId = 109;
+				party._mazePosition = Common::Point(13, 14);
+				break;
+			case 2:
+				party._mazeId = 112;
+				party._mazePosition = Common::Point(13, 3);
+				break;
+			case 3:
+				party._mazeId = 92;
+				party._mazePosition = Common::Point(2, 3);
+				break;
+			case 12:
+			case 13:
+				party._mazeId = 14;
+				party._mazePosition = Common::Point(10, 2);
+				break;
+			case 16:
+			case 17:
+			case 18:
+				party._mazeId = 4;
+				party._mazePosition = Common::Point(5, 14);
+				break;
+			case 20:
+			case 21:
+			case 22:
+				party._mazeId = 21;
+				party._mazePosition = Common::Point(9, 11);
+				break;
+			case 24:
+			case 25:
+			case 26:
+				party._mazeId = 1;
+				party._mazePosition = Common::Point(10, 4);
+				break;
+			case 28:
+			case 29:
+			case 30:
+			case 31:
+				party._mazeId = 26;
+				party._mazePosition = Common::Point(12, 10);
+				break;
+			case 32:
+			case 33:
+			case 34:
+			case 35:
+				party._mazeId = 3;
+				party._mazePosition = Common::Point(4, 9);
+				break;
+			case 36:
+			case 37:
+			case 38:
+			case 39:
+				party._mazeId = 16;
+				party._mazePosition = Common::Point(2, 7);
+				break;
+			case 40:
+			case 41:
+			case 42:
+			case 43:
+				party._mazeId = 23;
+				party._mazePosition = Common::Point(10, 9);
+				break;
+			case 44:
+			case 45:
+			case 46:
+			case 47:
+				party._mazeId = 13;
+				party._mazePosition = Common::Point(2, 10);
+				break;
+			case 103:
+			case 104:
+				map._loadDarkSide = false;
+				party._mazeId = 8;
+				party._mazePosition = Common::Point(11, 15);
+				party._mazeDirection = DIR_NORTH;
+				break;
+			case 105:
+				party._mazeId = 24;
+				party._mazePosition = Common::Point(11, 9);
+				break;
+			case 106:
+				party._mazeId = 12;
+				party._mazePosition = Common::Point(6, 15);
+				break;
+			case 107:
+				party._mazeId = 15;
+				party._mazePosition = Common::Point(4, 12);
+				break;
+			default:
+				party._mazeId = 29;
+				party._mazePosition = Common::Point(25, 21);
+				party._mazeDirection = DIR_NORTH;
+				break;
+			}
+		}
+	}
+
+	_flipGround ^= 1;
+	draw3d(true);
+	int tempVal = scripts._v2;
+	scripts._v2 = 0;
+	combat.giveCharDamage(party._fallDamage, 0, 0);
+	scripts._v2 = tempVal;
+
+	_flipGround ^= 1;
 }
 
+/**
+ * Check movement in the given direction
+ */
 bool Interface::checkMoveDirection(int key) {
 	Map &map = *_vm->_map;
 	Party &party = *_vm->_party;
 	SoundManager &sound = *_vm->_sound;
 	Direction dir = party._mazeDirection;
 
-	switch (_buttonValue) {
+	switch (key) {
 	case (Common::KBD_CTRL << 16) | Common::KEYCODE_LEFT:
 		party._mazeDirection = (party._mazeDirection == DIR_NORTH) ? DIR_WEST :
 			(Direction)(party._mazeDirection - 1);
@@ -948,10 +1164,10 @@ void Interface::draw3d(bool updateFlag) {
 	// Draw the minimap
 	drawMiniMap();
 
-	if (party._falling == 1)
+	if (_falling == 1)
 		handleFalling();
 
-	if (party._falling == 2) {
+	if (_falling == 2) {
 		screen.saveBackground(1);
 	}
 
@@ -991,6 +1207,9 @@ void Interface::draw3d(bool updateFlag) {
 		events.wait(2);
 }
 
+/**
+ * Handle doing the falling
+ */
 void Interface::handleFalling() {
 	Party &party = *_vm->_party;
 	Screen &screen = *_vm->_screen;
@@ -1043,17 +1262,23 @@ void Interface::handleFalling() {
 }
 
 void Interface::saveFall() {
-
+	// TODO
 }
 
 void Interface::fall(int v) {
 
 }
 
+/**
+ * Shake the screen
+ */
 void Interface::shake(int time) {
 
 }
 
+/**
+ * Draw the minimap
+ */
 void Interface::drawMiniMap() {
 	Map &map = *_vm->_map;
 	Party &party = *_vm->_party;
diff --git a/engines/xeen/interface.h b/engines/xeen/interface.h
index 4435310..e427845 100644
--- a/engines/xeen/interface.h
+++ b/engines/xeen/interface.h
@@ -98,6 +98,7 @@ private:
 public:
 	int _intrIndex1;
 	Common::String _interfaceText;
+	int _falling;
 public:
 	Interface(XeenEngine *vm);
 
@@ -111,7 +112,7 @@ public:
 
 	void mainIconsPrint();
 
-	void doFalling();
+	void startFalling(bool v);
 
 	void perform();
 
diff --git a/engines/xeen/map.cpp b/engines/xeen/map.cpp
index dc58c2d..1c7cbd8 100644
--- a/engines/xeen/map.cpp
+++ b/engines/xeen/map.cpp
@@ -886,11 +886,12 @@ Map::Map(XeenEngine *vm) : _vm(vm), _mobData(vm) {
 }
 
 void Map::load(int mapId) {
+	Interface &intf = *_vm->_interface;
 	Screen &screen = *_vm->_screen;
 	IndoorDrawList &indoorList = _vm->_interface->_indoorList;
 	OutdoorDrawList &outdoorList = _vm->_interface->_outdoorList;
 
-	if (_vm->_party->_falling) {
+	if (intf._falling) {
 		Window &w = screen._windows[9];
 		w.open();
 		w.writeString(OOPS);
diff --git a/engines/xeen/party.cpp b/engines/xeen/party.cpp
index cd1dc21..2eb4cc2 100644
--- a/engines/xeen/party.cpp
+++ b/engines/xeen/party.cpp
@@ -111,7 +111,6 @@ Party::Party(XeenEngine *vm) {
 	_isNight = false;
 	_stepped = false;
 	_damageType = DT_PHYSICAL;
-	_falling = false;
 	_fallMaze = 0;
 	_fallDamage = 0;
 	_dead = false;
diff --git a/engines/xeen/party.h b/engines/xeen/party.h
index 58bfbd2..4f32cca 100644
--- a/engines/xeen/party.h
+++ b/engines/xeen/party.h
@@ -121,7 +121,6 @@ public:
 	bool _newDay;
 	bool _isNight;
 	bool _stepped;
-	int _falling;
 	Common::Point _fallPosition;
 	int _fallMaze;
 	int _fallDamage;
diff --git a/engines/xeen/scripts.cpp b/engines/xeen/scripts.cpp
index 6ab4c1f..086c0d4 100644
--- a/engines/xeen/scripts.cpp
+++ b/engines/xeen/scripts.cpp
@@ -804,10 +804,12 @@ void Scripts::cmdExchObj(Common::Array<byte> &params) {
 }
 
 void Scripts::cmdFallToMap(Common::Array<byte> &params) {
+	Interface &intf = *_vm->_interface;
 	Party &party = *_vm->_party;
 	party._fallMaze = params[0];
 	party._fallPosition = Common::Point(params[1], params[2]);
 	party._fallDamage = params[3];
+	intf.startFalling(true);
 
 	_lineNum = -1;
 }
diff --git a/engines/xeen/scripts.h b/engines/xeen/scripts.h
index d353581..cc32a96 100644
--- a/engines/xeen/scripts.h
+++ b/engines/xeen/scripts.h
@@ -148,7 +148,6 @@ private:
 	int _mirrorId;
 	int _refreshIcons;
 	int _scriptResult;
-	int _v2;
 	bool _scriptExecuted;
 	bool _var50;
 	MazeEvent *_event;
@@ -229,6 +228,7 @@ public:
 	int _whoWill;
 	int _nEdamageType;
 	int _itemType;
+	int _v2;
 	Common::Array<MirrorEntry> _mirror;
 public:
 	Scripts(XeenEngine *vm);


Commit: adde24a338eafc5aab0c3e51c439aea64bfdbfb7
    https://github.com/scummvm/scummvm/commit/adde24a338eafc5aab0c3e51c439aea64bfdbfb7
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-02-15T14:20:35-05:00

Commit Message:
XEEN: Move more code from InterfaceMap that should be in Interface class

Changed paths:
    engines/xeen/interface.cpp
    engines/xeen/interface.h
    engines/xeen/interface_map.cpp
    engines/xeen/interface_map.h



diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp
index 8a35563..0d488d1 100644
--- a/engines/xeen/interface.cpp
+++ b/engines/xeen/interface.cpp
@@ -153,7 +153,11 @@ void Interface::initDrawStructs() {
 }
 
 void Interface::setup() {
-	InterfaceMap::setup();
+	_borderSprites.load("border.icn");
+	_spellFxSprites.load("spellfx.icn");
+	_fecpSprites.load("fecp.brd");
+	_blessSprites.load("bless.icn");
+	_charPowSprites.load("charpow.icn");
 	_uiSprites.load("inn.icn");
 
 	Party &party = *_vm->_party;
@@ -1656,4 +1660,117 @@ void Interface::drawMiniMap() {
 	party._wizardEyeActive = eyeActive;
 }
 
+/**
+ * Draw the display borders
+ */
+void Interface::assembleBorder() {
+	Resources &res = *_vm->_resources;
+	Screen &screen = *_vm->_screen;
+
+	// Draw the outer frame
+	res._globalSprites.draw(screen._windows[0], 0, Common::Point(8, 8));
+
+	// Draw the animating bat character used to show when levitate is active
+	_borderSprites.draw(screen._windows[0], _vm->_party->_levitateActive ? _batUIFrame + 16 : 16,
+		Common::Point(0, 82));
+	_batUIFrame = (_batUIFrame + 1) % 12;
+
+	// Draw UI element to indicate whether can spot hidden doors
+	_borderSprites.draw(screen,
+		(_thinWall && _vm->_party->checkSkill(SPOT_DOORS)) ? _spotDoorsUIFrame + 28 : 28,
+		Common::Point(194, 91));
+	_spotDoorsUIFrame = (_spotDoorsUIFrame + 1) % 12;
+
+	// Draw UI element to indicate whether can sense danger
+	_borderSprites.draw(screen,
+		(_vm->_dangerSenseAllowed && _vm->_party->checkSkill(DANGER_SENSE)) ? _spotDoorsUIFrame + 40 : 40,
+		Common::Point(107, 9));
+	_dangerSenseUIFrame = (_dangerSenseUIFrame + 1) % 12;
+
+	// Handle the face UI elements for indicating clairvoyance status
+	_face1UIFrame = (_face1UIFrame + 1) % 4;
+	if (_face1State == 0)
+		_face1UIFrame += 4;
+	else if (_face1State == 2)
+		_face1UIFrame = 0;
+
+	_face2UIFrame = (_face2UIFrame + 1) % 4 + 12;
+	if (_face2State == 0)
+		_face2UIFrame += 252;
+	else if (_face2State == 2)
+		_face2UIFrame = 0;
+
+	if (!_vm->_party->_clairvoyanceActive) {
+		_face1UIFrame = 0;
+		_face2UIFrame = 8;
+	}
+
+	_borderSprites.draw(screen, _face1UIFrame, Common::Point(0, 32));
+	_borderSprites.draw(screen,
+		screen._windows[10]._enabled || screen._windows[2]._enabled ?
+		52 : _face2UIFrame,
+		Common::Point(215, 32));
+
+	// Draw resistence indicators
+	if (!screen._windows[10]._enabled && !screen._windows[2]._enabled
+		&& screen._windows[38]._enabled) {
+		_fecpSprites.draw(screen, _vm->_party->_fireResistence ? 1 : 0,
+			Common::Point(2, 2));
+		_fecpSprites.draw(screen, _vm->_party->_electricityResistence ? 3 : 2,
+			Common::Point(219, 2));
+		_fecpSprites.draw(screen, _vm->_party->_coldResistence ? 5 : 4,
+			Common::Point(2, 134));
+		_fecpSprites.draw(screen, _vm->_party->_poisonResistence ? 7 : 6,
+			Common::Point(219, 134));
+	} else {
+		_fecpSprites.draw(screen, _vm->_party->_fireResistence ? 9 : 8,
+			Common::Point(8, 8));
+		_fecpSprites.draw(screen, _vm->_party->_electricityResistence ? 10 : 11,
+			Common::Point(219, 8));
+		_fecpSprites.draw(screen, _vm->_party->_coldResistence ? 12 : 13,
+			Common::Point(8, 134));
+		_fecpSprites.draw(screen, _vm->_party->_poisonResistence ? 14 : 15,
+			Common::Point(219, 134));
+	}
+
+	// Draw UI element for blessed
+	_blessSprites.draw(screen, 16, Common::Point(33, 137));
+	if (_vm->_party->_blessed) {
+		_blessedUIFrame = (_blessedUIFrame + 1) % 4;
+		_blessSprites.draw(screen, _blessedUIFrame, Common::Point(33, 137));
+	}
+
+	// Draw UI element for power shield
+	if (_vm->_party->_powerShield) {
+		_powerShieldUIFrame = (_powerShieldUIFrame + 1) % 4;
+		_blessSprites.draw(screen, _powerShieldUIFrame + 4,
+			Common::Point(55, 137));
+	}
+
+	// Draw UI element for holy bonus
+	if (_vm->_party->_holyBonus) {
+		_holyBonusUIFrame = (_holyBonusUIFrame + 1) % 4;
+		_blessSprites.draw(screen, _holyBonusUIFrame + 8, Common::Point(160, 137));
+	}
+
+	// Draw UI element for heroism
+	if (_vm->_party->_heroism) {
+		_heroismUIFrame = (_heroismUIFrame + 1) % 4;
+		_blessSprites.draw(screen, _heroismUIFrame + 12, Common::Point(182, 137));
+	}
+
+	// Draw direction character if direction sense is active
+	if (_vm->_party->checkSkill(DIRECTION_SENSE) && !_vm->_noDirectionSense) {
+		const char *dirText = DIRECTION_TEXT_UPPER[_vm->_party->_mazeDirection];
+		Common::String msg = Common::String::format(
+			"\002""08\003""c\013""139\011""116%c\014""d\001", *dirText);
+		screen._windows[0].writeString(msg);
+	}
+
+	// Draw view frame
+	if (screen._windows[12]._enabled)
+		screen._windows[12].frame();
+}
+
+
 } // End of namespace Xeen
diff --git a/engines/xeen/interface.h b/engines/xeen/interface.h
index e427845..8d3044f 100644
--- a/engines/xeen/interface.h
+++ b/engines/xeen/interface.h
@@ -64,6 +64,10 @@ private:
 	XeenEngine *_vm;
 	SpriteResource _uiSprites;
 	SpriteResource _iconSprites;
+	SpriteResource _borderSprites;
+	SpriteResource _spellFxSprites;
+	SpriteResource _fecpSprites;
+	SpriteResource _blessSprites;
 	DrawStruct _mainList[16];
 	int _combatCharIds[8];
 
@@ -104,7 +108,7 @@ public:
 
 	virtual ~Interface() {}
 
-	virtual void setup();
+	void setup();
 
 	void manageCharacters(bool soundPlayed);
 
@@ -121,6 +125,8 @@ public:
 	void bash(const Common::Point &pt, Direction direction);
 
 	void draw3d(bool updateFlag);
+
+	void assembleBorder();
 };
 
 } // End of namespace Xeen
diff --git a/engines/xeen/interface_map.cpp b/engines/xeen/interface_map.cpp
index 4f408d1..837971b 100644
--- a/engines/xeen/interface_map.cpp
+++ b/engines/xeen/interface_map.cpp
@@ -398,14 +398,6 @@ InterfaceMap::InterfaceMap(XeenEngine *vm): _vm(vm) {
 	_face1State = _face2State = 0;
 }
 
-void InterfaceMap::setup() {
-	_borderSprites.load("border.icn");
-	_spellFxSprites.load("spellfx.icn");
-	_fecpSprites.load("fecp.brd");
-	_blessSprites.load("bless.icn");
-	_charPowSprites.load("charpow.icn");
-}
-
 void InterfaceMap::drawMap() {
 	Combat &combat = *_vm->_combat;
 	Map &map = *_vm->_map;
@@ -4447,113 +4439,4 @@ void InterfaceMap::moveMonsters() {
 	// TODO
 }
 
-void InterfaceMap::assembleBorder() {
-	Resources &res = *_vm->_resources;
-	Screen &screen = *_vm->_screen;
-
-	// Draw the outer frame
-	res._globalSprites.draw(screen._windows[0], 0, Common::Point(8, 8));
-
-	// Draw the animating bat character used to show when levitate is active
-	_borderSprites.draw(screen._windows[0], _vm->_party->_levitateActive ? _batUIFrame + 16 : 16,
-		Common::Point(0, 82));
-	_batUIFrame = (_batUIFrame + 1) % 12;
-
-	// Draw UI element to indicate whether can spot hidden doors
-	_borderSprites.draw(screen,
-		(_thinWall && _vm->_party->checkSkill(SPOT_DOORS)) ? _spotDoorsUIFrame + 28 : 28,
-		Common::Point(194, 91));
-	_spotDoorsUIFrame = (_spotDoorsUIFrame + 1) % 12;
-
-	// Draw UI element to indicate whether can sense danger
-	_borderSprites.draw(screen,
-		(_vm->_dangerSenseAllowed && _vm->_party->checkSkill(DANGER_SENSE)) ? _spotDoorsUIFrame + 40 : 40,
-		Common::Point(107, 9));
-	_dangerSenseUIFrame = (_dangerSenseUIFrame + 1) % 12;
-
-	// Handle the face UI elements for indicating clairvoyance status
-	_face1UIFrame = (_face1UIFrame + 1) % 4;
-	if (_face1State == 0)
-		_face1UIFrame += 4;
-	else if (_face1State == 2)
-		_face1UIFrame = 0;
-
-	_face2UIFrame = (_face2UIFrame + 1) % 4 + 12;
-	if (_face2State == 0)
-		_face2UIFrame += 252;
-	else if (_face2State == 2)
-		_face2UIFrame = 0;
-
-	if (!_vm->_party->_clairvoyanceActive) {
-		_face1UIFrame = 0;
-		_face2UIFrame = 8;
-	}
-
-	_borderSprites.draw(screen, _face1UIFrame, Common::Point(0, 32));
-	_borderSprites.draw(screen,
-		screen._windows[10]._enabled || screen._windows[2]._enabled ?
-		52 : _face2UIFrame,
-		Common::Point(215, 32));
-
-	// Draw resistence indicators
-	if (!screen._windows[10]._enabled && !screen._windows[2]._enabled
-		&& screen._windows[38]._enabled) {
-		_fecpSprites.draw(screen, _vm->_party->_fireResistence ? 1 : 0,
-			Common::Point(2, 2));
-		_fecpSprites.draw(screen, _vm->_party->_electricityResistence ? 3 : 2,
-			Common::Point(219, 2));
-		_fecpSprites.draw(screen, _vm->_party->_coldResistence ? 5 : 4,
-			Common::Point(2, 134));
-		_fecpSprites.draw(screen, _vm->_party->_poisonResistence ? 7 : 6,
-			Common::Point(219, 134));
-	} else {
-		_fecpSprites.draw(screen, _vm->_party->_fireResistence ? 9 : 8,
-			Common::Point(8, 8));
-		_fecpSprites.draw(screen, _vm->_party->_electricityResistence ? 10 : 11,
-			Common::Point(219, 8));
-		_fecpSprites.draw(screen, _vm->_party->_coldResistence ? 12 : 13,
-			Common::Point(8, 134));
-		_fecpSprites.draw(screen, _vm->_party->_poisonResistence ? 14 : 15,
-			Common::Point(219, 134));
-	}
-
-	// Draw UI element for blessed
-	_blessSprites.draw(screen, 16, Common::Point(33, 137));
-	if (_vm->_party->_blessed) {
-		_blessedUIFrame = (_blessedUIFrame + 1) % 4;
-		_blessSprites.draw(screen, _blessedUIFrame, Common::Point(33, 137));
-	}
-
-	// Draw UI element for power shield
-	if (_vm->_party->_powerShield) {
-		_powerShieldUIFrame = (_powerShieldUIFrame + 1) % 4;
-		_blessSprites.draw(screen, _powerShieldUIFrame + 4,
-			Common::Point(55, 137));
-	}
-
-	// Draw UI element for holy bonus
-	if (_vm->_party->_holyBonus) {
-		_holyBonusUIFrame = (_holyBonusUIFrame + 1) % 4;
-		_blessSprites.draw(screen, _holyBonusUIFrame + 8, Common::Point(160, 137));
-	}
-
-	// Draw UI element for heroism
-	if (_vm->_party->_heroism) {
-		_heroismUIFrame = (_heroismUIFrame + 1) % 4;
-		_blessSprites.draw(screen, _heroismUIFrame + 12, Common::Point(182, 137));
-	}
-
-	// Draw direction character if direction sense is active
-	if (_vm->_party->checkSkill(DIRECTION_SENSE) && !_vm->_noDirectionSense) {
-		const char *dirText = DIRECTION_TEXT_UPPER[_vm->_party->_mazeDirection];
-		Common::String msg = Common::String::format(
-			"\002""08\003""c\013""139\011""116%c\014""d\001", *dirText);
-		screen._windows[0].writeString(msg);
-	}
-
-	// Draw view frame
-	if (screen._windows[12]._enabled)
-		screen._windows[12].frame();
-}
-
 } // End of namespace Xeen
diff --git a/engines/xeen/interface_map.h b/engines/xeen/interface_map.h
index a062624..9ac9222 100644
--- a/engines/xeen/interface_map.h
+++ b/engines/xeen/interface_map.h
@@ -92,10 +92,6 @@ public:
 class InterfaceMap {
 private:
 	XeenEngine *_vm;
-	SpriteResource _borderSprites;
-	SpriteResource _spellFxSprites;
-	SpriteResource _fecpSprites;
-	SpriteResource _blessSprites;
 	int _combatFloatCounter;
 
 	void initDrawStructs();
@@ -123,8 +119,6 @@ protected:
 
 	void animate3d();
 
-	virtual void setup();
-
 	void drawMap();
 public:
 	OutdoorDrawList _outdoorList;
@@ -160,8 +154,6 @@ public:
 
 	void drawOutdoors();
 
-	void assembleBorder();
-
 	void moveMonsters();
 
 };


Commit: 93e5fd7c20a69a052625293133d7d93728444c3b
    https://github.com/scummvm/scummvm/commit/93e5fd7c20a69a052625293133d7d93728444c3b
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-02-15T14:43:04-05:00

Commit Message:
XEEN: Moved more variables out of InterfaceMap that belong in Interface

Changed paths:
    engines/xeen/interface.cpp
    engines/xeen/interface.h
    engines/xeen/interface_map.cpp
    engines/xeen/interface_map.h



diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp
index 0d488d1..cebd14d 100644
--- a/engines/xeen/interface.cpp
+++ b/engines/xeen/interface.cpp
@@ -127,12 +127,25 @@ Interface::Interface(XeenEngine *vm) : ButtonContainer(), InterfaceMap(vm),
 	_buttonsLoaded = false;
 	_intrIndex1 = 0;
 	_steppingFX = 0;
+	_falling = false;
+	_blessedUIFrame = 0;
+	_powerShieldUIFrame = 0;
+	_holyBonusUIFrame = 0;
+	_heroismUIFrame = 0;
+	_flipUIFrame = 0;
+	_face1UIFrame = 0;
+	_face2UIFrame = 0;
+	_batUIFrame = 0;
+	_spotDoorsUIFrame = 0;
+	_dangerSenseUIFrame = 0;
+	_face1State = _face2State = 0;
+	_upDoorText = false;
+	_tillMove = 0;
 
 	Common::fill(&_combatCharIds[0], &_combatCharIds[8], 0);
 	initDrawStructs();
 }
 
-
 void Interface::initDrawStructs() {
 	_mainList[0] = DrawStruct(7, 232, 74);
 	_mainList[1] = DrawStruct(0, 235, 75);
@@ -1162,6 +1175,15 @@ void Interface::draw3d(bool updateFlag) {
 	if (screen._windows[11]._enabled)
 		return;
 
+	_flipUIFrame = (_flipUIFrame + 1) % 4;
+	if (_flipUIFrame == 0)
+		_flipWater = !_flipWater;
+	if (_tillMove && (_vm->_mode == MODE_1 || _vm->_mode == MODE_COMBAT) &&
+		!_flag1 && _vm->_moveMonsters) {
+		if (--_tillMove == 0)
+			moveMonsters();
+	}
+
 	// Draw the map
 	drawMap();
 
@@ -1200,7 +1222,6 @@ void Interface::draw3d(bool updateFlag) {
 	party._stepped = false;
 	if (_vm->_mode == MODE_9) {
 		// TODO: Save current scripts data?
-		error("TODO: save scripts?");
 	}
 
 	// TODO: Check use of updateFlag here. Original doesn't have it, but I
@@ -1772,5 +1793,8 @@ void Interface::assembleBorder() {
 		screen._windows[12].frame();
 }
 
+void Interface::moveMonsters() {
+	// TODO
+}
 
 } // End of namespace Xeen
diff --git a/engines/xeen/interface.h b/engines/xeen/interface.h
index 8d3044f..fa5f1aa 100644
--- a/engines/xeen/interface.h
+++ b/engines/xeen/interface.h
@@ -73,6 +73,11 @@ private:
 
 	bool _buttonsLoaded;
 	int _steppingFX;
+	int _blessedUIFrame;
+	int _powerShieldUIFrame;
+	int _holyBonusUIFrame;
+	int _heroismUIFrame;
+	int _flipUIFrame;
 
 	void initDrawStructs();
 
@@ -103,6 +108,14 @@ public:
 	int _intrIndex1;
 	Common::String _interfaceText;
 	int _falling;
+	int _face1State, _face2State;
+	int _face1UIFrame, _face2UIFrame;
+	int _spotDoorsUIFrame;
+	int _dangerSenseUIFrame;
+	int _batUIFrame;
+	bool _upDoorText;
+	Common::String _screenText;
+	byte _tillMove;
 public:
 	Interface(XeenEngine *vm);
 
@@ -127,6 +140,8 @@ public:
 	void draw3d(bool updateFlag);
 
 	void assembleBorder();
+
+	void moveMonsters();
 };
 
 } // End of namespace Xeen
diff --git a/engines/xeen/interface_map.cpp b/engines/xeen/interface_map.cpp
index 837971b..6f4f708 100644
--- a/engines/xeen/interface_map.cpp
+++ b/engines/xeen/interface_map.cpp
@@ -381,21 +381,8 @@ InterfaceMap::InterfaceMap(XeenEngine *vm): _vm(vm) {
 	_combatFloatCounter = 0;
 	_thinWall = false;
 	_isAnimReset = false;
-	_upDoorText = false;
-	_batUIFrame = 0;
-	_spotDoorsUIFrame = 0;
-	_dangerSenseUIFrame = 0;
-	_face1UIFrame = 0;
-	_face2UIFrame = 0;
-	_blessedUIFrame = 0;
-	_powerShieldUIFrame = 0;
-	_holyBonusUIFrame = 0;
-	_heroismUIFrame = 0;
-	_flipUIFrame = 0;
-	_tillMove = 0;
 	_flag1 = false;
 	_overallFrame = 0;
-	_face1State = _face2State = 0;
 }
 
 void InterfaceMap::drawMap() {
@@ -408,15 +395,6 @@ void InterfaceMap::drawMap() {
 	const int OUTDOOR_INDEXES[3] = { 119, 113, 116 };
 	const int COMBAT_OFFSET_X[4] = { 8, 6, 4, 2 };
 
-	_flipUIFrame = (_flipUIFrame + 1) % 4;
-	if (_flipUIFrame == 0)
-		_flipWater = !_flipWater;
-	if (_tillMove && (_vm->_mode == MODE_1 || _vm->_mode == MODE_COMBAT) &&
-		!_flag1 && _vm->_moveMonsters) {
-		if (--_tillMove == 0)
-			moveMonsters();
-	}
-
 	MazeObject &objObject = map._mobData._objects[_objNumber];
 	Direction partyDirection = _vm->_party->_mazeDirection;
 	int objNum = _objNumber - 1;
@@ -4434,9 +4412,4 @@ void InterfaceMap::drawOutdoors() {
 	_charsShooting = _isShooting;
 }
 
-
-void InterfaceMap::moveMonsters() {
-	// TODO
-}
-
 } // End of namespace Xeen
diff --git a/engines/xeen/interface_map.h b/engines/xeen/interface_map.h
index 9ac9222..761e997 100644
--- a/engines/xeen/interface_map.h
+++ b/engines/xeen/interface_map.h
@@ -88,7 +88,6 @@ public:
 	int size() const { return 170; }
 };
 
-
 class InterfaceMap {
 private:
 	XeenEngine *_vm;
@@ -108,11 +107,6 @@ protected:
 	bool _isShooting;
 	bool _thinWall;
 	bool _isAnimReset;
-	int _blessedUIFrame;
-	int _powerShieldUIFrame;
-	int _holyBonusUIFrame;
-	int _heroismUIFrame;
-	int _flipUIFrame;
 	bool _flag1;
 
 	void setMazeBits();
@@ -124,16 +118,8 @@ public:
 	OutdoorDrawList _outdoorList;
 	IndoorDrawList _indoorList;
 	SpriteResource _charPowSprites;
-	bool _upDoorText;
-	Common::String _screenText;
-	int _face1State, _face2State;
-	int _face1UIFrame, _face2UIFrame;
-	int _spotDoorsUIFrame;
-	int _dangerSenseUIFrame;
-	byte _tillMove;
 	int _objNumber;
 	int _overallFrame;
-	int _batUIFrame;
 	bool _charsShooting;
 public:
 	InterfaceMap(XeenEngine *vm);
@@ -153,9 +139,6 @@ public:
 	void setOutdoorsObjects();
 
 	void drawOutdoors();
-
-	void moveMonsters();
-
 };
 
 } // End of namespace Xeen


Commit: bdc8e73c1bbd3fc8c29b48028d02d1d4950f08a3
    https://github.com/scummvm/scummvm/commit/bdc8e73c1bbd3fc8c29b48028d02d1d4950f08a3
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-02-15T14:55:59-05:00

Commit Message:
XEEN: Fix walking through walls

Changed paths:
    engines/xeen/interface.cpp



diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp
index cebd14d..cac9f3a 100644
--- a/engines/xeen/interface.cpp
+++ b/engines/xeen/interface.cpp
@@ -923,6 +923,8 @@ bool Interface::checkMoveDirection(int key) {
 		int surfaceId = map.getCell(2);
 		if (surfaceId >= map.mazeData()._difficulties._wallNoPass) {
 			party._mazeDirection = dir;
+			sound.playFX(46);
+			return false;
 		} else {
 			party._mazeDirection = dir;
 


Commit: ef2a4595c2c17260f61ad93d6c4374af7fa8a606
    https://github.com/scummvm/scummvm/commit/ef2a4595c2c17260f61ad93d6c4374af7fa8a606
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-02-15T15:01:22-05:00

Commit Message:
XEEN: Moved _openDoor into InterfaceMap

Changed paths:
    engines/xeen/interface.cpp
    engines/xeen/interface_map.cpp
    engines/xeen/interface_map.h
    engines/xeen/xeen.cpp
    engines/xeen/xeen.h



diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp
index cac9f3a..11fc312 100644
--- a/engines/xeen/interface.cpp
+++ b/engines/xeen/interface.cpp
@@ -934,10 +934,10 @@ bool Interface::checkMoveDirection(int key) {
 				return false;
 			} else {
 				if (_buttonValue == Common::KEYCODE_UP && _wo[107]) {
-					_vm->_openDoor = true;
+					_openDoor = true;
 					sound.playFX(47);
 					draw3d(true);
-					_vm->_openDoor = false;
+					_openDoor = false;
 				}
 				return true;
 			}
diff --git a/engines/xeen/interface_map.cpp b/engines/xeen/interface_map.cpp
index 6f4f708..a3241a1 100644
--- a/engines/xeen/interface_map.cpp
+++ b/engines/xeen/interface_map.cpp
@@ -383,6 +383,7 @@ InterfaceMap::InterfaceMap(XeenEngine *vm): _vm(vm) {
 	_isAnimReset = false;
 	_flag1 = false;
 	_overallFrame = 0;
+	_openDoor = false;
 }
 
 void InterfaceMap::drawMap() {
@@ -4243,7 +4244,7 @@ void InterfaceMap::drawIndoors() {
 
 	if (_wo[107]) {
 		_indoorList._fwl_1F1R._sprites = &map._wallSprites._fwl2;
-		if (!_vm->_openDoor)
+		if (!_openDoor)
 			_indoorList._fwl_1F1R._frame = 0;
 		else
 			_indoorList._fwl_1F1R._frame = map.mazeData()._wallKind ? 1 : 10;
@@ -4303,7 +4304,7 @@ void InterfaceMap::drawIndoors() {
 	_indoorList[0]._sprites = &map._skySprites[map._currentSky];
 	_indoorList[0]._flags = _flipSky ? SPRFLAG_HORIZ_FLIPPED : 0;
 
-	if (_vm->_openDoor) {
+	if (_openDoor) {
 		Common::Point pt(
 			_vm->_party->_mazePosition.x + SCREEN_POSITIONING_X[
 				_vm->_party->_mazeDirection][_vm->_party->_mazePosition.x],
diff --git a/engines/xeen/interface_map.h b/engines/xeen/interface_map.h
index 761e997..1ff9829 100644
--- a/engines/xeen/interface_map.h
+++ b/engines/xeen/interface_map.h
@@ -121,6 +121,7 @@ public:
 	int _objNumber;
 	int _overallFrame;
 	bool _charsShooting;
+	bool _openDoor;
 public:
 	InterfaceMap(XeenEngine *vm);
 
diff --git a/engines/xeen/xeen.cpp b/engines/xeen/xeen.cpp
index e0a2beb..a3240bf 100644
--- a/engines/xeen/xeen.cpp
+++ b/engines/xeen/xeen.cpp
@@ -56,7 +56,6 @@ XeenEngine::XeenEngine(OSystem *syst, const XeenGameDescription *gameDesc)
 	_noDirectionSense = false;
 	_moveMonsters = false;
 	_mode = MODE_0;
-	_openDoor = 0;
 	_startupWindowActive = false;
 }
 
diff --git a/engines/xeen/xeen.h b/engines/xeen/xeen.h
index 2d85335..d0a72f5 100644
--- a/engines/xeen/xeen.h
+++ b/engines/xeen/xeen.h
@@ -157,7 +157,6 @@ public:
 	bool _dangerSenseAllowed;
 	bool _noDirectionSense;
 	bool _moveMonsters;
-	int _openDoor;
 	bool _startupWindowActive;
 public:
 	XeenEngine(OSystem *syst, const XeenGameDescription *gameDesc);


Commit: 75a070de1755fca9244eec1796ea892118afa84b
    https://github.com/scummvm/scummvm/commit/75a070de1755fca9244eec1796ea892118afa84b
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-02-15T20:47:56-05:00

Commit Message:
XEEN: Implementing combat methods

Changed paths:
    engines/xeen/combat.cpp
    engines/xeen/combat.h
    engines/xeen/dialogs_items.cpp
    engines/xeen/interface.cpp
    engines/xeen/interface.h
    engines/xeen/interface_map.cpp
    engines/xeen/interface_map.h



diff --git a/engines/xeen/combat.cpp b/engines/xeen/combat.cpp
index 582444d..3797c18 100644
--- a/engines/xeen/combat.cpp
+++ b/engines/xeen/combat.cpp
@@ -20,12 +20,64 @@
  *
  */
 
-#include "xeen/combat.h"
 #include "common/algorithm.h"
-#include "common/textconsole.h"
+#include "common/rect.h"
+#include "xeen/combat.h"
+#include "xeen/interface.h"
+#include "xeen/xeen.h"
 
 namespace Xeen {
 
+static const int MONSTER_GRID_X[48] = {
+	1, 1, 1, 0, -1, -1, -1, 1, 1, 1, 0, -1,
+	-1, -1, 1, 1, 1, 0, -1, -1, -1, 1, 1, 1,
+	0, -1, -1, -1, 1, 1, 1, 0, -1, -1, -1, 1,
+	1, 1, 0, -1, -1, -1, 1, 1, 1, 0, -1, -1
+};
+
+static const int MONSTER_GRID_Y[48] = {
+	0, 0, 0, -1, 0, 0, 0, 0, 0, 0, -1, 0,
+	0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0,
+	0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0
+};
+
+static const int MONSTER_GRID3[48] = {
+	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+	- 1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1,
+	0, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, 1,
+	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+};
+
+static const int MONSTER_GRID_BITINDEX1[48] = {
+	1, 1, 1, 2, 3, 3, 3, 1, 1, 1, 2, 3,
+	3, 3, 1, 1, 1, 2, 3, 3, 3, 1, 1, 1,
+	0, 3, 3, 3, 1, 1, 1, 0, 3, 3, 3, 1,
+	1, 1, 0, 3, 3, 3, 1, 1, 1, 0, 3, 3
+};
+
+static const int MONSTER_GRID_BITINDEX2[48] = {
+	2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+	2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1,
+	0, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+static const int MONSTER_GRID_BITMASK[12] = {
+	0xC, 8, 4, 0, 0xF, 0xF000, 0xF00, 0xF0, 0xF00, 0xF0, 0x0F, 0xF000
+};
+
+static const int ATTACK_TYPE_FX[23] = {
+	49, 18, 13, 14, 15, 17, 16, 0, 6, 1, 2, 3,
+	4, 5, 4, 9, 27, 29, 44, 51, 53, 61, 71
+};
+
+static const int MONSTER_SHOOT_POW[7] = { 12, 14, 0, 4, 8, 10, 13 };
+
+static const int COMBAT_SHOOTING[4] = { 1, 1, 2, 3 };
+
+/*------------------------------------------------------------------------*/
+
 Combat::Combat(XeenEngine *vm): _vm(vm) {
 	Common::fill(&_attackMonsters[0], &_attackMonsters[26], 0);
 	Common::fill(&_charsArray1[0], &_charsArray1[12], 0);
@@ -34,9 +86,14 @@ Combat::Combat(XeenEngine *vm): _vm(vm) {
 	Common::fill(&_elemPow[0], &_elemPow[12], 0);
 	Common::fill(&_elemScale[0], &_elemScale[12], 0);
 	Common::fill(&_shooting[0], &_shooting[8], 0);
+	Common::fill(&_monsterMap[0][0], &_monsterMap[32][32], 0);
+	Common::fill(&_monsterMoved[0], &_monsterMoved[MAX_NUM_MONSTERS], false);
+	Common::fill(&_rangeAttacking[0], &_rangeAttacking[MAX_NUM_MONSTERS], false);
+	Common::fill(&_gmonHit[0], &_gmonHit[36], 0);
 	_globalCombat = 0;
 	_whosTurn = -1;
 	_itemFlag = false;
+	_monstersAttacking = false;
 }
 
 void Combat::clear() {
@@ -51,5 +108,345 @@ void Combat::giveCharDamage(int damage, int v2, int v3) {
 	error("TODO: giveCharDamage");
 }
 
+void Combat::moveMonsters() {
+	Interface &intf = *_vm->_interface;
+	Map &map = *_vm->_map;
+	Party &party = *_vm->_party;
+
+	if (!_vm->_moveMonsters)
+		return;
+
+	intf._tillMove = 0;
+	if (intf._charsShooting)
+		return;
+
+	Common::fill(&_monsterMap[0][0], &_monsterMap[32][32], 0);
+	Common::fill(&_monsterMoved[0], &_monsterMoved[MAX_NUM_MONSTERS], false);
+	Common::fill(&_rangeAttacking[0], &_rangeAttacking[MAX_NUM_MONSTERS], false);
+	Common::fill(&_gmonHit[0], &_gmonHit[36], -1);
+	_vm->_dangerSenseAllowed = false;
+
+	for (uint idx = 0; idx < map._mobData._monsters.size(); ++idx) {
+		MazeMonster &monster = map._mobData._monsters[idx];
+		if (monster._position.y < 32) {
+			_monsterMap[monster._position.y][monster._position.x]++;
+		}
+	}
+
+	for (int loopNum = 0; loopNum < 2; ++loopNum) {
+		int arrIndex = -1;
+		for (int yDiff = 3; yDiff >= -3; --yDiff) {
+			for (int xDiff = 3; xDiff >= -3; --xDiff) {
+				Common::Point pt = party._mazePosition + Common::Point(xDiff, yDiff);
+				++arrIndex;
+
+				for (int idx = 0; idx < (int)map._mobData._monsters.size(); ++idx) {
+					MazeMonster &monster = map._mobData._monsters[idx];
+					MonsterStruct &monsterData = map._monsterData[monster._spriteId];
+
+					if (pt == monster._position) {
+						_vm->_dangerSenseAllowed = true;
+						if ((monster._isAttacking || _vm->_mode == MODE_SLEEPING)
+								&& !_monsterMoved[idx]) {
+							if (party._mazePosition.x == pt.x || party._mazePosition.y == pt.y) {
+								// Check for range attacks
+								if (monsterData._rangeAttack && !_rangeAttacking[idx]
+									&& _attackMonsters[0] != idx && _attackMonsters[1] != idx
+									&& _attackMonsters[2] != idx && !monster._field7) {
+									// Setup monster for attacking
+									setupMonsterAttack(monster._spriteId, pt);
+									_rangeAttacking[idx] = true;
+								}
+							}
+						}
+					}
+
+					switch (party._mazeDirection) {
+					case DIR_NORTH:
+					case DIR_SOUTH:
+						if (monsterCanMove(pt, MONSTER_GRID_BITMASK[MONSTER_GRID_BITINDEX1[arrIndex]],
+								MONSTER_GRID_X[arrIndex], MONSTER_GRID_Y[arrIndex], idx)) {
+							// Move the monster
+							moveMonster(idx, Common::Point(MONSTER_GRID_X[arrIndex], MONSTER_GRID_Y[arrIndex]));
+						} else {
+							if (monsterCanMove(pt, MONSTER_GRID_BITMASK[MONSTER_GRID_BITINDEX2[arrIndex]],
+								arrIndex >= 21 && arrIndex <= 27 ? MONSTER_GRID3[arrIndex] : 0,
+								arrIndex >= 21 && arrIndex <= 27 ? 0 : MONSTER_GRID3[arrIndex],
+								idx))
+							if (arrIndex >= 21 && arrIndex <= 27) {
+								moveMonster(idx, Common::Point(MONSTER_GRID3[arrIndex], 0));
+							} else {
+								moveMonster(idx, Common::Point(0, MONSTER_GRID3[arrIndex]));
+							}
+						}
+						break;
+
+					case DIR_EAST:
+					case DIR_WEST:
+						if (monsterCanMove(pt, MONSTER_GRID_BITMASK[MONSTER_GRID_BITINDEX2[arrIndex]],
+							arrIndex >= 21 && arrIndex <= 27 ? MONSTER_GRID3[arrIndex] : 0,
+							arrIndex >= 21 && arrIndex <= 27 ? 0 : MONSTER_GRID3[arrIndex],
+							idx)) {
+							if (arrIndex >= 21 && arrIndex <= 27) {
+								moveMonster(idx, Common::Point(MONSTER_GRID3[arrIndex], 0));
+							} else {
+								moveMonster(idx, Common::Point(0, MONSTER_GRID3[arrIndex]));
+							}
+						} else if (monsterCanMove(pt, MONSTER_GRID_BITMASK[MONSTER_GRID_BITINDEX1[arrIndex]],
+								MONSTER_GRID_X[arrIndex], MONSTER_GRID_Y[arrIndex], idx)) {
+							moveMonster(idx, Common::Point(MONSTER_GRID_X[arrIndex], MONSTER_GRID_Y[arrIndex]));
+						}
+					}
+				}
+			}
+		}
+	}
+
+	monsterOvercome();
+	if (_monstersAttacking)
+		monstersAttack();
+}
+
+void Combat::monstersAttack() {
+	EventsManager &events = *_vm->_events;
+	Interface &intf = *_vm->_interface;
+	Map &map = *_vm->_map;
+	Party &party = *_vm->_party;
+	SoundManager &sound = *_vm->_sound;
+	int powNum = -1;
+	MonsterStruct *monsterData = nullptr;
+	OutdoorDrawList &outdoorList = intf._outdoorList;
+	IndoorDrawList &indoorList = intf._indoorList;
+
+	for (int idx = 0; idx < 36; ++idx) {
+		if (_gmonHit[idx] != -1) {
+			monsterData = &map._monsterData[_gmonHit[idx]];
+			powNum = MONSTER_SHOOT_POW[monsterData->_attackType];
+			if (powNum != 12)
+				break;
+		}
+	}
+
+	_powSprites.load(Common::String::format("pow%d.icn", powNum));
+	sound.playFX(ATTACK_TYPE_FX[monsterData->_attackType]);
+
+	for (int charNum = 0; charNum < MAX_PARTY_COUNT; ++charNum) {
+		if (!_shooting[charNum])
+			continue;
+
+		if (map._isOutdoors) {
+			outdoorList._attackImgs1[charNum]._scale = 3;
+			outdoorList._attackImgs2[charNum]._scale = 7;
+			outdoorList._attackImgs3[charNum]._scale = 11;
+			outdoorList._attackImgs4[charNum]._scale = 15;
+			outdoorList._attackImgs1[charNum]._sprites = nullptr;
+			outdoorList._attackImgs2[charNum]._sprites = nullptr;
+			outdoorList._attackImgs3[charNum]._sprites = nullptr;
+			outdoorList._attackImgs4[charNum]._sprites = nullptr;
+
+			switch (_shooting[charNum]) {
+			case 1:
+				outdoorList._attackImgs1[charNum]._sprites = &_powSprites;
+				break;
+			case 2:
+				outdoorList._attackImgs2[charNum]._sprites = &_powSprites;
+				break;
+			default:
+				outdoorList._attackImgs3[charNum]._sprites = &_powSprites;
+				break;
+			}
+		} else {
+			indoorList._attackImgs1[charNum]._scale = 3;
+			indoorList._attackImgs2[charNum]._scale = 7;
+			indoorList._attackImgs3[charNum]._scale = 11;
+			indoorList._attackImgs4[charNum]._scale = 15;
+			indoorList._attackImgs1[charNum]._sprites = nullptr;
+			indoorList._attackImgs2[charNum]._sprites = nullptr;
+			indoorList._attackImgs3[charNum]._sprites = nullptr;
+			indoorList._attackImgs4[charNum]._sprites = nullptr;
+
+			switch (_shooting[charNum]) {
+			case 1:
+				indoorList._attackImgs1[charNum]._sprites = &_powSprites;
+				break;
+			case 2:
+				indoorList._attackImgs2[charNum]._sprites = &_powSprites;
+				break;
+			default:
+				indoorList._attackImgs3[charNum]._sprites = &_powSprites;
+				break;
+			}
+		}
+	}
+
+	// Wait whilst the attacking effect is done
+	do {
+		intf.draw3d(true);
+		events.pollEventsAndWait();
+	} while (!_vm->shouldQuit() && intf._isAttacking);
+	
+	endAttack();
+
+	if (_vm->_mode != MODE_COMBAT) {
+		// Combat wasn't previously active, but it is now. Set up
+		// the combat party from the currently active party
+		party._combatParty.clear();
+		for (uint idx = 0; idx < party._activeParty.size(); ++idx)
+			party._combatParty.push_back(&party._activeParty[idx]);
+	}
+
+	for (int idx = 0; idx < 36; ++idx) {
+		if (_gmonHit[idx] != -1)
+			attackMonster(_gmonHit[idx]);
+	}
+
+	_monstersAttacking = false;
+
+	if (_vm->_mode != MODE_SLEEPING) {
+		for (uint charNum = 0; charNum < party._activeParty.size(); ++charNum) {
+			Condition condition = party._activeParty[charNum].worstCondition();
+
+			if (condition != ASLEEP && (condition < PARALYZED || condition == NO_CONDITION)) {
+				_vm->_mode = MODE_1;
+				break;
+			}
+		}
+	}
+}
+
+void Combat::setupMonsterAttack(int monsterDataIndex, const Common::Point &pt) {
+	Party &party = *_vm->_party;
+
+	for (int idx = 0; idx < 36; ++idx) {
+		if (_gmonHit[idx] != -1) {
+			int result = stopAttack(pt - party._mazePosition);
+			if (result) {	
+				_monstersAttacking = true;
+				_gmonHit[idx] = monsterDataIndex;
+
+				if (result != 1) {
+					for (int charNum = 0; charNum < MAX_PARTY_COUNT; ++charNum) {
+						if (!_shooting[charNum]) {
+							_shooting[charNum] = COMBAT_SHOOTING[result - 1];
+						}
+					}
+				}
+			}
+		}
+	}
+}
+
+bool Combat::monsterCanMove(const Common::Point &pt, int wallShift,
+		int xDiff, int yDiff, int monsterId) {
+	Map &map = *_vm->_map;
+	MazeMonster &monster = map._mobData._monsters[monsterId];
+	MonsterStruct &monsterData = map._monsterData[monster._spriteId];
+
+	Common::Point tempPos = pt;
+	if (map._isOutdoors) {
+		tempPos += Common::Point(xDiff, yDiff);
+		wallShift = 4;
+	}
+	int v = map.mazeLookup(tempPos, wallShift);
+
+	if (!map._isOutdoors) {
+		return v <= map.mazeData()._difficulties._wallNoPass;
+	} else {
+		SurfaceType surfaceType;
+		switch (v) {
+		case 0:
+		case 2:
+		case 3:
+		case 4:
+		case 5:
+		case 6:
+		case 8:
+		case 11:
+		case 13:
+		case 14:
+			surfaceType = (SurfaceType)map.mazeData()._surfaceTypes[map._currentSurfaceId];
+			if (surfaceType == SURFTYPE_WATER || surfaceType == SURFTYPE_DWATER) {
+				return monsterData._flying || monster._spriteId == 59;
+			} else if (surfaceType == SURFTYPE_SPACE) {
+				return monsterData._flying;
+			} else {
+				return _vm->_files->_isDarkCc || monster._spriteId != 59;
+			}
+		default:
+			return v <= map.mazeData()._difficulties._wallNoPass;
+		}
+	}
+}
+
+void Combat::moveMonster(int monsterId, const Common::Point &pt) {
+	Map &map = *_vm->_map;
+	MazeMonster &monster = map._mobData._monsters[monsterId];
+
+	if (_monsterMap[pt.y][pt.x] < 3 && !monster._field7 && _vm->_moveMonsters) {
+		++_monsterMap[pt.y][pt.x];
+		--_monsterMap[monster._position.y][monster._position.x];
+		monster._position = pt;
+		_monsterMoved[monsterId] = true;
+	}
+}
+
+void Combat::endAttack() {
+	Interface &intf = *_vm->_interface;
+	Map &map = *_vm->_map;
+	Party &party = *_vm->_party;
+	intf._isAttacking = false;
+	IndoorDrawList &indoorList = intf._indoorList;
+	OutdoorDrawList &outdoorList = intf._outdoorList;
+
+	for (uint idx = 0; idx < party._activeParty.size(); ++idx) {
+		Character &c = party._activeParty[idx];
+
+		if (map._isOutdoors) {
+			outdoorList._attackImgs1[idx]._scale = 0;
+			outdoorList._attackImgs2[idx]._scale = 0;
+			outdoorList._attackImgs3[idx]._scale = 0;
+			outdoorList._attackImgs4[idx]._scale = 0;
+			outdoorList._attackImgs1[idx]._sprites = nullptr;
+			outdoorList._attackImgs2[idx]._sprites = nullptr;
+			outdoorList._attackImgs3[idx]._sprites = nullptr;
+			outdoorList._attackImgs4[idx]._sprites = nullptr;
+		} else {
+			indoorList._attackImgs1[idx]._scale = 0;
+			indoorList._attackImgs2[idx]._scale = 0;
+			indoorList._attackImgs3[idx]._scale = 0;
+			indoorList._attackImgs4[idx]._scale = 0;
+			indoorList._attackImgs1[idx]._sprites = nullptr;
+			indoorList._attackImgs2[idx]._sprites = nullptr;
+			indoorList._attackImgs3[idx]._sprites = nullptr;
+			indoorList._attackImgs4[idx]._sprites = nullptr;
+		}
+	}
+
+	Common::fill(&_shooting[0], &_shooting[MAX_PARTY_COUNT], false);
+}
+
+void Combat::monsterOvercome() {
+	Map &map = *_vm->_map;
+
+	for (uint idx = 0; idx < map._mobData._monsters.size(); ++idx) {
+		MazeMonster &monster = map._mobData._monsters[idx];
+		int dataIndex = monster._spriteId;
+
+		if (monster._field7 != 0 && monster._field7 != 13) {
+			// Do a saving throw for monster
+			if (dataIndex <= _vm->getRandomNumber(1, dataIndex + 50))
+				monster._field7 = 0;
+		}
+	}
+}
+
+void Combat::attackMonster(int monsterId) {
+
+}
+
+bool Combat::stopAttack(const Common::Point &diffPt) {
+	// TODO
+	return false;
+}
 
 } // End of namespace Xeen
diff --git a/engines/xeen/combat.h b/engines/xeen/combat.h
index 5058742..977d580 100644
--- a/engines/xeen/combat.h
+++ b/engines/xeen/combat.h
@@ -24,9 +24,13 @@
 #define XEEN_COMBAT_H
 
 #include "common/scummsys.h"
+#include "common/rect.h"
+#include "xeen/sprites.h"
 
 namespace Xeen {
 
+#define MAX_NUM_MONSTERS 107
+
 enum DamageType {
 	DT_PHYSICAL = 0, DT_MAGICAL = 1, DT_FIRE = 2, DT_ELECTRICAL = 3,
 	DT_COLD = 4, DT_POISON = 5, DT_ENERGY = 6, DT_SLEEP = 7,
@@ -51,16 +55,39 @@ class Combat {
 private:
 	XeenEngine *_vm;
 public:
+	SpriteResource _powSprites;
 	int _attackMonsters[26];
 	int _charsArray1[12];
 	bool _monPow[12];
 	int _monsterScale[12];
 	int _elemPow[12];
 	int _elemScale[12];
-	bool _shooting[8];
+	int _shooting[8];
 	int _globalCombat;
 	int _whosTurn;
 	bool _itemFlag;
+	int _monsterMap[32][32];
+	bool _monsterMoved[MAX_NUM_MONSTERS];
+	bool _rangeAttacking[MAX_NUM_MONSTERS];
+	int _gmonHit[36];
+	bool _monstersAttacking;
+
+	void monstersAttack();
+
+	void setupMonsterAttack(int monsterDataIndex, const Common::Point &pt);
+
+	bool monsterCanMove(const Common::Point &pt, int wallShift,
+		int v1, int v2, int monsterId);
+
+	void moveMonster(int monsterId, const Common::Point &pt);
+
+	void attackMonster(int monsterId);
+
+	void endAttack();
+
+	void monsterOvercome();
+	
+	bool stopAttack(const Common::Point &diffPt);
 public:
 	Combat(XeenEngine *vm);
 
@@ -69,6 +96,8 @@ public:
 	void doCombat();
 
 	void giveCharDamage(int damage, int v2, int v3);
+
+	void moveMonsters();
 };
 
 } // End of namespace Xeen
diff --git a/engines/xeen/dialogs_items.cpp b/engines/xeen/dialogs_items.cpp
index d37d124..29ec4c6 100644
--- a/engines/xeen/dialogs_items.cpp
+++ b/engines/xeen/dialogs_items.cpp
@@ -1052,7 +1052,7 @@ int ItemsDialog::doItemOptions(Character &c, int actionIndex, int itemIndex, Ite
 	}
 
 	intf._charsShooting = false;
-	intf.moveMonsters();
+	combat.moveMonsters();
 	combat._whosTurn = -1;
 	return true;
 }
diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp
index 11fc312..db0bd81 100644
--- a/engines/xeen/interface.cpp
+++ b/engines/xeen/interface.cpp
@@ -142,7 +142,6 @@ Interface::Interface(XeenEngine *vm) : ButtonContainer(), InterfaceMap(vm),
 	_upDoorText = false;
 	_tillMove = 0;
 
-	Common::fill(&_combatCharIds[0], &_combatCharIds[8], 0);
 	initDrawStructs();
 }
 
@@ -244,6 +243,7 @@ void Interface::setMainButtons() {
  * be animated.
  */
 void Interface::perform() {
+	Combat &combat = *_vm->_combat;
 	EventsManager &events = *_vm->_events;
 	Map &map = *_vm->_map;
 	Party &party = *_vm->_party;
@@ -314,7 +314,7 @@ void Interface::perform() {
 	case Common::KEYCODE_w:
 		// Wait one turn
 		chargeStep();
-		moveMonsters();
+		combat.moveMonsters();
 		_upDoorText = false;
 		_flipDefaultGround = !_flipDefaultGround;
 		_flipGround = !_flipGround;
@@ -456,7 +456,7 @@ void Interface::perform() {
 		if (_buttonValue < (int)party._activeParty.size()) {
 			CharacterInfo::show(_vm, _buttonValue);
 			if (party._stepped)
-				moveMonsters();
+				combat.moveMonsters();
 		}
 		break;
 
@@ -533,7 +533,7 @@ void Interface::chargeStep() {
 	if (_vm->_party->_partyDead) {
 		_vm->_party->changeTime(_vm->_map->_isOutdoors ? 10 : 1);
 		if (!_tillMove) {
-			moveMonsters();
+			_vm->_combat->moveMonsters();
 		}
 
 		_tillMove = 3;
@@ -1181,9 +1181,9 @@ void Interface::draw3d(bool updateFlag) {
 	if (_flipUIFrame == 0)
 		_flipWater = !_flipWater;
 	if (_tillMove && (_vm->_mode == MODE_1 || _vm->_mode == MODE_COMBAT) &&
-		!_flag1 && _vm->_moveMonsters) {
+		!combat._monstersAttacking && _vm->_moveMonsters) {
 		if (--_tillMove == 0)
-			moveMonsters();
+			combat.moveMonsters();
 	}
 
 	// Draw the map
@@ -1213,8 +1213,8 @@ void Interface::draw3d(bool updateFlag) {
 
 	if (combat._attackMonsters[0] != -1 || combat._attackMonsters[1] != -1
 			|| combat._attackMonsters[2] != -1) {
-		if ((_vm->_mode == MODE_1 || _vm->_mode == MODE_SLEEPING) && !_flag1
-				&& !_charsShooting && _vm->_moveMonsters) {
+		if ((_vm->_mode == MODE_1 || _vm->_mode == MODE_SLEEPING) && 
+				!combat._monstersAttacking && !_charsShooting && _vm->_moveMonsters) {
 			combat.doCombat();
 			if (scripts._eventSkipped)
 				scripts.checkEvents();
@@ -1795,8 +1795,4 @@ void Interface::assembleBorder() {
 		screen._windows[12].frame();
 }
 
-void Interface::moveMonsters() {
-	// TODO
-}
-
 } // End of namespace Xeen
diff --git a/engines/xeen/interface.h b/engines/xeen/interface.h
index fa5f1aa..297b984 100644
--- a/engines/xeen/interface.h
+++ b/engines/xeen/interface.h
@@ -69,7 +69,6 @@ private:
 	SpriteResource _fecpSprites;
 	SpriteResource _blessSprites;
 	DrawStruct _mainList[16];
-	int _combatCharIds[8];
 
 	bool _buttonsLoaded;
 	int _steppingFX;
@@ -140,8 +139,6 @@ public:
 	void draw3d(bool updateFlag);
 
 	void assembleBorder();
-
-	void moveMonsters();
 };
 
 } // End of namespace Xeen
diff --git a/engines/xeen/interface_map.cpp b/engines/xeen/interface_map.cpp
index a3241a1..d6d15d6 100644
--- a/engines/xeen/interface_map.cpp
+++ b/engines/xeen/interface_map.cpp
@@ -30,8 +30,8 @@ namespace Xeen {
 static bool debugFlag = false;
 
 OutdoorDrawList::OutdoorDrawList() : _sky1(_data[0]), _sky2(_data[1]), 
-	_groundSprite(_data[2]), _combatImgs1(&_data[124]), _combatImgs2(&_data[95]),
-	_combatImgs3(&_data[76]), _combatImgs4(&_data[53]), _groundTiles(&_data[3]) {
+	_groundSprite(_data[2]), _attackImgs1(&_data[124]), _attackImgs2(&_data[95]),
+	_attackImgs3(&_data[76]), _attackImgs4(&_data[53]), _groundTiles(&_data[3]) {
 	_data[0] = DrawStruct(0, 8, 8);
 	_data[1] = DrawStruct(1, 8, 25);
 	_data[2] = DrawStruct(0, 8, 67);
@@ -190,8 +190,8 @@ IndoorDrawList::IndoorDrawList() :
 	_objects3(_data[127]), _objects4(_data[97]), _objects5(_data[98]),
 	_objects6(_data[99]), _objects7(_data[55]), _objects8(_data[56]),
 	_objects9(_data[58]), _objects10(_data[57]), _objects11(_data[59]),
-	_combatImgs1(&_data[162]), _combatImgs2(&_data[135]),
-	_combatImgs3(&_data[111]), _combatImgs4(&_data[79]) {
+	_attackImgs1(&_data[162]), _attackImgs2(&_data[135]),
+	_attackImgs3(&_data[111]), _attackImgs4(&_data[79]) {
 	// Setup draw structure positions
 	_data[0] = DrawStruct(0, 8, 8);
 	_data[1] = DrawStruct(1, 8, 25);
@@ -375,13 +375,12 @@ InterfaceMap::InterfaceMap(XeenEngine *vm): _vm(vm) {
 	_flipGround = false;
 	_flipSky = false;
 	_flipDefaultGround = false;
-	_isShooting = false;
+	_isAttacking = false;
 	_charsShooting = false;
 	_objNumber = 0;
 	_combatFloatCounter = 0;
 	_thinWall = false;
 	_isAnimReset = false;
-	_flag1 = false;
 	_overallFrame = 0;
 	_openDoor = false;
 }
@@ -430,27 +429,27 @@ void InterfaceMap::drawMap() {
 		for (int idx = 0; idx < 44; ++idx)
 			_outdoorList[OUTDOOR_DRAWSTRCT_INDEXES[idx]]._frame = -1;
 
-		if (_flag1) {
+		if (combat._monstersAttacking) {
 			for (int idx = 0; idx < 8; ++idx) {
-				if (_outdoorList._combatImgs4[idx]._sprites)
-					_outdoorList._combatImgs4[idx]._frame = 0;
-				else if (_outdoorList._combatImgs3[idx]._sprites)
-					_outdoorList._combatImgs3[idx]._frame = 1;
-				else if (_outdoorList._combatImgs2[idx]._sprites)
-					_outdoorList._combatImgs2[idx]._frame = 2;
-				else if (_outdoorList._combatImgs1[idx]._sprites)
-					_outdoorList._combatImgs1[idx]._frame = 0;
+				if (_outdoorList._attackImgs4[idx]._sprites)
+					_outdoorList._attackImgs4[idx]._frame = 0;
+				else if (_outdoorList._attackImgs3[idx]._sprites)
+					_outdoorList._attackImgs3[idx]._frame = 1;
+				else if (_outdoorList._attackImgs2[idx]._sprites)
+					_outdoorList._attackImgs2[idx]._frame = 2;
+				else if (_outdoorList._attackImgs1[idx]._sprites)
+					_outdoorList._attackImgs1[idx]._frame = 0;
 			}
 		} else if (_charsShooting) {
 			for (int idx = 0; idx < 8; ++idx) {
-				if (_outdoorList._combatImgs1[idx]._sprites)
-					_outdoorList._combatImgs1[idx]._frame = 0;
-				else if (_outdoorList._combatImgs2[idx]._sprites)
-					_outdoorList._combatImgs2[idx]._frame = 1;
-				else if (_outdoorList._combatImgs3[idx]._sprites)
-					_outdoorList._combatImgs3[idx]._frame = 2;
-				else if (_outdoorList._combatImgs4[idx]._sprites)
-					_outdoorList._combatImgs1[idx]._frame = 0;
+				if (_outdoorList._attackImgs1[idx]._sprites)
+					_outdoorList._attackImgs1[idx]._frame = 0;
+				else if (_outdoorList._attackImgs2[idx]._sprites)
+					_outdoorList._attackImgs2[idx]._frame = 1;
+				else if (_outdoorList._attackImgs3[idx]._sprites)
+					_outdoorList._attackImgs3[idx]._frame = 2;
+				else if (_outdoorList._attackImgs4[idx]._sprites)
+					_outdoorList._attackImgs1[idx]._frame = 0;
 			}
 		}
 
@@ -557,7 +556,7 @@ void InterfaceMap::drawMap() {
 		for (int idx = 3; idx < _indoorList.size(); ++idx)
 			_indoorList[idx]._frame = -1;
 
-		if (_flag1) {
+		if (combat._monstersAttacking) {
 			for (int idx = 0; idx < 96; ++idx) {
 				if (_indoorList[79 + idx]._sprites != nullptr) {
 					_indoorList[79 + idx]._frame = 0;
@@ -762,12 +761,12 @@ void InterfaceMap::animate3d() {
 		}
 	}
 
-	DrawStruct *combatImgs1 = map._isOutdoors ? _outdoorList._combatImgs1 : _indoorList._combatImgs1;
-	DrawStruct *combatImgs2 = map._isOutdoors ? _outdoorList._combatImgs2 : _indoorList._combatImgs2;
-	DrawStruct *combatImgs3 = map._isOutdoors ? _outdoorList._combatImgs3 : _indoorList._combatImgs3;
-	DrawStruct *combatImgs4 = map._isOutdoors ? _outdoorList._combatImgs4 : _indoorList._combatImgs4;
+	DrawStruct *combatImgs1 = map._isOutdoors ? _outdoorList._attackImgs1 : _indoorList._attackImgs1;
+	DrawStruct *combatImgs2 = map._isOutdoors ? _outdoorList._attackImgs2 : _indoorList._attackImgs2;
+	DrawStruct *combatImgs3 = map._isOutdoors ? _outdoorList._attackImgs3 : _indoorList._attackImgs3;
+	DrawStruct *combatImgs4 = map._isOutdoors ? _outdoorList._attackImgs4 : _indoorList._attackImgs4;
 
-	if (_flag1) {
+	if (combat._monstersAttacking) {
 		for (int idx = 0; idx < 8; ++idx) {
 			if (combatImgs1[idx]._sprites) {
 				combatImgs1[idx]._sprites = nullptr;
@@ -4326,13 +4325,13 @@ void InterfaceMap::drawIndoors() {
 	_vm->_screen->_windows[3].drawList(&_indoorList[0], _indoorList.size());
 
 	// Check for any character shooting
-	_isShooting = false;
+	_isAttacking = false;
 	for (uint idx = 0; idx < _vm->_party->_activeParty.size(); ++idx) {
 		if (_vm->_combat->_shooting[idx])
-			_isShooting = true;
+			_isAttacking = true;
 	}
 	
-	_charsShooting = _isShooting;
+	_charsShooting = _isAttacking;
 }
 
 /**
@@ -4404,13 +4403,13 @@ void InterfaceMap::drawOutdoors() {
 	screen._windows[3].drawList(&_outdoorList[0], _outdoorList.size());
 
 	// Check for any character shooting
-	_isShooting = false;
+	_isAttacking = false;
 	for (uint idx = 0; idx < _vm->_party->_activeParty.size(); ++idx) {
 		if (_vm->_combat->_shooting[idx])
-			_isShooting = true;
+			_isAttacking = true;
 	}
 
-	_charsShooting = _isShooting;
+	_charsShooting = _isAttacking;
 }
 
 } // End of namespace Xeen
diff --git a/engines/xeen/interface_map.h b/engines/xeen/interface_map.h
index 1ff9829..a37bf34 100644
--- a/engines/xeen/interface_map.h
+++ b/engines/xeen/interface_map.h
@@ -37,10 +37,10 @@ public:
 	DrawStruct &_sky1, &_sky2;
 	DrawStruct &_groundSprite;
 	DrawStruct * const _groundTiles;
-	DrawStruct * const _combatImgs1;
-	DrawStruct * const _combatImgs2;
-	DrawStruct * const _combatImgs3;
-	DrawStruct * const _combatImgs4;
+	DrawStruct * const _attackImgs1;
+	DrawStruct * const _attackImgs2;
+	DrawStruct * const _attackImgs3;
+	DrawStruct * const _attackImgs4;
 public:
 	OutdoorDrawList();
 
@@ -73,10 +73,10 @@ public:
 	DrawStruct &_objects0, &_objects1, &_objects2, &_objects3;
 	DrawStruct &_objects4, &_objects5, &_objects6, &_objects7;
 	DrawStruct &_objects8, &_objects9, &_objects10, &_objects11;
-	DrawStruct * const _combatImgs1;
-	DrawStruct * const _combatImgs2;
-	DrawStruct * const _combatImgs3;
-	DrawStruct * const _combatImgs4;
+	DrawStruct * const _attackImgs1;
+	DrawStruct * const _attackImgs2;
+	DrawStruct * const _attackImgs3;
+	DrawStruct * const _attackImgs4;
 public:
 	IndoorDrawList();
 
@@ -104,10 +104,8 @@ protected:
 	bool _flipGround;
 	bool _flipSky;
 	bool _flipDefaultGround;
-	bool _isShooting;
 	bool _thinWall;
 	bool _isAnimReset;
-	bool _flag1;
 
 	void setMazeBits();
 
@@ -122,6 +120,7 @@ public:
 	int _overallFrame;
 	bool _charsShooting;
 	bool _openDoor;
+	bool _isAttacking;
 public:
 	InterfaceMap(XeenEngine *vm);
 


Commit: e7ffed76b43471052597bae43afe51c168ded01b
    https://github.com/scummvm/scummvm/commit/e7ffed76b43471052597bae43afe51c168ded01b
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-02-16T11:42:29-05:00

Commit Message:
XEEN: Implemented giveCharDamage

Changed paths:
    engines/xeen/combat.cpp
    engines/xeen/combat.h
    engines/xeen/interface.cpp



diff --git a/engines/xeen/combat.cpp b/engines/xeen/combat.cpp
index 3797c18..9848e80 100644
--- a/engines/xeen/combat.cpp
+++ b/engines/xeen/combat.cpp
@@ -104,8 +104,132 @@ void Combat::doCombat() {
 	error("TODO: doCombat");
 }
 
-void Combat::giveCharDamage(int damage, int v2, int v3) {
-	error("TODO: giveCharDamage");
+void Combat::giveCharDamage(int damage, DamageType attackType, int charIndex) {
+	Party &party = *_vm->_party;
+	Screen &screen = *_vm->_screen;
+	Scripts &scripts = *_vm->_scripts;
+	SoundManager &sound = *_vm->_sound;
+	int charIndex1 = charIndex + 1;
+	int selectedIndex1 = 0;
+	int selectedIndex2 = 0;
+	bool breakFlag = false;
+
+	screen.closeWindows();
+	
+	int idx = (int)party._activeParty.size();
+	if (!scripts._v2) {
+		for (idx = 0; idx < (int)party._activeParty.size(); ++idx) {
+			Character &c = party._activeParty[idx];
+			Condition condition = c.worstCondition();
+
+			if (!(condition >= UNCONSCIOUS && condition <= ERADICATED)) {
+				if (!selectedIndex1) {
+					selectedIndex1 = idx + 1;
+				} else {
+					selectedIndex2 = idx + 1;
+					break;
+				}
+			}
+		}
+	}
+	if (idx == (int)party._activeParty.size()) {
+		selectedIndex1 = scripts._v2 ? charIndex : 0;
+		goto loop;
+	}
+
+	for (;;) {
+		// The if below is to get around errors due to the
+		// goto I was forced to use when reimplementing this method
+		if (true) {
+			Character &c = party._activeParty[selectedIndex1];
+			c._conditions[ASLEEP] = 0;	// Force character to be awake
+
+			int frame = 0, fx = 0;
+			switch (attackType) {
+			case DT_PHYSICAL:
+				fx = 29;
+				break;
+			case DT_MAGICAL:
+				frame = 6;
+				fx = 27;
+				break;
+			case DT_FIRE:
+				damage -= party._fireResistence;
+				frame = 1;
+				fx = 22;
+				break;
+			case DT_ELECTRICAL:
+				damage -= party._electricityResistence;
+				frame = 2;
+				fx = 23;
+				break;
+			case DT_COLD:
+				damage -= party._coldResistence;
+				frame = 3;
+				fx = 24;
+				break;
+			case DT_POISON:
+				damage -= party._poisonResistence;
+				frame = 4;
+				fx = 26;
+				break;
+			case DT_ENERGY:
+				frame = 5;
+				fx = 25;
+				break;
+			case DT_SLEEP:
+				fx = 38;
+				break;
+			default:
+				break;
+			}
+
+			// All attack types other than physical allow for saving
+			// throws to reduce the damage
+			if (attackType != DT_PHYSICAL) {
+				while (c.charSavingThrow(attackType) && damage > 0)
+					damage /= 2;
+			}
+
+			// Draw the attack effect on the character sprite
+			sound.playFX(fx);
+			_powSprites.draw(screen, frame,
+				Common::Point(CHAR_FACES_X[selectedIndex1], 150));
+			screen._windows[33].update();
+
+			// Reduce damage if power shield active, and set it zero
+			// if the damage amount has become negative.. you wouldn't
+			// want attacks healing the characters
+			if (party._powerShield)
+				damage -= party._powerShield;
+			if (damage < 0)
+				damage = 0;
+
+			// TODO: This seems weird.. maybe I've got attack types wrong..
+			// why should attack type 7 (DT_SLEEP) set the dead condition?
+			if (attackType == DT_SLEEP) {
+				damage = c._currentHp;
+				c._conditions[DEAD] = 1;
+			}
+
+			// Subtract the hit points from the character
+			c.subtractHitPoints(damage);
+		}
+
+		if (selectedIndex2) {
+			++selectedIndex1;
+loop:
+			if ((scripts._v2 ? charIndex1 : (int)party._activeParty.size()) > selectedIndex1)
+				break;
+		}
+
+		// Break check and if not, move to other index
+		if (!selectedIndex2 || breakFlag)
+			break;
+
+		selectedIndex1 = selectedIndex2 - 1;
+		breakFlag = true;
+	}
 }
 
 void Combat::moveMonsters() {
@@ -445,6 +569,12 @@ void Combat::attackMonster(int monsterId) {
 }
 
 bool Combat::stopAttack(const Common::Point &diffPt) {
+	Map &map = *_vm->_map;
+
+	if (map._isOutdoors) {
+
+	}
+
 	// TODO
 	return false;
 }
diff --git a/engines/xeen/combat.h b/engines/xeen/combat.h
index 977d580..d6ec233 100644
--- a/engines/xeen/combat.h
+++ b/engines/xeen/combat.h
@@ -95,7 +95,7 @@ public:
 
 	void doCombat();
 
-	void giveCharDamage(int damage, int v2, int v3);
+	void giveCharDamage(int damage, DamageType attackType, int charIndex);
 
 	void moveMonsters();
 };
diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp
index db0bd81..c8324a6 100644
--- a/engines/xeen/interface.cpp
+++ b/engines/xeen/interface.cpp
@@ -839,7 +839,7 @@ void Interface::startFalling(bool flag) {
 	draw3d(true);
 	int tempVal = scripts._v2;
 	scripts._v2 = 0;
-	combat.giveCharDamage(party._fallDamage, 0, 0);
+	combat.giveCharDamage(party._fallDamage, DT_PHYSICAL, 0);
 	scripts._v2 = tempVal;
 
 	_flipGround ^= 1;


Commit: 30d94950beb02188644dcfd71f3c3a067d0a0c5a
    https://github.com/scummvm/scummvm/commit/30d94950beb02188644dcfd71f3c3a067d0a0c5a
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-02-16T14:35:23-05:00

Commit Message:
XEEN: Starting of combat UI, moved _combatParty into Combat class

Changed paths:
    engines/xeen/combat.cpp
    engines/xeen/combat.h
    engines/xeen/dialogs_char_info.cpp
    engines/xeen/dialogs_items.cpp
    engines/xeen/dialogs_quick_ref.cpp
    engines/xeen/interface.cpp
    engines/xeen/interface.h
    engines/xeen/party.cpp
    engines/xeen/party.h



diff --git a/engines/xeen/combat.cpp b/engines/xeen/combat.cpp
index 9848e80..d660817 100644
--- a/engines/xeen/combat.cpp
+++ b/engines/xeen/combat.cpp
@@ -22,6 +22,7 @@
 
 #include "common/algorithm.h"
 #include "common/rect.h"
+#include "xeen/character.h"
 #include "xeen/combat.h"
 #include "xeen/interface.h"
 #include "xeen/xeen.h"
@@ -94,16 +95,13 @@ Combat::Combat(XeenEngine *vm): _vm(vm) {
 	_whosTurn = -1;
 	_itemFlag = false;
 	_monstersAttacking = false;
+	_combatMode = 0;
 }
 
 void Combat::clear() {
 	Common::fill(&_attackMonsters[0], &_attackMonsters[26], -1);
 }
 
-void Combat::doCombat() {
-	error("TODO: doCombat");
-}
-
 void Combat::giveCharDamage(int damage, DamageType attackType, int charIndex) {
 	Party &party = *_vm->_party;
 	Screen &screen = *_vm->_screen;
@@ -414,9 +412,9 @@ void Combat::monstersAttack() {
 	if (_vm->_mode != MODE_COMBAT) {
 		// Combat wasn't previously active, but it is now. Set up
 		// the combat party from the currently active party
-		party._combatParty.clear();
+		_combatParty.clear();
 		for (uint idx = 0; idx < party._activeParty.size(); ++idx)
-			party._combatParty.push_back(&party._activeParty[idx]);
+			_combatParty.push_back(&party._activeParty[idx]);
 	}
 
 	for (int idx = 0; idx < 36; ++idx) {
@@ -523,8 +521,6 @@ void Combat::endAttack() {
 	OutdoorDrawList &outdoorList = intf._outdoorList;
 
 	for (uint idx = 0; idx < party._activeParty.size(); ++idx) {
-		Character &c = party._activeParty[idx];
-
 		if (map._isOutdoors) {
 			outdoorList._attackImgs1[idx]._scale = 0;
 			outdoorList._attackImgs2[idx]._scale = 0;
diff --git a/engines/xeen/combat.h b/engines/xeen/combat.h
index d6ec233..6b306b4 100644
--- a/engines/xeen/combat.h
+++ b/engines/xeen/combat.h
@@ -50,11 +50,15 @@ enum SpecialAttack {
 };
 
 class XeenEngine;
+class Character;
 
 class Combat {
 private:
 	XeenEngine *_vm;
 public:
+	Common::Array<Character *> _combatParty;
+	Common::Array<int> _charsBlocked;
+	Common::Array<int> _charsGone;
 	SpriteResource _powSprites;
 	int _attackMonsters[26];
 	int _charsArray1[12];
@@ -71,6 +75,7 @@ public:
 	bool _rangeAttacking[MAX_NUM_MONSTERS];
 	int _gmonHit[36];
 	bool _monstersAttacking;
+	int _combatMode;
 
 	void monstersAttack();
 
@@ -93,8 +98,6 @@ public:
 
 	void clear();
 
-	void doCombat();
-
 	void giveCharDamage(int damage, DamageType attackType, int charIndex);
 
 	void moveMonsters();
diff --git a/engines/xeen/dialogs_char_info.cpp b/engines/xeen/dialogs_char_info.cpp
index df4b699..c00916c 100644
--- a/engines/xeen/dialogs_char_info.cpp
+++ b/engines/xeen/dialogs_char_info.cpp
@@ -36,18 +36,19 @@ void CharacterInfo::show(XeenEngine *vm, int charIndex) {
 }
 
 void CharacterInfo::execute(int charIndex) {
-	Screen &screen = *_vm->_screen;
+	Combat &combat = *_vm->_combat;
 	EventsManager &events = *_vm->_events;
 	Interface &intf = *_vm->_interface;
 	Party &party = *_vm->_party;
-	
+	Screen &screen = *_vm->_screen;
+
 	bool redrawFlag = true;
 	Mode oldMode = _vm->_mode;
 	_vm->_mode = MODE_CHARACTER_INFO;
 	loadDrawStructs();
 	addButtons();
 
-	Character *c = (oldMode != MODE_COMBAT) ? &party._activeParty[charIndex] : party._combatParty[charIndex];
+	Character *c = (oldMode != MODE_COMBAT) ? &party._activeParty[charIndex] : combat._combatParty[charIndex];
 	intf.highlightChar(charIndex);
 	Window &w = screen._windows[24];
 	w.open();
@@ -86,9 +87,9 @@ void CharacterInfo::execute(int charIndex) {
 		case Common::KEYCODE_F5:
 		case Common::KEYCODE_F6:
 			_buttonValue -= Common::KEYCODE_F1;
-			if (_buttonValue < (int)(oldMode == MODE_COMBAT ? party._combatParty.size() : party._activeParty.size())) {
+			if (_buttonValue < (int)(oldMode == MODE_COMBAT ? combat._combatParty.size() : party._activeParty.size())) {
 				charIndex = _buttonValue;
-				c = (oldMode != MODE_COMBAT) ? &party._activeParty[charIndex] : party._combatParty[charIndex];
+				c = (oldMode != MODE_COMBAT) ? &party._activeParty[charIndex] : combat._combatParty[charIndex];
 			} else {
 				_vm->_mode = MODE_CHARACTER_INFO;
 			}
diff --git a/engines/xeen/dialogs_items.cpp b/engines/xeen/dialogs_items.cpp
index 29ec4c6..ec82afb 100644
--- a/engines/xeen/dialogs_items.cpp
+++ b/engines/xeen/dialogs_items.cpp
@@ -37,6 +37,7 @@ Character *ItemsDialog::show(XeenEngine *vm, Character *c, ItemsMode mode) {
 }
 
 Character *ItemsDialog::execute(Character *c, ItemsMode mode) {
+	Combat &combat = *_vm->_combat;
 	EventsManager &events = *_vm->_events;
 	Interface &intf = *_vm->_interface;
 	Party &party = *_vm->_party;
@@ -337,11 +338,11 @@ Character *ItemsDialog::execute(Character *c, ItemsMode mode) {
 				_buttonValue -= Common::KEYCODE_F1;
 				
 				if (_buttonValue < (int)(_vm->_mode == MODE_COMBAT ?
-						party._combatParty.size() : party._activeParty.size())) {
+						combat._combatParty.size() : party._activeParty.size())) {
 					// Character number is valid
 					redrawFlag = REDRAW_TEXT;
 					Character *newChar = _vm->_mode == MODE_COMBAT ?
-						party._combatParty[_buttonValue] : &party._activeParty[_buttonValue];
+						combat._combatParty[_buttonValue] : &party._activeParty[_buttonValue];
 
 					if (mode == ITEMMODE_BLACKSMITH) {
 						_oldCharacter = newChar;
diff --git a/engines/xeen/dialogs_quick_ref.cpp b/engines/xeen/dialogs_quick_ref.cpp
index f4066a0..e9ffbd4 100644
--- a/engines/xeen/dialogs_quick_ref.cpp
+++ b/engines/xeen/dialogs_quick_ref.cpp
@@ -41,9 +41,9 @@ void QuickReferenceDialog::execute() {
 
 	events.setCursor(0);
 
-	for (uint idx = 0; idx < (combat._globalCombat == 2 ? party._combatParty.size() :
+	for (uint idx = 0; idx < (combat._globalCombat == 2 ? combat._combatParty.size() :
 			party._activeParty.size()); ++idx) {
-		Character &c = combat._globalCombat == 2 ? *party._combatParty[idx] :
+		Character &c = combat._globalCombat == 2 ? *combat._combatParty[idx] :
 			party._activeParty[idx];
 		Condition condition = c.worstCondition();
 		lines[idx] = Common::String::format(QUICK_REF_LINE,
diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp
index c8324a6..479795d 100644
--- a/engines/xeen/interface.cpp
+++ b/engines/xeen/interface.cpp
@@ -43,6 +43,7 @@ PartyDrawer::PartyDrawer(XeenEngine *vm): _vm(vm) {
 }
 
 void PartyDrawer::drawParty(bool updateFlag) {
+	Combat &combat = *_vm->_combat;
 	Party &party = *_vm->_party;
 	Resources &res = *_vm->_resources;
 	Screen &screen = *_vm->_screen;
@@ -50,9 +51,9 @@ void PartyDrawer::drawParty(bool updateFlag) {
 	_restoreSprites.draw(screen, 0, Common::Point(8, 149));
 
 	// Handle drawing the party faces
-	uint partyCount = inCombat ? party._combatParty.size() : party._activeParty.size();
+	uint partyCount = inCombat ? combat._combatParty.size() : party._activeParty.size();
 	for (uint idx = 0; idx < partyCount; ++idx) {
-		Character &ps = inCombat ? *party._combatParty[idx] : party._activeParty[idx];
+		Character &ps = inCombat ? *combat._combatParty[idx] : party._activeParty[idx];
 		Condition charCondition = ps.worstCondition();
 		int charFrame = FACE_CONDITION_FRAMES[charCondition];
 		
@@ -64,7 +65,7 @@ void PartyDrawer::drawParty(bool updateFlag) {
 	}
 
 	for (uint idx = 0; idx < partyCount; ++idx) {
-		Character &ps = inCombat ? *party._combatParty[idx] : party._activeParty[idx];
+		Character &ps = inCombat ? *combat._combatParty[idx] : party._activeParty[idx];
 
 		// Draw the Hp bar
 		int maxHp = ps.getMaxHP();
@@ -212,7 +213,7 @@ void Interface::mainIconsPrint() {
 	screen._windows[34].update();
 }
 
-void Interface::setMainButtons() {
+void Interface::setMainButtons(bool combatMode) {
 	clearButtons();
 
 	addButton(Common::Rect(235,  75, 259,  95),  Common::KEYCODE_s, &_iconSprites);
@@ -236,6 +237,18 @@ void Interface::setMainButtons() {
 	addButton(Common::Rect(239, 37, 312, 47), Common::KEYCODE_2, &_iconSprites, false);
 	addButton(Common::Rect(239, 47, 312, 57), Common::KEYCODE_3, &_iconSprites, false);
 	addPartyButtons(_vm);
+
+	if (combatMode) {
+		_buttons[0]._value = Common::KEYCODE_f;
+		_buttons[1]._value = Common::KEYCODE_c;
+		_buttons[2]._value = Common::KEYCODE_a;
+		_buttons[3]._value = Common::KEYCODE_u;
+		_buttons[4]._value = Common::KEYCODE_r;
+		_buttons[5]._value = Common::KEYCODE_b;
+		_buttons[6]._value = Common::KEYCODE_o;
+		_buttons[7]._value = Common::KEYCODE_i;
+		_buttons[16]._value = 0;
+	}
 }
 
 /**
@@ -1215,7 +1228,7 @@ void Interface::draw3d(bool updateFlag) {
 			|| combat._attackMonsters[2] != -1) {
 		if ((_vm->_mode == MODE_1 || _vm->_mode == MODE_SLEEPING) && 
 				!combat._monstersAttacking && !_charsShooting && _vm->_moveMonsters) {
-			combat.doCombat();
+			doCombat();
 			if (scripts._eventSkipped)
 				scripts.checkEvents();
 		}
@@ -1795,4 +1808,28 @@ void Interface::assembleBorder() {
 		screen._windows[12].frame();
 }
 
+void Interface::doCombat() {
+	Combat &combat = *_vm->_combat;
+	EventsManager &events = *_vm->_events;
+	Screen &screen = *_vm->_screen;
+	bool isDarkCc = _vm->_files->_isDarkCc;
+	bool upDoorText = _upDoorText;
+	
+	_upDoorText = false;
+	combat._combatMode = 2;
+	_vm->_mode = MODE_COMBAT;
+
+	_iconSprites.load("combat.icn");
+	for (int idx = 1; idx < 16; ++idx)
+		_mainList[idx]._sprites = nullptr;
+
+	// Set the combat buttons
+	setMainButtons(true);
+	mainIconsPrint();
+
+
+
+	error("TODO");
+}
+
 } // End of namespace Xeen
diff --git a/engines/xeen/interface.h b/engines/xeen/interface.h
index 297b984..40926ac 100644
--- a/engines/xeen/interface.h
+++ b/engines/xeen/interface.h
@@ -84,7 +84,7 @@ private:
 
 	void setupBackground();
 
-	void setMainButtons();
+	void setMainButtons(bool combatMode = false);
 
 	void chargeStep();
 
@@ -139,6 +139,8 @@ public:
 	void draw3d(bool updateFlag);
 
 	void assembleBorder();
+
+	void doCombat();
 };
 
 } // End of namespace Xeen
diff --git a/engines/xeen/party.cpp b/engines/xeen/party.cpp
index 2eb4cc2..3913ad6 100644
--- a/engines/xeen/party.cpp
+++ b/engines/xeen/party.cpp
@@ -105,7 +105,6 @@ Party::Party(XeenEngine *vm) {
 	for (int i = 0; i < TOTAL_CHARACTERS; ++i)
 		Common::fill(&_characterFlags[i][0], &_characterFlags[i][24], false);
 
-	_combatPartyCount = 0;
 	_partyDead = false;
 	_newDay = false;
 	_isNight = false;
@@ -531,10 +530,11 @@ void Party::notEnough(int consumableId, int whereId, bool mode, ErrorWaitType wa
 }
 
 void Party::checkPartyDead() {
+	Combat &combat = *_vm->_combat;
 	bool inCombat = _vm->_mode == MODE_COMBAT;
 
-	for (uint charIdx = 0; charIdx < (inCombat ? _combatParty.size() : _activeParty.size()); ++charIdx) {
-		Character &c = inCombat ? *_combatParty[charIdx] : _activeParty[charIdx];
+	for (uint charIdx = 0; charIdx < (inCombat ? combat._combatParty.size() : _activeParty.size()); ++charIdx) {
+		Character &c = inCombat ? *combat._combatParty[charIdx] : _activeParty[charIdx];
 		Condition cond = c.worstCondition();
 		if (cond <= CONFUSED || cond == NO_CONDITION) {
 			_dead = false;
diff --git a/engines/xeen/party.h b/engines/xeen/party.h
index 4f32cca..035b344 100644
--- a/engines/xeen/party.h
+++ b/engines/xeen/party.h
@@ -115,8 +115,6 @@ public:
 	// Other party related runtime data
 	Roster _roster;
 	Common::Array<Character> _activeParty;
-	Common::Array<Character *> _combatParty;
-	int _combatPartyCount;
 	bool _partyDead;
 	bool _newDay;
 	bool _isNight;


Commit: c045adae76e414a8e6b57e48a651ea6c29ed280a
    https://github.com/scummvm/scummvm/commit/c045adae76e414a8e6b57e48a651ea6c29ed280a
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-02-16T19:58:53-05:00

Commit Message:
XEEN: Implementing more combat logic

Changed paths:
  A engines/xeen/dialogs_control_panel.cpp
  A engines/xeen/dialogs_control_panel.h
  A engines/xeen/dialogs_fight_options.cpp
  A engines/xeen/dialogs_fight_options.h
    engines/xeen/character.cpp
    engines/xeen/character.h
    engines/xeen/combat.cpp
    engines/xeen/combat.h
    engines/xeen/interface.cpp
    engines/xeen/interface.h
    engines/xeen/map.cpp
    engines/xeen/map.h
    engines/xeen/module.mk
    engines/xeen/party.cpp
    engines/xeen/party.h
    engines/xeen/resources.cpp
    engines/xeen/resources.h
    engines/xeen/scripts.cpp



diff --git a/engines/xeen/character.cpp b/engines/xeen/character.cpp
index ac25b32..afe3854 100644
--- a/engines/xeen/character.cpp
+++ b/engines/xeen/character.cpp
@@ -818,6 +818,9 @@ void Character::synchronize(Common::Serializer &s) {
 	s.syncAsByte(_currentCombatSpell);
 }
 
+/**
+ * Returns the worst condition the character is suffering from
+ */
 Condition Character::worstCondition() const {
 	for (int cond = ERADICATED; cond >= CURSED; --cond) {
 		if (_conditions[cond])
@@ -827,6 +830,28 @@ Condition Character::worstCondition() const {
 	return NO_CONDITION;
 }
 
+/**
+ * Returns whether the given character has a disabling condition, but still alive
+ */
+bool Character::isDisabled() const {
+	Condition condition = worstCondition();
+
+	return condition == ASLEEP || condition == PARALYZED || condition == UNCONSCIOUS
+		|| condition == STONED || condition == ERADICATED;
+}
+
+/**
+* Returns whether the given character has a disabling condition, or is dead
+*/
+bool Character::isDisabledOrDead() const {
+	Condition condition = worstCondition();
+
+	return condition == ASLEEP || (condition >= PARALYZED && condition <= ERADICATED);
+}
+
+/**
+ * Get the character's age
+ */
 int Character::getAge(bool ignoreTemp) const {
 	int year = MIN(Party::_vm->_party->_year - _birthYear, (uint)254);
 
diff --git a/engines/xeen/character.h b/engines/xeen/character.h
index 9e8687d..be38ba5 100644
--- a/engines/xeen/character.h
+++ b/engines/xeen/character.h
@@ -270,6 +270,10 @@ public:
 
 	Condition worstCondition() const;
 
+	bool isDisabled() const;
+
+	bool isDisabledOrDead() const;
+
 	int getAge(bool ignoreTemp = false) const;
 
 	int getMaxHP() const;
diff --git a/engines/xeen/combat.cpp b/engines/xeen/combat.cpp
index d660817..c8f5824 100644
--- a/engines/xeen/combat.cpp
+++ b/engines/xeen/combat.cpp
@@ -96,6 +96,10 @@ Combat::Combat(XeenEngine *vm): _vm(vm) {
 	_itemFlag = false;
 	_monstersAttacking = false;
 	_combatMode = 0;
+	_monsterIndex = 0;
+	_partyRan = false;
+	_monster2Attack = -1;
+	_whosSpeed = 0;
 }
 
 void Combat::clear() {
@@ -412,9 +416,7 @@ void Combat::monstersAttack() {
 	if (_vm->_mode != MODE_COMBAT) {
 		// Combat wasn't previously active, but it is now. Set up
 		// the combat party from the currently active party
-		_combatParty.clear();
-		for (uint idx = 0; idx < party._activeParty.size(); ++idx)
-			_combatParty.push_back(&party._activeParty[idx]);
+		setupCombatParty();
 	}
 
 	for (int idx = 0; idx < 36; ++idx) {
@@ -575,4 +577,150 @@ bool Combat::stopAttack(const Common::Point &diffPt) {
 	return false;
 }
 
+/**
+ * Setup the combat party with a copy of the currently active party
+ */
+void Combat::setupCombatParty() {
+	Party &party = *_vm->_party;
+
+	_combatParty.clear();
+	for (uint idx = 0; idx < party._activeParty.size(); ++idx)
+		_combatParty.push_back(&party._activeParty[idx]);
+}
+
+void Combat::setSpeedTable() {
+	Map &map = *_vm->_map;
+	Common::Array<int> charSpeeds;
+	bool flag = _whosSpeed != -1;
+	int oldSpeed = (_whosSpeed == -1) ? 0 : _speedTable[_whosSpeed];
+
+	Common::fill(&_speedTable[0], &_speedTable[12], -1);
+	Common::fill(&charSpeeds[0], &charSpeeds[12], -1);
+
+	// Set up speeds for party membres
+	int maxSpeed = 0;
+	for (uint charNum = 0; charNum < _combatParty.size(); ++charNum) {
+		Character &c = *_combatParty[charNum];
+		charSpeeds.push_back(c.getStat(SPEED));
+
+		maxSpeed = MAX(charSpeeds[charNum], maxSpeed);
+	}
+
+	// Add in speeds of attacking monsters
+	for (int monsterNum = 0; monsterNum < 3; ++monsterNum) {
+		if (_attackMonsters[monsterNum] != -1) {
+			MazeMonster &monster = map._mobData._monsters[_attackMonsters[monsterNum]];
+			MonsterStruct &monsterData = map._monsterData[monster._spriteId];
+			charSpeeds.push_back(monsterData._speed);
+
+			maxSpeed = MAX(maxSpeed, monsterData._speed);
+		} else {
+			charSpeeds.push_back(0);
+		}
+	}
+
+	_speedTable.clear();
+	for (; maxSpeed >= 0; --maxSpeed) {
+		for (uint idx = 0; idx < charSpeeds.size(); ++idx) {
+			if (charSpeeds[idx] == maxSpeed)
+				_speedTable.push_back(idx);
+		}
+	}
+
+	if (flag) {
+		if (_speedTable[_whosSpeed] != oldSpeed) {
+			for (uint idx = 0; idx < charSpeeds.size(); ++idx) {
+				if (oldSpeed == _speedTable[idx]) {
+					_whosSpeed = idx;
+					break;
+				}
+			}
+		}
+	}
+}
+
+/**
+ * Returns true if all participants in the combat are disabled
+ */
+bool Combat::allHaveGone() const {
+	for (uint idx = 0; idx < _charsGone.size(); ++idx) {
+		if (!_charsGone[idx]) {
+			if (idx >= _combatParty.size()) {
+				return false;
+			} else {
+				Condition condition = _combatParty[idx]->worstCondition();
+				if (condition < PARALYZED || condition == NO_CONDITION)
+					return false;
+			}
+		}
+	}
+
+	return true;
+}
+
+bool Combat::charsCantAct() const {
+	for (uint idx = 0; idx < _combatParty.size(); ++idx) {
+		Condition condition = _combatParty[idx]->worstCondition();
+
+		if (!(condition == ASLEEP || (condition >= PARALYZED && condition != NO_CONDITION)))
+			return false;
+	}
+
+	return true;
+}
+
+Common::String Combat::getMonsterDescriptions() {
+	Map &map = *_vm->_map;
+	Common::String lines[3];
+
+	// Get names of monsters attacking, if any
+	for (int idx = 0; idx < 3; ++idx) {
+		if (_attackMonsters[idx] != -1) {
+			MazeMonster &monster = map._mobData._monsters[_attackMonsters[idx]];
+			MonsterStruct &monsterData = map._monsterData[monster._spriteId];
+
+			Common::String format = "\n\v020\f%2u%s\fd";
+			format.setChar('2' + idx, 3);
+			lines[idx] = Common::String::format(format.c_str(), monsterData._name.c_str());
+		}
+	}
+
+	if (_monsterIndex == 2 && _attackMonsters[2] != -1) {
+		_monster2Attack = _attackMonsters[2];
+	} if (_monsterIndex == 1 && _attackMonsters[1] != -1) {
+		_monster2Attack = _attackMonsters[1];
+	} else {
+		_monster2Attack = _attackMonsters[0];
+		_monsterIndex = 0;
+	}
+
+	return Common::String::format(COMBAT_DETAILS, lines[0].c_str(),
+		lines[1].c_str(), lines[2].c_str());
+}
+
+void Combat::attack(Character &c, int v2) {
+	error("TODO");
+}
+
+void Combat::block() {
+	_charsBlocked[_whosTurn] = true;
+}
+
+bool Combat::castSpell(bool flag) {
+	error("TODO: castSpell");
+}
+
+void Combat::quickFight() {
+	error("TODO: quickFight");
+}
+
+void Combat::giveTreasure() {
+	error("TODO: giveTreasure");
+}
+
+void Combat::run() {
+	error("TODO: run");
+}
+
+
 } // End of namespace Xeen
diff --git a/engines/xeen/combat.h b/engines/xeen/combat.h
index 6b306b4..dee15ed 100644
--- a/engines/xeen/combat.h
+++ b/engines/xeen/combat.h
@@ -57,15 +57,17 @@ private:
 	XeenEngine *_vm;
 public:
 	Common::Array<Character *> _combatParty;
-	Common::Array<int> _charsBlocked;
+	Common::Array<bool> _charsBlocked;
 	Common::Array<int> _charsGone;
 	SpriteResource _powSprites;
 	int _attackMonsters[26];
+	int _monster2Attack;
 	int _charsArray1[12];
 	bool _monPow[12];
 	int _monsterScale[12];
 	int _elemPow[12];
 	int _elemScale[12];
+	Common::Array<int> _speedTable;
 	int _shooting[8];
 	int _globalCombat;
 	int _whosTurn;
@@ -76,6 +78,9 @@ public:
 	int _gmonHit[36];
 	bool _monstersAttacking;
 	int _combatMode;
+	int _monsterIndex;
+	bool _partyRan;
+	int _whosSpeed;
 
 	void monstersAttack();
 
@@ -101,6 +106,28 @@ public:
 	void giveCharDamage(int damage, DamageType attackType, int charIndex);
 
 	void moveMonsters();
+
+	void setupCombatParty();
+
+	void setSpeedTable();
+
+	bool allHaveGone() const;
+
+	bool charsCantAct() const;
+
+	Common::String getMonsterDescriptions();
+
+	void attack(Character &c, int v2);
+
+	void block();
+
+	bool castSpell(bool flag);
+
+	void quickFight();
+
+	void giveTreasure();
+
+	void run();
 };
 
 } // End of namespace Xeen
diff --git a/engines/xeen/dialogs_control_panel.cpp b/engines/xeen/dialogs_control_panel.cpp
new file mode 100644
index 0000000..7e8f89c
--- /dev/null
+++ b/engines/xeen/dialogs_control_panel.cpp
@@ -0,0 +1,42 @@
+/* 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 "xeen/dialogs_control_panel.h"
+#include "xeen/party.h"
+#include "xeen/resources.h"
+#include "xeen/xeen.h"
+
+namespace Xeen {
+
+int ControlPanel::show(XeenEngine *vm) {
+	ControlPanel *dlg = new ControlPanel(vm);
+	int result = dlg->execute();
+	delete dlg;
+
+	return result;
+}
+
+int ControlPanel::execute() {
+	error("TODO: ControlPanel");
+}
+
+} // End of namespace Xeen
diff --git a/engines/xeen/dialogs_control_panel.h b/engines/xeen/dialogs_control_panel.h
new file mode 100644
index 0000000..16c3781
--- /dev/null
+++ b/engines/xeen/dialogs_control_panel.h
@@ -0,0 +1,43 @@
+/* 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_CONTROL_PANEL_H
+#define XEEN_DIALOGS_CONTROL_PANEL_H
+
+#include "xeen/dialogs.h"
+
+namespace Xeen {
+
+class ControlPanel : public ButtonContainer {
+private:
+	XeenEngine *_vm;
+
+	ControlPanel(XeenEngine *vm) : ButtonContainer(), _vm(vm) {}
+
+	int execute();
+public:
+	static int show(XeenEngine *vm);
+};
+
+} // End of namespace Xeen
+
+#endif /* XEEN_DIALOGS_CONTROL_PANEL_H */
diff --git a/engines/xeen/dialogs_fight_options.cpp b/engines/xeen/dialogs_fight_options.cpp
new file mode 100644
index 0000000..c84e754
--- /dev/null
+++ b/engines/xeen/dialogs_fight_options.cpp
@@ -0,0 +1,39 @@
+/* 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 "xeen/dialogs_fight_options.h"
+#include "xeen/resources.h"
+#include "xeen/xeen.h"
+
+namespace Xeen {
+
+void FightOptions::show(XeenEngine *vm) {
+	FightOptions *dlg = new FightOptions(vm);
+	dlg->execute();
+	delete dlg;
+}
+
+void FightOptions::execute() {
+	error("TODO: FightOptions");
+}
+
+} // End of namespace Xeen
diff --git a/engines/xeen/dialogs_fight_options.h b/engines/xeen/dialogs_fight_options.h
new file mode 100644
index 0000000..7b058bc
--- /dev/null
+++ b/engines/xeen/dialogs_fight_options.h
@@ -0,0 +1,43 @@
+/* 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_FIGHT_OPTIONS_H
+#define XEEN_DIALOGS_FIGHT_OPTIONS_H
+
+#include "xeen/dialogs.h"
+
+namespace Xeen {
+
+class FightOptions : public ButtonContainer {
+private:
+	XeenEngine *_vm;
+
+	FightOptions(XeenEngine *vm) : ButtonContainer(), _vm(vm) {}
+
+	void execute();
+public:
+	static void show(XeenEngine *vm);
+};
+
+} // End of namespace Xeen
+
+#endif /* XEEN_DIALOGS_FIGHT_OPTIONS_H */
diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp
index 479795d..a839628 100644
--- a/engines/xeen/interface.cpp
+++ b/engines/xeen/interface.cpp
@@ -21,10 +21,13 @@
  */
 
 #include "xeen/interface.h"
+#include "xeen/dialogs_automap.h"
 #include "xeen/dialogs_char_info.h"
+#include "xeen/dialogs_control_panel.h"
 #include "xeen/dialogs_error.h"
-#include "xeen/dialogs_automap.h"
+#include "xeen/dialogs_fight_options.h"
 #include "xeen/dialogs_info.h"
+#include "xeen/dialogs_items.h"
 #include "xeen/dialogs_query.h"
 #include "xeen/dialogs_quests.h"
 #include "xeen/dialogs_quick_ref.h"
@@ -121,6 +124,9 @@ void PartyDrawer::unhighlightChar() {
 	}
 }
 
+void PartyDrawer::resetHighlight() {
+	_hiliteChar = -1;
+}
 /*------------------------------------------------------------------------*/
 
 Interface::Interface(XeenEngine *vm) : ButtonContainer(), InterfaceMap(vm), 
@@ -320,7 +326,11 @@ void Interface::perform() {
 	case Common::KEYCODE_TAB:
 		// Stop mosters doing any movement
 		_vm->_moveMonsters = false;
-		warning("TODO: showControlPanel");
+		if (ControlPanel::show(_vm) == -1) {
+			_vm->_quitMode = 2;
+		} else {
+			_vm->_moveMonsters = 1;
+		}
 		break;
 
 	case Common::KEYCODE_SPACE:
@@ -1811,9 +1821,13 @@ void Interface::assembleBorder() {
 void Interface::doCombat() {
 	Combat &combat = *_vm->_combat;
 	EventsManager &events = *_vm->_events;
+	Map &map = *_vm->_map;
+	Party &party = *_vm->_party;
 	Screen &screen = *_vm->_screen;
-	bool isDarkCc = _vm->_files->_isDarkCc;
+	Scripts &scripts = *_vm->_scripts;
+	SoundManager &sound = *_vm->_sound;
 	bool upDoorText = _upDoorText;
+	bool reloadMap = false;
 	
 	_upDoorText = false;
 	combat._combatMode = 2;
@@ -1827,9 +1841,345 @@ void Interface::doCombat() {
 	setMainButtons(true);
 	mainIconsPrint();
 
+	combat._combatParty.clear();
+	combat._charsGone.clear();
+	combat._charsBlocked.clear();
+	combat._charsArray1[0] = 0;
+	combat._charsArray1[1] = 0;
+	combat._charsArray1[2] = 0;
+	combat._monstersAttacking = 0;
+	combat._partyRan = false;
+
+	// Set up the combat party
+	combat.setupCombatParty();
+	combat.setSpeedTable();
+	combat._whosSpeed = -1;
+	combat._whosTurn = -1;
+	resetHighlight();
+
+	nextChar();
+
+	if (!party._dead) {
+		combat.setSpeedTable();
+		if (_tillMove) {
+			combat.moveMonsters();
+			draw3d(true);
+		}
+
+		Window &w = screen._windows[2];
+		w.open();
+		bool breakFlag = false;
+
+		while (!_vm->shouldQuit() && !breakFlag) {
+			highlightChar(combat._whosTurn);
+			combat.setSpeedTable();
+
+			// Write out the description of the monsters being battled
+			w.writeString(combat.getMonsterDescriptions());
+			_iconSprites.draw(screen, 32, Common::Point(233, combat._monsterIndex * 10 + 27),
+				0x8010000);
+			w.update();
+
+			// Wait for keypress
+			int index = 0;
+			do {
+				events.updateGameCounter();
+				draw3d(true);
+
+				if (++index == 5 && combat._attackMonsters[0] != -1) {
+					MazeMonster &monster = map._mobData._monsters[combat._monster2Attack];
+					MonsterStruct &monsterData = map._monsterData[monster._spriteId];
+					sound.playFX(monsterData._fx);
+				}
+
+				do {
+					events.pollEventsAndWait();
+					checkEvents(_vm);
+				} while (!_vm->shouldQuit() && events.timeElapsed() < 1 && !_buttonValue);
+			} while (!_vm->shouldQuit() && !_buttonValue);
+			if (_vm->shouldQuit())
+				return;
+
+			switch (_buttonValue) {
+			case Common::KEYCODE_TAB:
+				// Show the control panel
+				if (ControlPanel::show(_vm) == 2) {
+					reloadMap = true;
+					breakFlag = true;
+				} else {
+					highlightChar(combat._whosTurn);
+				}
+				break;
+
+			case Common::KEYCODE_1:
+			case Common::KEYCODE_2:
+			case Common::KEYCODE_3:
+				_buttonValue -= Common::KEYCODE_1;
+				if (combat._attackMonsters[_buttonValue] != -1) {
+					combat._monster2Attack = combat._attackMonsters[_buttonValue];
+					combat._monsterIndex = _buttonValue;
+				}
+				break;
+
+			case Common::KEYCODE_a:
+				// Attack
+				combat.attack(*combat._combatParty[combat._whosTurn], 0);
+				nextChar();
+				break;
+
+			case Common::KEYCODE_b:
+				// Block
+				combat.block();
+				nextChar();
+				break;
+				
+			case Common::KEYCODE_c:
+				// Cast Spell
+				if (combat.castSpell(false)) {
+					nextChar();
+				} else {
+					highlightChar(combat._combatParty[combat._whosTurn]->_rosterId);
+				}
+				break;
+
+			case Common::KEYCODE_f:
+				// Quick Fight
+				combat.quickFight();
+				nextChar();
+				break;
+
+			case Common::KEYCODE_i:
+				// Info dialog
+				InfoDialog::show(_vm);
+				highlightChar(combat._whosTurn);
+				break;
+
+			case Common::KEYCODE_o:
+				// Fight Options
+				FightOptions::show(_vm);
+				highlightChar(combat._whosTurn);
+				break;
+			
+			case Common::KEYCODE_q:
+				// Quick Reference dialog
+				QuickReferenceDialog::show(_vm);
+				highlightChar(combat._whosTurn);
+				break;
+
+			case Common::KEYCODE_r:
+				// Run from combat
+				combat.run();
+				nextChar();
+
+				if (_vm->_mode == MODE_1) {
+					warning("TODO: loss of treasure");
+					party.moveToRunLocation();
+					breakFlag = true;
+				}
+				break;
+
+			case Common::KEYCODE_u: {
+				int whosTurn = combat._whosTurn;
+				ItemsDialog::show(_vm, combat._combatParty[combat._whosTurn], ITEMMODE_COMBAT);
+				if (combat._whosTurn == whosTurn) {
+					highlightChar(combat._whosTurn);
+				} else {
+					combat._whosTurn = whosTurn;
+					nextChar();
+				}
+				break;
+			}
+
+			case Common::KEYCODE_F1:
+			case Common::KEYCODE_F2:
+			case Common::KEYCODE_F3:
+			case Common::KEYCODE_F4:
+			case Common::KEYCODE_F5:
+			case Common::KEYCODE_F6:
+				// Show character info
+				_buttonValue -= Common::KEYCODE_F1;
+				if (_buttonValue < (int)combat._combatParty.size()) {
+					CharacterInfo::show(_vm, _buttonValue);
+				}
+				highlightChar(combat._whosTurn);
+				break;
+
+			case Common::KEYCODE_LEFT:
+			case Common::KEYCODE_RIGHT:
+				// Rotate party direction left or right
+				if (_buttonValue == Common::KEYCODE_LEFT) {
+					party._mazeDirection = (party._mazeDirection == DIR_NORTH) ? 
+						DIR_WEST : (Direction)((int)party._mazeDirection - 1);
+				} else {
+					party._mazeDirection = (party._mazeDirection == DIR_WEST) ?
+					DIR_NORTH : (Direction)((int)party._mazeDirection + 1);
+				}
+
+				_flipSky ^= 1;
+				if (_tillMove)
+					combat.moveMonsters();
+				party._stepped = true;
+				break;
+			}
+
+			// Handling for if the combat turn is complete
+			if (combat.allHaveGone()) {
+				Common::fill(&combat._charsGone[0], &combat._charsGone[combat._charsGone.size()], false);
+				Common::fill(&combat._charsBlocked[0], &combat._charsBlocked[combat._charsBlocked.size()], false);
+				combat.setSpeedTable();
+				combat._whosTurn = -1;
+				combat._whosSpeed = -1;
+				nextChar();
+
+				for (uint idx = 0; idx < map._mobData._monsters.size(); ++idx) {
+					MazeMonster &monster = map._mobData._monsters[idx];
+					if (monster._spriteId == 53) {
+						warning("TODO: Monster 53's HP is altered here?!");
+					}
+				}
+
+				combat.moveMonsters();
+				setIndoorsMonsters();
+				party.changeTime(1);
+			}
+
+			if (combat._attackMonsters[0] == -1 && combat._attackMonsters[1] == -1
+					&& combat._attackMonsters[2] == -1) {
+				party.changeTime(1);
+				draw3d(true);
+
+				if (combat._attackMonsters[0] == -1 && combat._attackMonsters[1] == -1
+						&& combat._attackMonsters[2] == -1)
+					break;
+			}
+
+			party.checkPartyDead();
+			if (party._dead || _vm->_mode != MODE_COMBAT)
+				break;
+		}
+
+		_vm->_mode = MODE_1;
+		if (combat._partyRan && (combat._attackMonsters[0] != -1 ||
+				combat._attackMonsters[1] != -1 || combat._attackMonsters[2] != -1)) {
+			party.checkPartyDead();
+			if (!party._dead) {
+				party.moveToRunLocation();
+
+				for (uint idx = 0; idx < combat._combatParty.size(); ++idx) {
+					Character &c = *combat._combatParty[idx];
+					if (c.isDisabled())
+						c._conditions[DEAD] = 1;
+				}
+			}
+		}
+
+		w.close();
+		events.clearEvents();
+
+		_vm->_mode = MODE_COMBAT;
+		draw3d(true);
+		combat.giveTreasure();
+		_vm->_mode = MODE_1;
+		party._stepped = true;
+		unhighlightChar();
+
+		combat.setupCombatParty();
+		drawParty(true);
+	}
+
+	_iconSprites.load("main.icn");
+	for (int idx = 1; idx < 16; ++idx)
+		_mainList[idx]._sprites = &_iconSprites;
+
+	setMainButtons();
+	mainIconsPrint();
+	combat._monster2Attack = -1;
+
+	if (upDoorText) {
+		map.cellFlagLookup(party._mazePosition);
+		if (map._currentIsEvent)
+			scripts.checkEvents();
+	}
+
+	if (reloadMap) {
+		sound.playFX(51);
+		map._loadDarkSide = _vm->getGameID() != GType_WorldOfXeen;
+		map.load(_vm->getGameID() == GType_WorldOfXeen ? 28 : 29);
+		party._mazeDirection = _vm->getGameID() == GType_WorldOfXeen ?
+			DIR_EAST : DIR_SOUTH;
+	}
 
+	combat._combatMode = 1;
+}
 
-	error("TODO");
+/**
+ * Select next character or monster to be attacking
+ */
+void Interface::nextChar() {
+	Combat &combat = *_vm->_combat;
+	Party &party = *_vm->_party;
+
+	if (combat.allHaveGone())
+		return;
+	if ((combat._attackMonsters[0] == -1 && combat._attackMonsters[1] == -1 &&
+		combat._attackMonsters[2] == -1) || combat._combatParty.size() == 0) {
+		_vm->_mode = MODE_1;
+		return;
+	}
+
+	for (;;) {
+		// Check if party is dead
+		party.checkPartyDead();
+		if (party._dead) {
+			_vm->_mode = MODE_1;
+			break;
+		}
+
+		if (combat._whosTurn < (int)combat._combatParty.size()) {
+			if (!combat.allHaveGone())
+				highlightChar(combat._whosTurn);
+			break;
+		} else {
+			combat.attackMonster(0);
+			if (!party._dead)
+				party.checkPartyDead();
+
+			if (party._dead)
+				break;
+		}
+
+		// Check the combat participants
+		bool resetFlag = false;
+		for (uint idx = 0; idx < combat._speedTable.size(); ++idx) {
+			// Mark the given character as haven taken their turn
+			if (combat._whosTurn != -1) {
+				combat._charsGone[combat._whosTurn] = true;
+			}
+
+			combat._whosSpeed %= combat._speedTable.size();
+			combat._whosTurn = combat._speedTable[combat._whosSpeed];
+
+			if (combat.allHaveGone()) {
+				if (combat.charsCantAct()) {
+					combat.setSpeedTable();
+					combat._whosTurn = -1;
+					combat._whosSpeed = -1;
+
+					combat._charsGone.resize(combat._speedTable.size());
+					Common::fill(&combat._charsGone[0], &combat._charsGone[combat._charsGone.size()], 0);
+					resetFlag = true;
+					break;
+				}
+				return;
+			} else if (combat._whosTurn >= (int)combat._combatParty.size() ||
+					!combat._combatParty[combat._whosTurn]->isDisabledOrDead()) {
+				break;
+			}
+		}
+
+		if (party._dead)
+			break;
+	}
 }
 
 } // End of namespace Xeen
diff --git a/engines/xeen/interface.h b/engines/xeen/interface.h
index 40926ac..80b7980 100644
--- a/engines/xeen/interface.h
+++ b/engines/xeen/interface.h
@@ -54,6 +54,8 @@ public:
 	void highlightChar(int charId);
 
 	void unhighlightChar();
+
+	void resetHighlight();
 };
 
 /**
@@ -103,6 +105,8 @@ private:
 	void shake(int time);
 
 	void drawMiniMap();
+
+	void nextChar();
 public:
 	int _intrIndex1;
 	Common::String _interfaceText;
diff --git a/engines/xeen/map.cpp b/engines/xeen/map.cpp
index 1c7cbd8..01c050a 100644
--- a/engines/xeen/map.cpp
+++ b/engines/xeen/map.cpp
@@ -67,7 +67,7 @@ MonsterStruct::MonsterStruct() {
 	_imageNumber = 0;
 	_loopAnimation = 0;
 	_animationEffect = 0;
-	_field32 = 0;
+	_fx = 0;
 }
 
 MonsterStruct::MonsterStruct(Common::String name, int experience, int hp, int accuracy,
@@ -78,7 +78,7 @@ MonsterStruct::MonsterStruct(Common::String name, int experience, int hp, int ac
 		int poisonResistence, int energyResistence, int magicResistence,
 		int phsyicalResistence, int field29, int gold, int gems, int itemDrop,
 		bool flying, int imageNumber, int loopAnimation, int animationEffect,
-		int field32, Common::String attackVoc):
+		int fx, Common::String attackVoc):
 		_name(name), _experience(experience), _hp(hp), _accuracy(accuracy),
 		_speed(speed), _numberOfAttacks(numberOfAttacks), _hatesClass(hatesClass), 
 		_strikes(strikes), _dmgPerStrike(dmgPerStrike), _attackType(attackType), 
@@ -89,10 +89,9 @@ MonsterStruct::MonsterStruct(Common::String name, int experience, int hp, int ac
 		_magicResistence(magicResistence), _phsyicalResistence(phsyicalResistence), 
 		_field29(field29), _gold(gold), _gems(gems), _itemDrop(itemDrop),
 		_flying(flying), _imageNumber(imageNumber), _loopAnimation(loopAnimation),
-		_animationEffect(animationEffect), _field32(field32), _attackVoc(attackVoc) {
+		_animationEffect(animationEffect), _fx(fx), _attackVoc(attackVoc) {
 }
 
-
 void MonsterStruct::synchronize(Common::SeekableReadStream &s) {
 	char name[16];
 	s.read(name, 16);
@@ -127,7 +126,7 @@ void MonsterStruct::synchronize(Common::SeekableReadStream &s) {
 	_imageNumber = s.readByte();
 	_loopAnimation = s.readByte();
 	_animationEffect = s.readByte();
-	_field32 = s.readByte();
+	_fx = s.readByte();
 	
 	char attackVoc[10];
 	s.read(attackVoc, 9);
diff --git a/engines/xeen/map.h b/engines/xeen/map.h
index 806b408..a43cef5 100644
--- a/engines/xeen/map.h
+++ b/engines/xeen/map.h
@@ -77,7 +77,7 @@ public:
 	int _imageNumber;
 	int _loopAnimation;
 	int _animationEffect;
-	int _field32;
+	int _fx;
 	Common::String _attackVoc;
 public:
 	MonsterStruct();
diff --git a/engines/xeen/module.mk b/engines/xeen/module.mk
index 083abb9..a17311c 100644
--- a/engines/xeen/module.mk
+++ b/engines/xeen/module.mk
@@ -12,9 +12,11 @@ MODULE_OBJS := \
 	automap.o \
 	dialogs_automap.o \
 	dialogs_char_info.o \
+	dialogs_control_panel.o \
 	dialogs_dismiss.o \
 	dialogs_error.o \
 	dialogs_exchange.o \
+	dialogs_fight_options.o \
 	dialogs_options.o \
 	dialogs_info.o \
 	dialogs_input.o \
diff --git a/engines/xeen/party.cpp b/engines/xeen/party.cpp
index 3913ad6..993f156 100644
--- a/engines/xeen/party.cpp
+++ b/engines/xeen/party.cpp
@@ -545,4 +545,11 @@ void Party::checkPartyDead() {
 	_dead = true;
 }
 
+/**
+ * Move party position to the run destination on the current map
+ */
+void Party::moveToRunLocation() {
+	_mazePosition = _vm->_map->mazeData()._runPosition;
+}
+
 } // End of namespace Xeen
diff --git a/engines/xeen/party.h b/engines/xeen/party.h
index 035b344..5d98c55 100644
--- a/engines/xeen/party.h
+++ b/engines/xeen/party.h
@@ -150,6 +150,8 @@ public:
 	void notEnough(int consumableId, int whereId, bool mode, ErrorWaitType wait);
 
 	void checkPartyDead();
+
+	void moveToRunLocation();
 };
 
 } // End of namespace Xeen
diff --git a/engines/xeen/resources.cpp b/engines/xeen/resources.cpp
index 7dca04f..c57b6a7 100644
--- a/engines/xeen/resources.cpp
+++ b/engines/xeen/resources.cpp
@@ -1496,4 +1496,6 @@ const int NEW_CHARACTER_SPELLS[10][4] = {
 	{ 20, 1, -1, -1 }
 };
 
+const char *const COMBAT_DETAILS = "\r\f00\x03c\v000\t000\x02Combat%s%s%s\x1";
+
 } // End of namespace Xeen
diff --git a/engines/xeen/resources.h b/engines/xeen/resources.h
index 53c548f..d690212 100644
--- a/engines/xeen/resources.h
+++ b/engines/xeen/resources.h
@@ -522,6 +522,8 @@ extern const int RACE_ENERGY_RESISTENCES[5];
 extern const int RACE_POISON_RESISTENCES[5];
 extern const int NEW_CHARACTER_SPELLS[10][4];
 
+extern const char *const COMBAT_DETAILS;
+
 } // End of namespace Xeen
 
 #endif	/* XEEN_RESOURCES_H */
diff --git a/engines/xeen/scripts.cpp b/engines/xeen/scripts.cpp
index 086c0d4..37222a3 100644
--- a/engines/xeen/scripts.cpp
+++ b/engines/xeen/scripts.cpp
@@ -378,7 +378,7 @@ void Scripts::cmdTeleport(Common::Array<byte> &params) {
 	}
 
 	if (pt.x == 999) {
-		party._mazePosition = map.mazeData()._runPosition;
+		party.moveToRunLocation();
 	} else {
 		party._mazePosition = pt;
 	}


Commit: 7b3c10b09c76c4a8cbd5dbfabb0ceeaeccbbce26
    https://github.com/scummvm/scummvm/commit/7b3c10b09c76c4a8cbd5dbfabb0ceeaeccbbce26
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-02-17T21:47:01-05:00

Commit Message:
XEEN: Implemented Cast Spell dialog

Changed paths:
    engines/xeen/character.cpp
    engines/xeen/character.h
    engines/xeen/combat.cpp
    engines/xeen/combat.h
    engines/xeen/dialogs_error.cpp
    engines/xeen/dialogs_error.h
    engines/xeen/dialogs_spells.cpp
    engines/xeen/dialogs_spells.h
    engines/xeen/interface.cpp
    engines/xeen/resources.cpp
    engines/xeen/resources.h
    engines/xeen/spells.cpp
    engines/xeen/spells.h



diff --git a/engines/xeen/character.cpp b/engines/xeen/character.cpp
index afe3854..c91b860 100644
--- a/engines/xeen/character.cpp
+++ b/engines/xeen/character.cpp
@@ -707,7 +707,7 @@ void Character::clear() {
 	_lloydMap = 0;
 	_hasSpells = false;
 	_currentSpell = 0;
-	_quickOption = 0;
+	_quickOption = QUICK_ATTACK;
 	_lloydSide = 0;
 	Common::fill(&_conditions[0], &_conditions[16], 0);
 	_townUnknown = 0;
@@ -1822,4 +1822,20 @@ bool Character::hasSpecialItem() const {
 	return false;
 }
 
+int Character::getClassCategory() const {
+	switch (_class) {
+	case CLASS_ARCHER:
+	case CLASS_SORCERER:
+		return 1;
+		
+	case CLASS_DRUID:
+	case CLASS_RANGER:
+		return 2;
+		
+	default:
+		return 0;
+	}
+}
+
+
 } // End of namespace Xeen
diff --git a/engines/xeen/character.h b/engines/xeen/character.h
index be38ba5..bf77bef 100644
--- a/engines/xeen/character.h
+++ b/engines/xeen/character.h
@@ -85,6 +85,10 @@ enum AttributeCategory {
 	ATTR_ARMOR_CLASS = 8, ATTR_THIEVERY  = 9
 };
 
+enum QuickAction {
+	QUICK_ATTACK = 0, QUICK_SPELL = 1, QUICK_BLOCK = 2, QUICK_RUN = 3
+};
+
 class XeenEngine;
 class Character;
 
@@ -235,8 +239,8 @@ public:
 	int _lloydMap;
 	Common::Point _lloydPosition;
 	bool _hasSpells;
-	int _currentSpell;
-	int _quickOption;
+	int8 _currentSpell;
+	QuickAction _quickOption;
 	InventoryItemsGroup _items;
 	WeaponItems _weapons;
 	ArmorItems _armor;
@@ -321,6 +325,8 @@ public:
 	void subtractHitPoints(int amount);
 
 	bool hasSpecialItem() const;
+
+	int getClassCategory() const;
 };
 
 } // End of namespace Xeen
diff --git a/engines/xeen/combat.cpp b/engines/xeen/combat.cpp
index c8f5824..b77ef6e 100644
--- a/engines/xeen/combat.cpp
+++ b/engines/xeen/combat.cpp
@@ -100,6 +100,8 @@ Combat::Combat(XeenEngine *vm): _vm(vm) {
 	_partyRan = false;
 	_monster2Attack = -1;
 	_whosSpeed = 0;
+	_damageType = DT_PHYSICAL;
+	_oldCharacter = nullptr;
 }
 
 void Combat::clear() {
@@ -658,17 +660,21 @@ bool Combat::allHaveGone() const {
 	return true;
 }
 
+/**
+ * Returns true if all the characters of the party are disabled
+ */
 bool Combat::charsCantAct() const {
 	for (uint idx = 0; idx < _combatParty.size(); ++idx) {
-		Condition condition = _combatParty[idx]->worstCondition();
-
-		if (!(condition == ASLEEP || (condition >= PARALYZED && condition != NO_CONDITION)))
+		if (!_combatParty[idx]->isDisabledOrDead())
 			return false;
 	}
 
 	return true;
 }
 
+/**
+ * Return a description of the monsters being faced
+ */
 Common::String Combat::getMonsterDescriptions() {
 	Map &map = *_vm->_map;
 	Common::String lines[3];
@@ -702,25 +708,61 @@ void Combat::attack(Character &c, int v2) {
 	error("TODO");
 }
 
+/**
+ * Flag the currently active character as blocking/defending
+ */
 void Combat::block() {
 	_charsBlocked[_whosTurn] = true;
 }
 
-bool Combat::castSpell(bool flag) {
-	error("TODO: castSpell");
-}
-
+/**
+ * Perform whatever the current combat character's quick action is
+ */
 void Combat::quickFight() {
-	error("TODO: quickFight");
+	Spells &spells = *_vm->_spells;
+	Character *c = _combatParty[_whosTurn];
+	int spellId;
+
+	switch (c->_quickOption) {
+	case QUICK_ATTACK:
+		attack(*c, 0);
+		break;
+	case QUICK_SPELL:
+		if (c->_currentSpell != -1) {
+			spells.castSpell(SPELLS_ALLOWED[c->getClassCategory()][c->_currentSpell]);
+		}
+		break;
+	case QUICK_BLOCK:
+		block();
+		break;
+	case QUICK_RUN:
+		run();
+		break;
+	default:
+		break;
+	}
 }
 
 void Combat::giveTreasure() {
 	error("TODO: giveTreasure");
 }
 
+/**
+ * Current selected character is trying to run away
+ */
 void Combat::run() {
-	error("TODO: run");
-}
+	Map &map = *_vm->_map;
+	SoundManager &sound = *_vm->_sound;
 
+	if (_vm->getRandomNumber(1, 100) < map.mazeData()._difficulties._chance2Run) {
+		// Remove the character from the combat party
+		_combatParty.remove_at(_whosTurn);
+		setSpeedTable();
+		--_whosSpeed;
+		_whosTurn = -1;
+		_partyRan = true;
+		sound.playFX(51);
+	}
+}
 
 } // End of namespace Xeen
diff --git a/engines/xeen/combat.h b/engines/xeen/combat.h
index dee15ed..5ff6beb 100644
--- a/engines/xeen/combat.h
+++ b/engines/xeen/combat.h
@@ -81,6 +81,8 @@ public:
 	int _monsterIndex;
 	bool _partyRan;
 	int _whosSpeed;
+	DamageType _damageType;
+	Character *_oldCharacter;
 
 	void monstersAttack();
 
@@ -121,8 +123,6 @@ public:
 
 	void block();
 
-	bool castSpell(bool flag);
-
 	void quickFight();
 
 	void giveTreasure();
diff --git a/engines/xeen/dialogs_error.cpp b/engines/xeen/dialogs_error.cpp
index db2603a..7f649af 100644
--- a/engines/xeen/dialogs_error.cpp
+++ b/engines/xeen/dialogs_error.cpp
@@ -82,4 +82,34 @@ void ErrorScroll::show(XeenEngine *vm, const Common::String &msg, ErrorWaitType
 	ErrorDialog::show(vm, s, waitType);
 }
 
+/*------------------------------------------------------------------------*/
+
+void CantCast::show(XeenEngine *vm, int spellId, int componentNum) {
+	CantCast *dlg = new CantCast(vm);
+	dlg->execute(spellId, componentNum);
+	delete dlg;
+}
+
+void CantCast::execute(int spellId, int componentNum) {
+	EventsManager &events = *_vm->_events;
+	SoundManager &sound = *_vm->_sound;
+	Window &w = _vm->_screen->_windows[6];
+	Mode oldMode = _vm->_mode;
+	_vm->_mode = MODE_FF;
+
+	sound.playFX(21);
+	w.open();
+	w.writeString(Common::String::format(NOT_ENOUGH_TO_CAST,
+		SPELL_CAST_COMPONENTS[componentNum - 1]));
+	w.update();
+
+	do {
+		events.pollEventsAndWait();
+	} while (!_vm->shouldQuit() && !events.isKeyMousePressed());
+	events.clearEvents();
+
+	w.close();
+	_vm->_mode = oldMode;
+}
+
 } // End of namespace Xeen
diff --git a/engines/xeen/dialogs_error.h b/engines/xeen/dialogs_error.h
index 644b7e3..46efdb1 100644
--- a/engines/xeen/dialogs_error.h
+++ b/engines/xeen/dialogs_error.h
@@ -49,6 +49,17 @@ public:
 		ErrorWaitType waitType = WT_FREEZE_WAIT);
 };
 
+class CantCast: public ButtonContainer {
+private:
+	XeenEngine *_vm;
+
+	CantCast(XeenEngine *vm) : ButtonContainer(), _vm(vm) {}
+
+	void execute(int spellId, int componentNum);
+public:
+	static void show(XeenEngine *vm, int spellId, int componentNum);
+};
+
 } // End of namespace Xeen
 
 #endif /* XEEN_DIALOGS_ERROR_H */
diff --git a/engines/xeen/dialogs_spells.cpp b/engines/xeen/dialogs_spells.cpp
index 0ce0259..fe249d2 100644
--- a/engines/xeen/dialogs_spells.cpp
+++ b/engines/xeen/dialogs_spells.cpp
@@ -413,4 +413,146 @@ const char *SpellsScroll::setSpellText(Character *c, int v2) {
 	return nullptr;
 }
 
+/*------------------------------------------------------------------------*/
+
+int CastSpell::show(XeenEngine *vm, int mode) {
+	Combat &combat = *vm->_combat;
+	Interface &intf = *vm->_interface;
+	Party &party = *vm->_party;
+	Spells &spells = *vm->_spells;
+	int charNum;
+
+	// Get which character is doing the casting
+	if (mode == MODE_COMBAT) {
+		charNum = combat._whosTurn;
+	} else if (spells._lastCaster >= 0 && spells._lastCaster < (int)party._activeParty.size()) {
+		charNum = spells._lastCaster;
+	} else {
+		for (charNum = (int)party._activeParty.size() - 1; charNum >= 0; --charNum) {
+			if (party._activeParty[charNum]._hasSpells) {
+				spells._lastCaster = charNum;
+				break;
+			}
+		}
+	}
+
+	Character &c = party._activeParty[charNum];
+	intf.highlightChar(charNum);
+
+	CastSpell *dlg = new CastSpell(vm);
+	int spellId = dlg->execute(&c, mode);
+	delete dlg;
+
+	return spellId;
+}
+
+int CastSpell::show(XeenEngine *vm, Character *c, int mode) {
+	CastSpell *dlg = new CastSpell(vm);
+	int spellId = dlg->execute(c, mode);
+	delete dlg;
+
+	return spellId;
+}
+
+int CastSpell::execute(Character *c, int mode) {
+	EventsManager &events = *_vm->_events;
+	Interface &intf = *_vm->_interface;
+	Party &party = *_vm->_party;
+	Screen &screen = *_vm->_screen;
+	SoundManager &sound = *_vm->_sound;
+	Spells &spells = *_vm->_spells;
+	Window &w = screen._windows[10];
+	int charNum;
+
+	Mode oldMode = (Mode)mode;
+	int category = c->getClassCategory();
+
+	w.open();
+	loadButtons();
+	drawButtons(&screen);
+
+	int spellId = -1;
+	bool redrawFlag = true;
+	do {
+		if (redrawFlag) {
+			int spellIndex = c->_currentSpell != -1 ? c->_currentSpell : 39;
+			spellId = SPELLS_ALLOWED[category][spellIndex];
+			int gemCost = SPELL_GEM_COST[spellId];
+			int spCost = spells.calcSpellPoints(spellId, c->getCurrentLevel());
+
+			w.writeString(Common::String::format(CAST_SPELL_DETAILS,
+				c->_name.c_str(), spells._spellNames[spellId].c_str(), 
+				spCost, gemCost, c->_currentSp));
+			w.update();
+
+			_vm->_mode = MODE_3;
+			redrawFlag = false;
+		}
+
+		events.updateGameCounter();
+		intf.draw3d(true);
+
+		// Wait for event or time expiry
+		do {
+			events.pollEventsAndWait();
+			checkEvents(_vm);
+		} while (!_vm->shouldQuit() && events.timeElapsed() < 1 && !_buttonValue);
+
+		switch (_buttonValue) {
+		case Common::KEYCODE_F1:
+		case Common::KEYCODE_F2:
+		case Common::KEYCODE_F3:
+		case Common::KEYCODE_F4:
+		case Common::KEYCODE_F5:
+		case Common::KEYCODE_F6:
+			// Only allow changing character if the party is not in combat
+			if (oldMode != MODE_COMBAT) {
+				_vm->_mode = oldMode;
+				_buttonValue -= Common::KEYCODE_F1;
+
+				if (_buttonValue < (int)party._activeParty.size()) {
+					c = &party._activeParty[_buttonValue];
+					intf.highlightChar(_buttonValue);
+					redrawFlag = true;
+					break;
+				}
+			}
+			break;
+
+		case Common::KEYCODE_ESCAPE:
+			spellId = -1;
+			break;
+
+		case Common::KEYCODE_c:
+			// Cast spell - return the selected spell Id to be cast
+			if (c->_currentSpell != -1 && !c->noActions())
+				_buttonValue = Common::KEYCODE_ESCAPE;
+			break;
+
+		case Common::KEYCODE_n:
+			// Select new spell
+			_vm->_mode = oldMode;
+			c = SpellsScroll::show(_vm, c, 1);
+			redrawFlag = true;
+			break;
+
+		default:
+			break;
+		}
+	} while (!_vm->shouldQuit() && _buttonValue != Common::KEYCODE_ESCAPE);
+
+	w.close();
+	intf.unhighlightChar();
+
+	return spellId;
+}
+
+void CastSpell::loadButtons() {
+	_iconSprites.load("cast.icn");
+	addButton(Common::Rect(234, 108, 259, 128), Common::KEYCODE_d, &_iconSprites);
+	addButton(Common::Rect(261, 108, 285, 128), Common::KEYCODE_w, &_iconSprites);
+	addButton(Common::Rect(288, 108, 312, 128), Common::KEYCODE_ESCAPE, &_iconSprites);
+	addPartyButtons(_vm);
+}
+
 } // End of namespace Xeen
diff --git a/engines/xeen/dialogs_spells.h b/engines/xeen/dialogs_spells.h
index 69e339f..d0de44c 100644
--- a/engines/xeen/dialogs_spells.h
+++ b/engines/xeen/dialogs_spells.h
@@ -56,6 +56,21 @@ public:
 	static Character *show(XeenEngine *vm, Character *c, int v2);
 };
 
+class CastSpell : public ButtonContainer {
+private:
+	XeenEngine *_vm;
+	SpriteResource _iconSprites;
+
+	CastSpell(XeenEngine *vm) : ButtonContainer(), _vm(vm) {}
+
+	int execute(Character *c, int mode);
+
+	void loadButtons();
+public:
+	static int show(XeenEngine *vm, int mode);
+	static int show(XeenEngine *vm, Character *c, int mode);
+};
+
 } // End of namespace Xeen
 
 #endif /* XEEN_DIALOGS_SPELLS_H */
diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp
index a839628..3bd3ef1 100644
--- a/engines/xeen/interface.cpp
+++ b/engines/xeen/interface.cpp
@@ -31,6 +31,7 @@
 #include "xeen/dialogs_query.h"
 #include "xeen/dialogs_quests.h"
 #include "xeen/dialogs_quick_ref.h"
+#include "xeen/dialogs_spells.h"
 #include "xeen/resources.h"
 #include "xeen/xeen.h"
 
@@ -267,6 +268,7 @@ void Interface::perform() {
 	Map &map = *_vm->_map;
 	Party &party = *_vm->_party;
 	Scripts &scripts = *_vm->_scripts;
+	Spells &spells = *_vm->_spells;
 	const Common::Rect waitBounds(8, 8, 224, 140);
 
 	events.updateGameCounter();
@@ -517,6 +519,14 @@ void Interface::perform() {
 		}
 		break;
 
+	case Common::KEYCODE_c: {
+		// Cast spell
+		int spellId = CastSpell::show(_vm, _vm->_mode);
+		if (spellId != -1)
+			spells.castSpell(spellId);
+		break;
+	}
+
 	case Common::KEYCODE_i:
 		// Show Info dialog
 		_vm->_moveMonsters = false;
@@ -585,8 +595,10 @@ void Interface::stepTime() {
 }
 
 void Interface::doStepCode() {
+	Combat &combat = *_vm->_combat;
 	Map &map = *_vm->_map;
 	Party &party = *_vm->_party;
+	Scripts &scripts = *_vm->_scripts;
 	int damage = 0;
 
 	party._stepped = true;
@@ -642,8 +654,11 @@ void Interface::doStepCode() {
 			_flipGround = !_flipGround;
 			draw3d(true);
 
-			warning("TODO: apply damage");
+			int oldVal = scripts._v2;
+			scripts._v2 = 0;
+			combat.giveCharDamage(damage, combat._damageType, 0);
 
+			scripts._v2 = oldVal;
 			_flipGround = !_flipGround;
 		} else if (party._partyDead) {
 			draw3d(true);
@@ -1825,6 +1840,7 @@ void Interface::doCombat() {
 	Party &party = *_vm->_party;
 	Screen &screen = *_vm->_screen;
 	Scripts &scripts = *_vm->_scripts;
+	Spells &spells = *_vm->_spells;
 	SoundManager &sound = *_vm->_sound;
 	bool upDoorText = _upDoorText;
 	bool reloadMap = false;
@@ -1933,14 +1949,13 @@ void Interface::doCombat() {
 				nextChar();
 				break;
 				
-			case Common::KEYCODE_c:
-				// Cast Spell
-				if (combat.castSpell(false)) {
-					nextChar();
-				} else {
-					highlightChar(combat._combatParty[combat._whosTurn]->_rosterId);
-				}
+			case Common::KEYCODE_c: {
+				// Cast spell
+				int spellId = CastSpell::show(_vm, _vm->_mode);
+				if (spellId != -1)
+					spells.castSpell(spellId);
 				break;
+			}
 
 			case Common::KEYCODE_f:
 				// Quick Fight
diff --git a/engines/xeen/resources.cpp b/engines/xeen/resources.cpp
index c57b6a7..0fe20fb 100644
--- a/engines/xeen/resources.cpp
+++ b/engines/xeen/resources.cpp
@@ -1498,4 +1498,19 @@ const int NEW_CHARACTER_SPELLS[10][4] = {
 
 const char *const COMBAT_DETAILS = "\r\f00\x03c\v000\t000\x02Combat%s%s%s\x1";
 
+const char *NOT_ENOUGH_TO_CAST = "\x03c\v010Not enough %s to Cast %s";
+const char *SPELL_CAST_COMPONENTS[2] = { "Spell Points", "Gems" };
+
+const char *const CAST_SPELL_DETAILS = 
+	"\r\x2\x3""c\v122\t013\f37C\fdast\t040\f37N\fdew"
+	"\t067ESC\x1\t000\v000\x3""cCast Spell\n"
+	"\n"
+	"%s\x3l\n"
+	"\n"
+	"Spell Ready:\x3""c\n"
+	"\n"
+	"\f09%s\fd\x2\x3l\n"
+	"\v082Cost\x3r\t000%u/%u\x3l\n"
+	"Cur SP\x3r\t000%u\x1";
+
 } // End of namespace Xeen
diff --git a/engines/xeen/resources.h b/engines/xeen/resources.h
index d690212..30eb4f5 100644
--- a/engines/xeen/resources.h
+++ b/engines/xeen/resources.h
@@ -524,6 +524,11 @@ extern const int NEW_CHARACTER_SPELLS[10][4];
 
 extern const char *const COMBAT_DETAILS;
 
+extern const char *NOT_ENOUGH_TO_CAST;
+extern const char *SPELL_CAST_COMPONENTS[2];
+
+extern const char *const CAST_SPELL_DETAILS;
+
 } // End of namespace Xeen
 
 #endif	/* XEEN_RESOURCES_H */
diff --git a/engines/xeen/spells.cpp b/engines/xeen/spells.cpp
index 4943d95..20ba480 100644
--- a/engines/xeen/spells.cpp
+++ b/engines/xeen/spells.cpp
@@ -104,6 +104,37 @@ void Spells::doSpell(int spellId) {
 	(this->*SPELL_LIST[spellId])();
 }
 
+void Spells::castSpell(int spellId) {
+	// TODO
+	error("TODO: castSpell");
+}
+
+/**
+ * Subtract the requirements for a given spell if available, returning
+ * true if there was sufficient
+ */
+int Spells::subSpellCost(Character &c, int spellId) {
+	Party &party = *_vm->_party;
+	int gemCost = SPELL_GEM_COST[spellId];
+	int spCost = SPELL_COSTS[spellId];
+
+	// Negative SP costs indicate it's dependent on the character's level
+	if (spCost <= 0) {
+		spCost = c.getCurrentLevel() * (spCost * -1);
+	}
+
+	if (spCost > c._currentSp)
+		// Not enough SP
+		return 1;
+	if (gemCost > party._gems)
+		// Not enough gems
+		return 2;
+
+	c._currentSp -= spCost;
+	party._gems -= gemCost;
+	return 0;
+}
+
 void Spells::light() { error("TODO: spell"); }
 void Spells::awaken() { error("TODO: spell"); }
 void Spells::magicArrow() { error("TODO: spell"); }
diff --git a/engines/xeen/spells.h b/engines/xeen/spells.h
index 15389be..cffb302 100644
--- a/engines/xeen/spells.h
+++ b/engines/xeen/spells.h
@@ -29,6 +29,7 @@
 namespace Xeen {
 
 class XeenEngine;
+class Character;
 
 #define MAX_SPELLS_PER_CLASS 40
 
@@ -158,6 +159,10 @@ public:
 	int calcSpellPoints(int spellId, int expenseFactor) const;
 
 	void doSpell(int spellId);
+
+	void castSpell(int spellId);
+
+	int subSpellCost(Character &c, int spellId);
 };
 
 } // End of namespace Xeen


Commit: 1d5d98e898cf132a102ef3b1953af31f53da79cc
    https://github.com/scummvm/scummvm/commit/1d5d98e898cf132a102ef3b1953af31f53da79cc
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-02-17T21:57:50-05:00

Commit Message:
XEEN: Fix display of buttons in Cast Spell window

Changed paths:
    engines/xeen/dialogs_spells.cpp



diff --git a/engines/xeen/dialogs_spells.cpp b/engines/xeen/dialogs_spells.cpp
index fe249d2..8688ffe 100644
--- a/engines/xeen/dialogs_spells.cpp
+++ b/engines/xeen/dialogs_spells.cpp
@@ -469,7 +469,6 @@ int CastSpell::execute(Character *c, int mode) {
 
 	w.open();
 	loadButtons();
-	drawButtons(&screen);
 
 	int spellId = -1;
 	bool redrawFlag = true;
@@ -483,6 +482,7 @@ int CastSpell::execute(Character *c, int mode) {
 			w.writeString(Common::String::format(CAST_SPELL_DETAILS,
 				c->_name.c_str(), spells._spellNames[spellId].c_str(), 
 				spCost, gemCost, c->_currentSp));
+			drawButtons(&screen);
 			w.update();
 
 			_vm->_mode = MODE_3;


Commit: 6a7fd1952d62ce0bf44a426aba061ecc85183168
    https://github.com/scummvm/scummvm/commit/6a7fd1952d62ce0bf44a426aba061ecc85183168
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-02-18T08:11:57-05:00

Commit Message:
XEEN: Fixes for display of Spells dialog

Changed paths:
    engines/xeen/dialogs_spells.cpp
    engines/xeen/dialogs_spells.h
    engines/xeen/town.cpp



diff --git a/engines/xeen/dialogs_spells.cpp b/engines/xeen/dialogs_spells.cpp
index 8688ffe..7abca3f 100644
--- a/engines/xeen/dialogs_spells.cpp
+++ b/engines/xeen/dialogs_spells.cpp
@@ -29,15 +29,15 @@
 
 namespace Xeen {
 
-Character *SpellsScroll::show(XeenEngine *vm, Character *c, int v2) {
-	SpellsScroll *dlg = new SpellsScroll(vm);
+Character *SpellsDialog::show(XeenEngine *vm, Character *c, int v2) {
+	SpellsDialog *dlg = new SpellsDialog(vm);
 	Character *result = dlg->execute(c, v2);
 	delete dlg;
 
 	return result;
 }
 
-Character *SpellsScroll::execute(Character *c, int v2) {
+Character *SpellsDialog::execute(Character *c, int isCasting) {
 	EventsManager &events = *_vm->_events;
 	Interface &intf = *_vm->_interface;
 	Party &party = *_vm->_party;
@@ -47,15 +47,15 @@ Character *SpellsScroll::execute(Character *c, int v2) {
 	bool isDarkCc = _vm->_files->_isDarkCc;
 	loadButtons();
 
-	int v2Copy = v2;
-	v2 &= 0x7f;
+	int castingCopy = isCasting;
+	isCasting &= 0x7f;
 	int selection = -1;
 	uint topIndex = 0;
 	int newSelection;
 	screen._windows[25].open();
 
-	while (!_vm->shouldQuit()) {
-		if (!v2) {
+	do {
+		if (!isCasting) {
 			if (!c->guildMember()) {
 				sound.playSample(nullptr, 0);
 				intf._overallFrame = 5;
@@ -73,38 +73,46 @@ Character *SpellsScroll::execute(Character *c, int v2) {
 		}
 
 		_spells.clear();
-		const char *errorMsg = setSpellText(c, v2Copy);
+		const char *errorMsg = setSpellText(c, castingCopy);
 		screen._windows[25].writeString(Common::String::format(SPELLS_FOR,
-			errorMsg == nullptr ? SPELL_LINES_0_TO_9 : nullptr));
+			errorMsg == nullptr ? SPELL_LINES_0_TO_9 : nullptr,
+			c->_name.c_str()));
+
+		// Setup and write out spell list
+		const char *names[10];
+		int colors[10];
+		Common::String emptyStr = "";
+		Common::fill(&names[0], &names[10], emptyStr.c_str());
+		Common::fill(&colors[0], &colors[10], 9);
+
+		for (int idx = 0; idx < 10; ++idx) {
+			if ((topIndex + idx) < _spells.size()) {
+				names[idx] = _spells[topIndex + idx]._name.c_str();
+				colors[idx] = _spells[topIndex + idx]._color;
+			}
+		}
 
 		screen._windows[37].writeString(Common::String::format(SPELLS_DIALOG_SPELLS,
-			(topIndex + 0) < _spells.size() ? _spells[topIndex + 0]._name.c_str() : nullptr,
-			(topIndex + 1) < _spells.size() ? _spells[topIndex + 1]._name.c_str() : nullptr,
-			(topIndex + 2) < _spells.size() ? _spells[topIndex + 2]._name.c_str() : nullptr,
-			(topIndex + 3) < _spells.size() ? _spells[topIndex + 3]._name.c_str() : nullptr,
-			(topIndex + 4) < _spells.size() ? _spells[topIndex + 4]._name.c_str() : nullptr,
-			(topIndex + 5) < _spells.size() ? _spells[topIndex + 5]._name.c_str() : nullptr,
-			(topIndex + 6) < _spells.size() ? _spells[topIndex + 6]._name.c_str() : nullptr,
-			(topIndex + 7) < _spells.size() ? _spells[topIndex + 7]._name.c_str() : nullptr,
-			(topIndex + 8) < _spells.size() ? _spells[topIndex + 8]._name.c_str() : nullptr,
-			(topIndex + 9) < _spells.size() ? _spells[topIndex + 9]._name.c_str() : nullptr,
-			v2 ? SPELL_PTS : GOLD,
-			v2 ? c->_currentSp : party._gold
+			colors[0], names[0], colors[1], names[1], colors[2], names[2],
+			colors[3], names[3], colors[4], names[4], colors[5], names[5],
+			colors[6], names[6], colors[7], names[7], colors[8], names[8],
+			colors[9], names[9],
+			isCasting ? SPELL_PTS : GOLD,
+			isCasting ? c->_currentSp : party._gold
 		));
 
-		_iconSprites.draw(screen, 4, Common::Point(39, 26));
-		_iconSprites.draw(screen, 0, Common::Point(187, 26));
-		_iconSprites.draw(screen, 2, Common::Point(187, 111));
-		if (v2)
-			_iconSprites.draw(screen._windows[25], 5, Common::Point(132, 123));
+		_scrollSprites.draw(screen, 4, Common::Point(39, 26));
+		_scrollSprites.draw(screen, 0, Common::Point(187, 26));
+		_scrollSprites.draw(screen, 2, Common::Point(187, 111));
+		if (isCasting)
+			_scrollSprites.draw(screen._windows[25], 5, Common::Point(132, 123));
 
 		screen._windows[25].update();
 
-		while (!_vm->shouldQuit() && !events.isKeyMousePressed())
+		do {
 			events.pollEventsAndWait();
-		if (_vm->shouldQuit())
-			break;
-		checkEvents(_vm);
+			checkEvents(_vm);
+		} while (!_vm->shouldQuit() && !_buttonValue);
 
 		switch (_buttonValue) {
 		case Common::KEYCODE_F1:
@@ -207,16 +215,16 @@ Character *SpellsScroll::execute(Character *c, int v2) {
 				int spellId = _spells[newSelection]._spellId;
 				int spellIndex = _spells[newSelection]._spellIndex;
 				int spellCost = spells.calcSpellCost(spellId, expenseFactor);
-				if (v2) {
+				if (isCasting) {
 					// TODO: Confirm this refactoring against against original
 					selection = _buttonValue;
 				} else {
 					Common::String spellName = _spells[_buttonValue]._name;
-					Common::String msg = (v2Copy & 0x80) ?
+					Common::String msg = (castingCopy & 0x80) ?
 						Common::String::format(SPELLS_PRESS_A_KEY, msg.c_str()) :
 						Common::String::format(SPELLS_PURCHASE, msg.c_str(), spellCost);
 
-					if (Confirm::show(_vm, msg, v2Copy + 1)) {
+					if (Confirm::show(_vm, msg, castingCopy + 1)) {
 						if (party.subtract(0, spellCost, 0, WT_FREEZE_WAIT)) {
 							++c->_spells[spellIndex];
 							sound.playSample(nullptr, 0);
@@ -253,37 +261,38 @@ Character *SpellsScroll::execute(Character *c, int v2) {
 				++topIndex;
 			break;
 		}
-	}
+	} while (!_vm->shouldQuit() && _buttonValue != Common::KEYCODE_ESCAPE);
 
 	screen._windows[25].close();
-	if (v2 && selection != -1)
+	if (isCasting && selection != -1)
 		c->_currentSpell = _spells[selection]._spellIndex;
 
 	return c;
 }
 
-void SpellsScroll::loadButtons() {
+void SpellsDialog::loadButtons() {
 	_iconSprites.load("main.icn");
 	_scrollSprites.load("scroll.icn");
 	addButton(Common::Rect(187, 26, 198, 36), Common::KEYCODE_UP, &_scrollSprites, true);
 	addButton(Common::Rect(187, 111, 198, 121), Common::KEYCODE_DOWN, &_scrollSprites, true);
-	addButton(Common::Rect(40, 28, 187, 36), Common::KEYCODE_1, &_scrollSprites, false);
-	addButton(Common::Rect(40, 37, 187, 45), Common::KEYCODE_2, &_scrollSprites, false);
-	addButton(Common::Rect(40, 46, 187, 54), Common::KEYCODE_3, &_scrollSprites, false);
-	addButton(Common::Rect(40, 55, 187, 63), Common::KEYCODE_4, &_scrollSprites, false);
-	addButton(Common::Rect(40, 64, 187, 72), Common::KEYCODE_5, &_scrollSprites, false);
-	addButton(Common::Rect(40, 73, 187, 81), Common::KEYCODE_6, &_scrollSprites, false);
-	addButton(Common::Rect(40, 82, 187, 90), Common::KEYCODE_7, &_scrollSprites, false);
-	addButton(Common::Rect(40, 91, 187, 99), Common::KEYCODE_8, &_scrollSprites, false);
-	addButton(Common::Rect(40, 100, 187, 108), Common::KEYCODE_9, &_scrollSprites, false);
-	addButton(Common::Rect(40, 109, 187, 117), Common::KEYCODE_0, &_scrollSprites, false);
-	addButton(Common::Rect(174, 123, 198, 133), Common::KEYCODE_ESCAPE, &_scrollSprites, false);
-	addButton(Common::Rect(187, 35, 198, 73), Common::KEYCODE_PAGEUP, &_scrollSprites, false);
-	addButton(Common::Rect(187, 74, 198, 112), Common::KEYCODE_PAGEDOWN, &_scrollSprites, false);
-	addButton(Common::Rect(132, 123, 168, 133), Common::KEYCODE_s, &_scrollSprites, false);
+	addButton(Common::Rect(40, 28, 187, 36), Common::KEYCODE_1);
+	addButton(Common::Rect(40, 37, 187, 45), Common::KEYCODE_2);
+	addButton(Common::Rect(40, 46, 187, 54), Common::KEYCODE_3);
+	addButton(Common::Rect(40, 55, 187, 63), Common::KEYCODE_4);
+	addButton(Common::Rect(40, 64, 187, 72), Common::KEYCODE_5);
+	addButton(Common::Rect(40, 73, 187, 81), Common::KEYCODE_6);
+	addButton(Common::Rect(40, 82, 187, 90), Common::KEYCODE_7);
+	addButton(Common::Rect(40, 91, 187, 99), Common::KEYCODE_8);
+	addButton(Common::Rect(40, 100, 187, 108), Common::KEYCODE_9);
+	addButton(Common::Rect(40, 109, 187, 117), Common::KEYCODE_0);
+	addButton(Common::Rect(174, 123, 198, 133), Common::KEYCODE_ESCAPE);
+	addButton(Common::Rect(187, 35, 198, 73), Common::KEYCODE_PAGEUP);
+	addButton(Common::Rect(187, 74, 198, 112), Common::KEYCODE_PAGEDOWN);
+	addButton(Common::Rect(132, 123, 168, 133), Common::KEYCODE_s);
+	addPartyButtons(_vm);
 }
 
-const char *SpellsScroll::setSpellText(Character *c, int v2) {
+const char *SpellsDialog::setSpellText(Character *c, int v2) {
 	Party &party = *_vm->_party;
 	Spells &spells = *_vm->_spells;
 	bool isDarkCc = _vm->_files->_isDarkCc;
@@ -459,10 +468,8 @@ int CastSpell::execute(Character *c, int mode) {
 	Interface &intf = *_vm->_interface;
 	Party &party = *_vm->_party;
 	Screen &screen = *_vm->_screen;
-	SoundManager &sound = *_vm->_sound;
 	Spells &spells = *_vm->_spells;
 	Window &w = screen._windows[10];
-	int charNum;
 
 	Mode oldMode = (Mode)mode;
 	int category = c->getClassCategory();
@@ -532,7 +539,7 @@ int CastSpell::execute(Character *c, int mode) {
 		case Common::KEYCODE_n:
 			// Select new spell
 			_vm->_mode = oldMode;
-			c = SpellsScroll::show(_vm, c, 1);
+			c = SpellsDialog::show(_vm, c, 1);
 			redrawFlag = true;
 			break;
 
@@ -549,8 +556,8 @@ int CastSpell::execute(Character *c, int mode) {
 
 void CastSpell::loadButtons() {
 	_iconSprites.load("cast.icn");
-	addButton(Common::Rect(234, 108, 259, 128), Common::KEYCODE_d, &_iconSprites);
-	addButton(Common::Rect(261, 108, 285, 128), Common::KEYCODE_w, &_iconSprites);
+	addButton(Common::Rect(234, 108, 259, 128), Common::KEYCODE_c, &_iconSprites);
+	addButton(Common::Rect(261, 108, 285, 128), Common::KEYCODE_n, &_iconSprites);
 	addButton(Common::Rect(288, 108, 312, 128), Common::KEYCODE_ESCAPE, &_iconSprites);
 	addPartyButtons(_vm);
 }
diff --git a/engines/xeen/dialogs_spells.h b/engines/xeen/dialogs_spells.h
index d0de44c..c27567c 100644
--- a/engines/xeen/dialogs_spells.h
+++ b/engines/xeen/dialogs_spells.h
@@ -33,19 +33,20 @@ struct SpellEntry {
 	Common::String _name;
 	int _spellIndex;
 	int _spellId;
+	int _color;
 
 	SpellEntry(const Common::String &name, int spellIndex, int spellId) :
-		_name(name), _spellIndex(spellIndex), _spellId(spellId) {}
+		_name(name), _spellIndex(spellIndex), _spellId(spellId), _color(9) {}
 };
 
-class SpellsScroll : public ButtonContainer {
+class SpellsDialog : public ButtonContainer {
 private:
 	XeenEngine *_vm;
 	SpriteResource _iconSprites;
 	SpriteResource _scrollSprites;
 	Common::Array<SpellEntry> _spells;
 
-	SpellsScroll(XeenEngine *vm) : ButtonContainer(), _vm(vm) {}
+	SpellsDialog(XeenEngine *vm) : ButtonContainer(), _vm(vm) {}
 
 	Character *execute(Character *c, int v2);
 
@@ -53,7 +54,7 @@ private:
 
 	const char *setSpellText(Character *c, int v2);
 public:
-	static Character *show(XeenEngine *vm, Character *c, int v2);
+	static Character *show(XeenEngine *vm, Character *c, int isCasting);
 };
 
 class CastSpell : public ButtonContainer {
diff --git a/engines/xeen/town.cpp b/engines/xeen/town.cpp
index f68a554..b850439 100644
--- a/engines/xeen/town.cpp
+++ b/engines/xeen/town.cpp
@@ -567,12 +567,12 @@ Character *Town::doGuildOptions(Character *c) {
 		}
 	} else if (_buttonValue == Common::KEYCODE_s) {
 		if (c->guildMember())
-			c = SpellsScroll::show(_vm, c, 0x80);
+			c = SpellsDialog::show(_vm, c, 0x80);
 		_buttonValue = 0;
 	} else if (_buttonValue == Common::KEYCODE_c) {
 		if (!c->noActions()) {
 			if (c->guildMember())
-				c = SpellsScroll::show(_vm, c, 0);
+				c = SpellsDialog::show(_vm, c, 0);
 			_buttonValue = 0;
 		}
 	}


Commit: 0f78fb9373b8c4befd727e9e56faf5d30ac59cff
    https://github.com/scummvm/scummvm/commit/0f78fb9373b8c4befd727e9e56faf5d30ac59cff
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-02-18T20:35:32-05:00

Commit Message:
XEEN: Implement extra code for passing active character to castSpell

Changed paths:
    engines/xeen/combat.cpp
    engines/xeen/dialogs_items.cpp
    engines/xeen/dialogs_spells.cpp
    engines/xeen/dialogs_spells.h
    engines/xeen/interface.cpp
    engines/xeen/spells.cpp
    engines/xeen/spells.h



diff --git a/engines/xeen/combat.cpp b/engines/xeen/combat.cpp
index b77ef6e..7ed3499 100644
--- a/engines/xeen/combat.cpp
+++ b/engines/xeen/combat.cpp
@@ -721,7 +721,6 @@ void Combat::block() {
 void Combat::quickFight() {
 	Spells &spells = *_vm->_spells;
 	Character *c = _combatParty[_whosTurn];
-	int spellId;
 
 	switch (c->_quickOption) {
 	case QUICK_ATTACK:
@@ -729,7 +728,7 @@ void Combat::quickFight() {
 		break;
 	case QUICK_SPELL:
 		if (c->_currentSpell != -1) {
-			spells.castSpell(SPELLS_ALLOWED[c->getClassCategory()][c->_currentSpell]);
+			spells.castSpell(c, SPELLS_ALLOWED[c->getClassCategory()][c->_currentSpell]);
 		}
 		break;
 	case QUICK_BLOCK:
diff --git a/engines/xeen/dialogs_items.cpp b/engines/xeen/dialogs_items.cpp
index ec82afb..f8131db 100644
--- a/engines/xeen/dialogs_items.cpp
+++ b/engines/xeen/dialogs_items.cpp
@@ -889,7 +889,7 @@ int ItemsDialog::doItemOptions(Character &c, int actionIndex, int itemIndex, Ite
 							screen._windows[30].close();
 							screen._windows[29].close();
 							screen._windows[24].close();
-							spells.doSpell(i._id);
+							spells.castItemSpell(i._id);
 
 							if (!charges) {
 								// Ran out of charges, so make item disappear
diff --git a/engines/xeen/dialogs_spells.cpp b/engines/xeen/dialogs_spells.cpp
index 7abca3f..2f4026b 100644
--- a/engines/xeen/dialogs_spells.cpp
+++ b/engines/xeen/dialogs_spells.cpp
@@ -29,9 +29,9 @@
 
 namespace Xeen {
 
-Character *SpellsDialog::show(XeenEngine *vm, Character *c, int v2) {
+Character *SpellsDialog::show(XeenEngine *vm, Character *c, int isCasting) {
 	SpellsDialog *dlg = new SpellsDialog(vm);
-	Character *result = dlg->execute(c, v2);
+	Character *result = dlg->execute(c, isCasting);
 	delete dlg;
 
 	return result;
@@ -116,6 +116,10 @@ Character *SpellsDialog::execute(Character *c, int isCasting) {
 
 		switch (_buttonValue) {
 		case Common::KEYCODE_F1:
+		case Common::KEYCODE_F2:
+		case Common::KEYCODE_F3:
+		case Common::KEYCODE_F4:
+		case Common::KEYCODE_F5:
 		case Common::KEYCODE_F6:
 			if (_vm->_mode != MODE_COMBAT) {
 				_buttonValue -= Common::KEYCODE_F1;
@@ -143,7 +147,7 @@ Character *SpellsDialog::execute(Character *c, int isCasting) {
 							break;
 						}
 
-						int spellIndex = (c->_currentSp == -1) ? 39 : c->_currentSpell;
+						int spellIndex = (c->_currentSpell == -1) ? 39 : c->_currentSpell;
 						int spellId = SPELLS_ALLOWED[category][spellIndex];
 						screen._windows[10].writeString(Common::String::format(SPELL_DETAILS,
 							spells._spellNames[spellId].c_str(),
@@ -445,17 +449,17 @@ int CastSpell::show(XeenEngine *vm, int mode) {
 		}
 	}
 
-	Character &c = party._activeParty[charNum];
+	Character *c = &party._activeParty[charNum];
 	intf.highlightChar(charNum);
 
 	CastSpell *dlg = new CastSpell(vm);
-	int spellId = dlg->execute(&c, mode);
+	int spellId = dlg->execute(c, mode);
 	delete dlg;
 
 	return spellId;
 }
 
-int CastSpell::show(XeenEngine *vm, Character *c, int mode) {
+int CastSpell::show(XeenEngine *vm, Character *&c, int mode) {
 	CastSpell *dlg = new CastSpell(vm);
 	int spellId = dlg->execute(c, mode);
 	delete dlg;
@@ -463,7 +467,7 @@ int CastSpell::show(XeenEngine *vm, Character *c, int mode) {
 	return spellId;
 }
 
-int CastSpell::execute(Character *c, int mode) {
+int CastSpell::execute(Character *&c, int mode) {
 	EventsManager &events = *_vm->_events;
 	Interface &intf = *_vm->_interface;
 	Party &party = *_vm->_party;
diff --git a/engines/xeen/dialogs_spells.h b/engines/xeen/dialogs_spells.h
index c27567c..f091da6 100644
--- a/engines/xeen/dialogs_spells.h
+++ b/engines/xeen/dialogs_spells.h
@@ -64,12 +64,12 @@ private:
 
 	CastSpell(XeenEngine *vm) : ButtonContainer(), _vm(vm) {}
 
-	int execute(Character *c, int mode);
+	int execute(Character *&c, int mode);
 
 	void loadButtons();
 public:
 	static int show(XeenEngine *vm, int mode);
-	static int show(XeenEngine *vm, Character *c, int mode);
+	static int show(XeenEngine *vm, Character *&c, int mode);
 };
 
 } // End of namespace Xeen
diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp
index 3bd3ef1..7efc7a7 100644
--- a/engines/xeen/interface.cpp
+++ b/engines/xeen/interface.cpp
@@ -521,9 +521,25 @@ void Interface::perform() {
 
 	case Common::KEYCODE_c: {
 		// Cast spell
-		int spellId = CastSpell::show(_vm, _vm->_mode);
-		if (spellId != -1)
-			spells.castSpell(spellId);
+		if (_tillMove) {
+			combat.moveMonsters();
+			draw3d(true);
+		}
+
+		int result = 0;
+		do {
+			Character *c = nullptr;
+			int spellId = CastSpell::show(_vm, c, _vm->_mode);
+			if (spellId == -1 || c == nullptr)
+				break;
+
+			result = spells.castSpell(c, spellId);
+		} while (result != -1);
+
+		if (result == 1) {
+			chargeStep();
+			doStepCode();
+		}
 		break;
 	}
 
@@ -1952,8 +1968,10 @@ void Interface::doCombat() {
 			case Common::KEYCODE_c: {
 				// Cast spell
 				int spellId = CastSpell::show(_vm, _vm->_mode);
-				if (spellId != -1)
-					spells.castSpell(spellId);
+				if (spellId != -1) {
+					Character *c = combat._combatParty[combat._whosTurn];
+					spells.castSpell(c, spellId);
+				}
 				break;
 			}
 
diff --git a/engines/xeen/spells.cpp b/engines/xeen/spells.cpp
index 20ba480..3b753bc 100644
--- a/engines/xeen/spells.cpp
+++ b/engines/xeen/spells.cpp
@@ -53,7 +53,7 @@ int Spells::calcSpellPoints(int spellId, int expenseFactor) const {
 
 typedef void(Spells::*SpellMethodPtr)();
 
-void Spells::doSpell(int spellId) {
+void Spells::executeSpell(int spellId) {
 	static const SpellMethodPtr SPELL_LIST[73] = {
 		&Spells::light, &Spells::awaken, &Spells::magicArrow, &Spells::firstAid,
 		&Spells::flyingFist, &Spells::energyBlast, &Spells::sleep,
@@ -92,6 +92,10 @@ void Spells::doSpell(int spellId) {
 		&Spells::implosion, &Spells::starBurst, &Spells::divineIntervention
 	};
 
+	(this->*SPELL_LIST[spellId])();
+}
+
+void Spells::castItemSpell(int spellId) {
 	if (_vm->_mode == MODE_COMBAT) {
 		if (spellId == 15 || spellId == 20 || spellId == 27 || spellId == 41
 				|| spellId == 47 || spellId == 54 || spellId == 57) {
@@ -101,12 +105,47 @@ void Spells::doSpell(int spellId) {
 		}
 	}
 
-	(this->*SPELL_LIST[spellId])();
+	executeSpell(spellId);
 }
 
-void Spells::castSpell(int spellId) {
-	// TODO
-	error("TODO: castSpell");
+/**
+ * Cast a given spell
+ */
+int Spells::castSpell(Character *c, int spellId) {
+	Combat &combat = *_vm->_combat;
+	Interface &intf = *_vm->_interface;
+	int oldTillMove = intf._tillMove;
+	int result = 1;
+	combat._oldCharacter = c;
+	
+	// Try and subtract the SP and gem requirements for the spell
+	int resultError = subSpellCost(*c, spellId);
+	if (resultError) {
+		CantCast::show(_vm, spellId, resultError);
+		result = -1;
+	} else {
+		// Some spells have special handling
+		switch (spellId) {
+		case 19:
+			// Enchant item
+			if (_vm->_mode != MODE_COMBAT) {
+				enchantItem();
+			} else {
+				// Return the spell costs and flag that another spell can be selected
+				addSpellCost(*c, spellId);
+				result = -1;
+			}
+			break;
+
+		default:
+			executeSpell(spellId);
+			break;
+		}
+	}
+
+	_vm->_moveMonsters = 1;
+	intf._tillMove = oldTillMove;
+	return result;
 }
 
 /**
@@ -126,7 +165,7 @@ int Spells::subSpellCost(Character &c, int spellId) {
 	if (spCost > c._currentSp)
 		// Not enough SP
 		return 1;
-	if (gemCost > party._gems)
+	if (gemCost > (int)party._gems)
 		// Not enough gems
 		return 2;
 
@@ -135,6 +174,23 @@ int Spells::subSpellCost(Character &c, int spellId) {
 	return 0;
 }
 
+/**
+ * Add the SP and gem requirements for a given spell to the given 
+ * character and party
+ */
+void Spells::addSpellCost(Character &c, int spellId) {
+	Party &party = *_vm->_party;
+	int gemCost = SPELL_GEM_COST[spellId];
+	int spCost = SPELL_COSTS[spellId];
+
+	if (spCost < 1)
+		spCost *= -1 * c.getCurrentLevel();
+
+	c._currentSp += spCost;
+	party._gems += gemCost;
+}
+
+
 void Spells::light() { error("TODO: spell"); }
 void Spells::awaken() { error("TODO: spell"); }
 void Spells::magicArrow() { error("TODO: spell"); }
diff --git a/engines/xeen/spells.h b/engines/xeen/spells.h
index cffb302..af52511 100644
--- a/engines/xeen/spells.h
+++ b/engines/xeen/spells.h
@@ -67,6 +67,8 @@ private:
 
 	void load();
 
+	void executeSpell(int spellId);
+
 	// Spell list
 	void light();
 	void awaken();
@@ -158,11 +160,13 @@ public:
 
 	int calcSpellPoints(int spellId, int expenseFactor) const;
 
-	void doSpell(int spellId);
+	void castItemSpell(int spellId);
 
-	void castSpell(int spellId);
+	int castSpell(Character *c, int spellId);
 
 	int subSpellCost(Character &c, int spellId);
+
+	void addSpellCost(Character &c, int spellId);
 };
 
 } // End of namespace Xeen


Commit: da368f5e008795168daa98dace83d6510100d8bc
    https://github.com/scummvm/scummvm/commit/da368f5e008795168daa98dace83d6510100d8bc
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-02-18T21:17:55-05:00

Commit Message:
XEEN: Add special case spell handling during combat

Changed paths:
    engines/xeen/interface.cpp
    engines/xeen/spells.cpp



diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp
index 7efc7a7..0c7f15d 100644
--- a/engines/xeen/interface.cpp
+++ b/engines/xeen/interface.cpp
@@ -527,8 +527,10 @@ void Interface::perform() {
 		}
 
 		int result = 0;
+		Character *c = &party._activeParty[(spells._lastCaster < 0 ||
+			spells._lastCaster >= (int)party._activeParty.size()) ?
+			(int)party._activeParty.size() - 1 : spells._lastCaster];
 		do {
-			Character *c = nullptr;
 			int spellId = CastSpell::show(_vm, c, _vm->_mode);
 			if (spellId == -1 || c == nullptr)
 				break;
diff --git a/engines/xeen/spells.cpp b/engines/xeen/spells.cpp
index 3b753bc..d2a2af3 100644
--- a/engines/xeen/spells.cpp
+++ b/engines/xeen/spells.cpp
@@ -126,13 +126,21 @@ int Spells::castSpell(Character *c, int spellId) {
 	} else {
 		// Some spells have special handling
 		switch (spellId) {
-		case 19:
-			// Enchant item
+		case 19:	// Enchant item
+		case 21:	// Etherialize
+		case 40:	// Jump
+		case 44:	// Lloyd's Beacon
+		case 66:	// Super Shelter
+		case 69:	// Teleport
+		case 71:	// Town Portal
+		case 75:	// Wizard Eye
 			if (_vm->_mode != MODE_COMBAT) {
-				enchantItem();
+				executeSpell(spellId);
 			} else {
 				// Return the spell costs and flag that another spell can be selected
 				addSpellCost(*c, spellId);
+				ErrorDialog::show(_vm, Common::String::format(CANT_CAST_WHILE_ENGAGED,
+					_spellNames[spellId]));
 				result = -1;
 			}
 			break;


Commit: aa89e602a2d261a24861bf65877bba3fab647409
    https://github.com/scummvm/scummvm/commit/aa89e602a2d261a24861bf65877bba3fab647409
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-02-18T21:42:57-05:00

Commit Message:
XEEN: Spell dialogs fixes for non-casters

Changed paths:
    engines/xeen/dialogs_spells.cpp



diff --git a/engines/xeen/dialogs_spells.cpp b/engines/xeen/dialogs_spells.cpp
index 2f4026b..dbe48c1 100644
--- a/engines/xeen/dialogs_spells.cpp
+++ b/engines/xeen/dialogs_spells.cpp
@@ -75,7 +75,7 @@ Character *SpellsDialog::execute(Character *c, int isCasting) {
 		_spells.clear();
 		const char *errorMsg = setSpellText(c, castingCopy);
 		screen._windows[25].writeString(Common::String::format(SPELLS_FOR,
-			errorMsg == nullptr ? SPELL_LINES_0_TO_9 : nullptr,
+			errorMsg == nullptr ? SPELL_LINES_0_TO_9 : "",
 			c->_name.c_str()));
 
 		// Setup and write out spell list
@@ -92,6 +92,9 @@ Character *SpellsDialog::execute(Character *c, int isCasting) {
 			}
 		}
 
+		if (_spells.size() == 0)
+			names[0] = errorMsg;
+
 		screen._windows[37].writeString(Common::String::format(SPELLS_DIALOG_SPELLS,
 			colors[0], names[0], colors[1], names[1], colors[2], names[2],
 			colors[3], names[3], colors[4], names[4], colors[5], names[5],
@@ -150,7 +153,7 @@ Character *SpellsDialog::execute(Character *c, int isCasting) {
 						int spellIndex = (c->_currentSpell == -1) ? 39 : c->_currentSpell;
 						int spellId = SPELLS_ALLOWED[category][spellIndex];
 						screen._windows[10].writeString(Common::String::format(SPELL_DETAILS,
-							spells._spellNames[spellId].c_str(),
+							c->_name.c_str(), spells._spellNames[spellId].c_str(),
 							spells.calcSpellPoints(spellId, c->getCurrentLevel()),
 							SPELL_GEM_COST[spellId], c->_currentSp));
 					}
@@ -555,6 +558,9 @@ int CastSpell::execute(Character *&c, int mode) {
 	w.close();
 	intf.unhighlightChar();
 
+	if (_vm->shouldQuit())
+		spellId = -1;
+
 	return spellId;
 }
 


Commit: cd5bc0ec7ec7652a39d550aea4f387eec45fa382
    https://github.com/scummvm/scummvm/commit/cd5bc0ec7ec7652a39d550aea4f387eec45fa382
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-02-18T22:05:25-05:00

Commit Message:
XEEN: Simplify use of addButton when setting up button lists

Changed paths:
    engines/xeen/dialogs.cpp
    engines/xeen/dialogs.h
    engines/xeen/dialogs_dismiss.cpp
    engines/xeen/dialogs_exchange.cpp
    engines/xeen/dialogs_items.cpp
    engines/xeen/dialogs_options.cpp
    engines/xeen/dialogs_party.cpp
    engines/xeen/dialogs_spells.cpp
    engines/xeen/interface.cpp
    engines/xeen/resources.cpp
    engines/xeen/resources.h
    engines/xeen/town.cpp



diff --git a/engines/xeen/dialogs.cpp b/engines/xeen/dialogs.cpp
index 8bb0af0..116054d 100644
--- a/engines/xeen/dialogs.cpp
+++ b/engines/xeen/dialogs.cpp
@@ -47,14 +47,19 @@ void ButtonContainer::restoreButtons() {
 	_buttons = _savedButtons.pop();
 }
 
-void ButtonContainer::addButton(const Common::Rect &bounds, int val, SpriteResource *sprites, bool draw) {
-	_buttons.push_back(UIButton(bounds, val, sprites, draw));
+void ButtonContainer::addButton(const Common::Rect &bounds, int val, 
+		SpriteResource *sprites) {
+	_buttons.push_back(UIButton(bounds, val, sprites, true));
+}
+
+void ButtonContainer::addButton(const Common::Rect &bounds, int val) {
+	_buttons.push_back(UIButton(bounds, val, nullptr, false));
 }
 
 void ButtonContainer::addPartyButtons(XeenEngine *vm) {
 	for (uint idx = 0; idx < MAX_ACTIVE_PARTY; ++idx) {
 		addButton(Common::Rect(CHAR_FACES_X[idx], 150, CHAR_FACES_X[idx] + 32, 182),
-			Common::KEYCODE_F1 + idx, nullptr, false);
+			Common::KEYCODE_F1 + idx);
 	}
 }
 
diff --git a/engines/xeen/dialogs.h b/engines/xeen/dialogs.h
index 02e945b..e2d8bc9 100644
--- a/engines/xeen/dialogs.h
+++ b/engines/xeen/dialogs.h
@@ -66,8 +66,9 @@ public:
 
 	void restoreButtons();
 
-	void addButton(const Common::Rect &bounds, int val, 
-		SpriteResource *sprites = nullptr, bool draw = true);
+	void addButton(const Common::Rect &bounds, int val, SpriteResource *sprites);
+
+	void addButton(const Common::Rect &bounds, int val);
 
 	void addPartyButtons(XeenEngine *vm);
 };
diff --git a/engines/xeen/dialogs_dismiss.cpp b/engines/xeen/dialogs_dismiss.cpp
index 0c28aff..1317d84 100644
--- a/engines/xeen/dialogs_dismiss.cpp
+++ b/engines/xeen/dialogs_dismiss.cpp
@@ -88,10 +88,10 @@ void Dismiss::execute() {
 void Dismiss::loadButtons() {
 	_iconSprites.load("esc.icn");
 	addButton(Common::Rect(225, 120, 249, 140), Common::KEYCODE_ESCAPE, &_iconSprites);
-	addButton(Common::Rect(16, 16, 48, 48), Common::KEYCODE_1, &_iconSprites, false);
-	addButton(Common::Rect(117, 16, 149, 48), Common::KEYCODE_2, &_iconSprites, false);
-	addButton(Common::Rect(16, 59, 48, 91), Common::KEYCODE_3, &_iconSprites, false);
-	addButton(Common::Rect(117, 59, 149, 91), Common::KEYCODE_4, &_iconSprites, false);
+	addButton(Common::Rect(16, 16, 48, 48), Common::KEYCODE_1);
+	addButton(Common::Rect(117, 16, 149, 48), Common::KEYCODE_2);
+	addButton(Common::Rect(16, 59, 48, 91), Common::KEYCODE_3);
+	addButton(Common::Rect(117, 59, 149, 91), Common::KEYCODE_4);
 }
 
 } // End of namespace Xeen
diff --git a/engines/xeen/dialogs_exchange.cpp b/engines/xeen/dialogs_exchange.cpp
index 0b1e538..37da4e0 100644
--- a/engines/xeen/dialogs_exchange.cpp
+++ b/engines/xeen/dialogs_exchange.cpp
@@ -70,11 +70,11 @@ void ExchangeDialog::execute(Character *&c, int &charIndex) {
 
 void ExchangeDialog::loadButtons() {
 	_iconSprites.load("esc.icn");
-	addButton(Common::Rect(225, 120, 249, 245), Common::KEYCODE_ESCAPE, &_iconSprites, true);
-	addButton(Common::Rect(16, 16, 48, 48), Common::KEYCODE_1, &_iconSprites, false);
-	addButton(Common::Rect(117, 16, 149, 48), Common::KEYCODE_2, &_iconSprites, false);
-	addButton(Common::Rect(16, 59, 48, 91), Common::KEYCODE_3, &_iconSprites, false);
-	addButton(Common::Rect(117, 59, 149, 91), Common::KEYCODE_4, &_iconSprites, false);
+	addButton(Common::Rect(225, 120, 249, 245), Common::KEYCODE_ESCAPE, &_iconSprites);
+	addButton(Common::Rect(16, 16, 48, 48), Common::KEYCODE_1);
+	addButton(Common::Rect(117, 16, 149, 48), Common::KEYCODE_2);
+	addButton(Common::Rect(16, 59, 48, 91), Common::KEYCODE_3);
+	addButton(Common::Rect(117, 59, 149, 91), Common::KEYCODE_4);
 }
 
 } // End of namespace Xeen
diff --git a/engines/xeen/dialogs_items.cpp b/engines/xeen/dialogs_items.cpp
index f8131db..21a8856 100644
--- a/engines/xeen/dialogs_items.cpp
+++ b/engines/xeen/dialogs_items.cpp
@@ -530,15 +530,15 @@ void ItemsDialog::loadButtons(ItemsMode mode, Character *&c) {
 		addButton(Common::Rect(148, 109, 172, 129), Common::KEYCODE_e, &_iconSprites);
 		addButton(Common::Rect(284, 109, 308, 129), Common::KEYCODE_ESCAPE, &_iconSprites);
 		addButton(Common::Rect(148, 109, 172, 129), Common::KEYCODE_u, &_iconSprites);
-		addButton(Common::Rect(8, 20, 263, 28), Common::KEYCODE_1, &_iconSprites, false);
-		addButton(Common::Rect(8, 29, 263, 37), Common::KEYCODE_2, &_iconSprites, false);
-		addButton(Common::Rect(8, 38, 263, 46), Common::KEYCODE_3, &_iconSprites, false);
-		addButton(Common::Rect(8, 47, 263, 55), Common::KEYCODE_4, &_iconSprites, false);
-		addButton(Common::Rect(8, 56, 263, 64), Common::KEYCODE_5, &_iconSprites, false);
-		addButton(Common::Rect(8, 65, 263, 73), Common::KEYCODE_6, &_iconSprites, false);
-		addButton(Common::Rect(8, 74, 263, 82), Common::KEYCODE_7, &_iconSprites, false);
-		addButton(Common::Rect(8, 83, 263, 91), Common::KEYCODE_8, &_iconSprites, false);
-		addButton(Common::Rect(8, 92, 263, 100), Common::KEYCODE_9, &_iconSprites, false);
+		addButton(Common::Rect(8, 20, 263, 28), Common::KEYCODE_1);
+		addButton(Common::Rect(8, 29, 263, 37), Common::KEYCODE_2);
+		addButton(Common::Rect(8, 38, 263, 46), Common::KEYCODE_3);
+		addButton(Common::Rect(8, 47, 263, 55), Common::KEYCODE_4);
+		addButton(Common::Rect(8, 56, 263, 64), Common::KEYCODE_5);
+		addButton(Common::Rect(8, 65, 263, 73), Common::KEYCODE_6);
+		addButton(Common::Rect(8, 74, 263, 82), Common::KEYCODE_7);
+		addButton(Common::Rect(8, 83, 263, 91), Common::KEYCODE_8);
+		addButton(Common::Rect(8, 92, 263, 100), Common::KEYCODE_9);
 	} else {
 		addButton(Common::Rect(12, 109, 36, 129), Common::KEYCODE_w, &_iconSprites);
 		addButton(Common::Rect(46, 109, 70, 129), Common::KEYCODE_a, &_iconSprites);
@@ -549,15 +549,15 @@ void ItemsDialog::loadButtons(ItemsMode mode, Character *&c) {
 		addButton(Common::Rect(216, 109, 240, 129), Common::KEYCODE_d, &_iconSprites);
 		addButton(Common::Rect(250, 109, 274, 129), Common::KEYCODE_q, &_iconSprites);
 		addButton(Common::Rect(284, 109, 308, 129), Common::KEYCODE_ESCAPE, &_iconSprites);
-		addButton(Common::Rect(8, 20, 263, 28), Common::KEYCODE_1, &_iconSprites, false);
-		addButton(Common::Rect(8, 29, 263, 37), Common::KEYCODE_2, &_iconSprites, false);
-		addButton(Common::Rect(8, 38, 263, 46), Common::KEYCODE_3, &_iconSprites, false);
-		addButton(Common::Rect(8, 47, 263, 55), Common::KEYCODE_4, &_iconSprites, false);
-		addButton(Common::Rect(8, 56, 263, 64), Common::KEYCODE_5, &_iconSprites, false);
-		addButton(Common::Rect(8, 65, 263, 73), Common::KEYCODE_6, &_iconSprites, false);
-		addButton(Common::Rect(8, 74, 263, 82), Common::KEYCODE_7, &_iconSprites, false);
-		addButton(Common::Rect(8, 83, 263, 91), Common::KEYCODE_8, &_iconSprites, false);
-		addButton(Common::Rect(8, 92, 263, 100), Common::KEYCODE_9, &_iconSprites, false);
+		addButton(Common::Rect(8, 20, 263, 28), Common::KEYCODE_1);
+		addButton(Common::Rect(8, 29, 263, 37), Common::KEYCODE_2);
+		addButton(Common::Rect(8, 38, 263, 46), Common::KEYCODE_3);
+		addButton(Common::Rect(8, 47, 263, 55), Common::KEYCODE_4);
+		addButton(Common::Rect(8, 56, 263, 64), Common::KEYCODE_5);
+		addButton(Common::Rect(8, 65, 263, 73), Common::KEYCODE_6);
+		addButton(Common::Rect(8, 74, 263, 82), Common::KEYCODE_7);
+		addButton(Common::Rect(8, 83, 263, 91), Common::KEYCODE_8);
+		addButton(Common::Rect(8, 92, 263, 100), Common::KEYCODE_9);
 		addPartyButtons(_vm);
 	}
 
@@ -807,15 +807,15 @@ int ItemsDialog::doItemOptions(Character &c, int actionIndex, int itemIndex, Ite
 
 		escSprites.load("esc.icn");
 		addButton(Common::Rect(235, 111, 259, 131), Common::KEYCODE_ESCAPE, &escSprites);
-		addButton(Common::Rect(8, 20, 263, 28), Common::KEYCODE_1, &escSprites, false);
-		addButton(Common::Rect(8, 29, 263, 37), Common::KEYCODE_2, &escSprites, false);
-		addButton(Common::Rect(8, 38, 263, 46), Common::KEYCODE_3, &escSprites, false);
-		addButton(Common::Rect(8, 47, 263, 55), Common::KEYCODE_4, &escSprites, false);
-		addButton(Common::Rect(8, 56, 263, 64), Common::KEYCODE_5, &escSprites, false);
-		addButton(Common::Rect(8, 65, 263, 73), Common::KEYCODE_6, &escSprites, false);
-		addButton(Common::Rect(8, 74, 263, 82), Common::KEYCODE_7, &escSprites, false);
-		addButton(Common::Rect(8, 83, 263, 91), Common::KEYCODE_8, &escSprites, false);
-		addButton(Common::Rect(8, 92, 263, 100), Common::KEYCODE_9, &escSprites, false);
+		addButton(Common::Rect(8, 20, 263, 28), Common::KEYCODE_1);
+		addButton(Common::Rect(8, 29, 263, 37), Common::KEYCODE_2);
+		addButton(Common::Rect(8, 38, 263, 46), Common::KEYCODE_3);
+		addButton(Common::Rect(8, 47, 263, 55), Common::KEYCODE_4);
+		addButton(Common::Rect(8, 56, 263, 64), Common::KEYCODE_5);
+		addButton(Common::Rect(8, 65, 263, 73), Common::KEYCODE_6);
+		addButton(Common::Rect(8, 74, 263, 82), Common::KEYCODE_7);
+		addButton(Common::Rect(8, 83, 263, 91), Common::KEYCODE_8);
+		addButton(Common::Rect(8, 92, 263, 100), Common::KEYCODE_9);
 
 		w.open();
 		w.writeString(Common::String::format(WHICH_ITEM, ITEM_ACTIONS[actionIndex]));
diff --git a/engines/xeen/dialogs_options.cpp b/engines/xeen/dialogs_options.cpp
index 8f02559..4b4974b 100644
--- a/engines/xeen/dialogs_options.cpp
+++ b/engines/xeen/dialogs_options.cpp
@@ -155,17 +155,17 @@ void OptionsMenu::showTitles2() {
 }
 
 void OptionsMenu::setupButtons(SpriteResource *buttons) {
-	addButton(Common::Rect(124, 87, 124 + 53, 87 + 10), 'S', buttons, false);
-	addButton(Common::Rect(126, 98, 126 + 47, 98 + 10), 'L', buttons, false);
-	addButton(Common::Rect(91, 110, 91 + 118, 110 + 10), 'C', buttons, false);
-	addButton(Common::Rect(85, 121, 85 + 131, 121 + 10), 'O', buttons, false);
+	addButton(Common::Rect(124, 87, 124 + 53, 87 + 10), 'S');
+	addButton(Common::Rect(126, 98, 126 + 47, 98 + 10), 'L');
+	addButton(Common::Rect(91, 110, 91 + 118, 110 + 10), 'C');
+	addButton(Common::Rect(85, 121, 85 + 131, 121 + 10), 'O');
 }
 
 void WorldOptionsMenu::setupButtons(SpriteResource *buttons) {
-	addButton(Common::Rect(93, 53, 93 + 134, 53 + 20), 'S', buttons, true);
-	addButton(Common::Rect(93, 78, 93 + 134, 78 + 20), 'L', buttons, true);
-	addButton(Common::Rect(93, 103, 93 + 134, 103 + 20), 'C', buttons, true);
-	addButton(Common::Rect(93, 128, 93 + 134, 128 + 20), 'O', buttons, true);
+	addButton(Common::Rect(93, 53, 93 + 134, 53 + 20), 'S', buttons);
+	addButton(Common::Rect(93, 78, 93 + 134, 78 + 20), 'L', buttons);
+	addButton(Common::Rect(93, 103, 93 + 134, 103 + 20), 'C', buttons);
+	addButton(Common::Rect(93, 128, 93 + 134, 128 + 20), 'O', buttons);
 }
 
 /*------------------------------------------------------------------------*/
diff --git a/engines/xeen/dialogs_party.cpp b/engines/xeen/dialogs_party.cpp
index 7414ce3..544c110 100644
--- a/engines/xeen/dialogs_party.cpp
+++ b/engines/xeen/dialogs_party.cpp
@@ -280,7 +280,7 @@ void PartyDialog::loadButtons() {
 	addButton(Common::Rect(122, 100, 146, 120), Common::KEYCODE_r, &_uiSprites);
 	addButton(Common::Rect(157, 100, 181, 120), Common::KEYCODE_c, &_uiSprites);
 	addButton(Common::Rect(192, 100, 216, 120), Common::KEYCODE_x, &_uiSprites);
-	addButton(Common::Rect(0, 0, 0, 0), Common::KEYCODE_ESCAPE, &_uiSprites, false);
+	addButton(Common::Rect(0, 0, 0, 0), Common::KEYCODE_ESCAPE);
 }
 
 void PartyDialog::initDrawStructs() {
@@ -310,10 +310,10 @@ void PartyDialog::setupFaces(int firstDisplayChar, bool updateFlag) {
 	// Reset the button areas for the display character images
 	while (_buttons.size() > 7)
 		_buttons.remove_at(7);
-	addButton(Common::Rect(16, 16, 48, 48), Common::KEYCODE_1, &_uiSprites, false);
-	addButton(Common::Rect(117, 16, 149, 48), Common::KEYCODE_2, &_uiSprites, false);
-	addButton(Common::Rect(59, 59, 91, 91), Common::KEYCODE_3, &_uiSprites, false);
-	addButton(Common::Rect(117, 59, 151, 91), Common::KEYCODE_4, &_uiSprites, false);
+	addButton(Common::Rect(16, 16, 48, 48), Common::KEYCODE_1);
+	addButton(Common::Rect(117, 16, 149, 48), Common::KEYCODE_2);
+	addButton(Common::Rect(59, 59, 91, 91), Common::KEYCODE_3);
+	addButton(Common::Rect(117, 59, 151, 91), Common::KEYCODE_4);
 
 
 	for (posIndex = 0; posIndex < 4; ++posIndex) {
@@ -712,10 +712,10 @@ int PartyDialog::selectCharacter(bool isDelete, int firstDisplayChar) {
 	saveButtons();
 	addButton(Common::Rect(225, isDelete ? 120 : 84, 249, isDelete ? 140 : 104), 
 		Common::KEYCODE_ESCAPE, &iconSprites);
-	addButton(Common::Rect(16, 16, 48, 48), Common::KEYCODE_1, &iconSprites, false);
-	addButton(Common::Rect(117, 16, 149, 48), Common::KEYCODE_2, &iconSprites, false);
-	addButton(Common::Rect(16, 59, 48, 91), Common::KEYCODE_3, &iconSprites, false);
-	addButton(Common::Rect(117, 59, 149, 91), Common::KEYCODE_4, &iconSprites, false);
+	addButton(Common::Rect(16, 16, 48, 48), Common::KEYCODE_1);
+	addButton(Common::Rect(117, 16, 149, 48), Common::KEYCODE_2);
+	addButton(Common::Rect(16, 59, 48, 91), Common::KEYCODE_3);
+	addButton(Common::Rect(117, 59, 149, 91), Common::KEYCODE_4);
 	addPartyButtons(_vm);
 
 	int result = -1, v;
diff --git a/engines/xeen/dialogs_spells.cpp b/engines/xeen/dialogs_spells.cpp
index dbe48c1..6a8b160 100644
--- a/engines/xeen/dialogs_spells.cpp
+++ b/engines/xeen/dialogs_spells.cpp
@@ -152,7 +152,7 @@ Character *SpellsDialog::execute(Character *c, int isCasting) {
 
 						int spellIndex = (c->_currentSpell == -1) ? 39 : c->_currentSpell;
 						int spellId = SPELLS_ALLOWED[category][spellIndex];
-						screen._windows[10].writeString(Common::String::format(SPELL_DETAILS,
+						screen._windows[10].writeString(Common::String::format(CAST_SPELL_DETAILS,
 							c->_name.c_str(), spells._spellNames[spellId].c_str(),
 							spells.calcSpellPoints(spellId, c->getCurrentLevel()),
 							SPELL_GEM_COST[spellId], c->_currentSp));
@@ -280,8 +280,8 @@ Character *SpellsDialog::execute(Character *c, int isCasting) {
 void SpellsDialog::loadButtons() {
 	_iconSprites.load("main.icn");
 	_scrollSprites.load("scroll.icn");
-	addButton(Common::Rect(187, 26, 198, 36), Common::KEYCODE_UP, &_scrollSprites, true);
-	addButton(Common::Rect(187, 111, 198, 121), Common::KEYCODE_DOWN, &_scrollSprites, true);
+	addButton(Common::Rect(187, 26, 198, 36), Common::KEYCODE_UP, &_scrollSprites);
+	addButton(Common::Rect(187, 111, 198, 121), Common::KEYCODE_DOWN, &_scrollSprites);
 	addButton(Common::Rect(40, 28, 187, 36), Common::KEYCODE_1);
 	addButton(Common::Rect(40, 37, 187, 45), Common::KEYCODE_2);
 	addButton(Common::Rect(40, 46, 187, 54), Common::KEYCODE_3);
diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp
index 0c7f15d..0420658 100644
--- a/engines/xeen/interface.cpp
+++ b/engines/xeen/interface.cpp
@@ -239,10 +239,10 @@ void Interface::setMainButtons(bool combatMode) {
 	addButton(Common::Rect(235, 169, 259, 189), (Common::KBD_CTRL << 16) |Common::KEYCODE_LEFT, &_iconSprites);
 	addButton(Common::Rect(260, 169, 284, 189), Common::KEYCODE_DOWN, &_iconSprites);
 	addButton(Common::Rect(286, 169, 310, 189), (Common::KBD_CTRL << 16) | Common::KEYCODE_RIGHT, &_iconSprites);
-	addButton(Common::Rect(236,  11, 308,  69),  Common::KEYCODE_EQUALS, &_iconSprites, false);
-	addButton(Common::Rect(239,  27, 312,  37),  Common::KEYCODE_1, &_iconSprites, false);
-	addButton(Common::Rect(239, 37, 312, 47), Common::KEYCODE_2, &_iconSprites, false);
-	addButton(Common::Rect(239, 47, 312, 57), Common::KEYCODE_3, &_iconSprites, false);
+	addButton(Common::Rect(236,  11, 308,  69),  Common::KEYCODE_EQUALS);
+	addButton(Common::Rect(239,  27, 312,  37),  Common::KEYCODE_1);
+	addButton(Common::Rect(239, 37, 312, 47), Common::KEYCODE_2);
+	addButton(Common::Rect(239, 47, 312, 57), Common::KEYCODE_3);
 	addPartyButtons(_vm);
 
 	if (combatMode) {
diff --git a/engines/xeen/resources.cpp b/engines/xeen/resources.cpp
index 0fe20fb..da57a80 100644
--- a/engines/xeen/resources.cpp
+++ b/engines/xeen/resources.cpp
@@ -931,18 +931,6 @@ const char *const SPELLS_PURCHASE =
 	"\x3l\xB""000\x9""000\xC""d%s  Do you wish to purchase "
 	"\xC""09%s\xC""d for %u?"; 
 
-const char *const SPELL_DETAILS =
-	"\xD\x2\x3""c\xB""122\x9""013\xC""37C\xC""dast"
-	"\x9""040\xC""37N\xC""dew\x9""067ESC\x1""000\xB""000\x3""cCast Spell\n"
-	"\n"
-	"%s\x3l\n"
-	"\n"
-	"Spell Ready:\x3""c\n"
-	"\n"
-	"\xC""09%s\xC""d\x2\x3l\n"
-	"\xB""082Cost\x3r\x9""000%u/%u\x3l\n"
-	"Cur SP\x3r\x9""000%u\x1";
-
 const char *const MAP_TEXT =
 	"\x3""c\xB""000\x9""000%s\x3l\xB""139"
 	"\x9""000X = %d\x3r\x9""000Y = %d\x3""c\x9""000%s";
diff --git a/engines/xeen/resources.h b/engines/xeen/resources.h
index 30eb4f5..c617844 100644
--- a/engines/xeen/resources.h
+++ b/engines/xeen/resources.h
@@ -288,8 +288,6 @@ extern const char *const SPELLS_PRESS_A_KEY;
 
 extern const char *const SPELLS_PURCHASE;
 
-extern const char *const SPELL_DETAILS;
-
 extern const char *const MAP_TEXT;
 
 extern const char *const LIGHT_COUNT_TEXT;
diff --git a/engines/xeen/town.cpp b/engines/xeen/town.cpp
index b850439..2723226 100644
--- a/engines/xeen/town.cpp
+++ b/engines/xeen/town.cpp
@@ -108,11 +108,11 @@ int Town::townAction(int actionId) {
 	case 1:
 		// Blacksmith
 		_icons1.load("esc.icn");
-		addButton(Common::Rect(261, 100, 285, 120), Common::KEYCODE_ESCAPE, &_icons1, true);
-		addButton(Common::Rect(234, 54, 308, 62), 0, &_icons1, false);
-		addButton(Common::Rect(234, 64, 308, 72), Common::KEYCODE_b, &_icons1, false);
-		addButton(Common::Rect(234, 74, 308, 82), 0, &_icons1, false);
-		addButton(Common::Rect(234, 84, 308, 92), 0, &_icons1, false);
+		addButton(Common::Rect(261, 100, 285, 120), Common::KEYCODE_ESCAPE, &_icons1);
+		addButton(Common::Rect(234, 54, 308, 62), 0);
+		addButton(Common::Rect(234, 64, 308, 72), Common::KEYCODE_b);
+		addButton(Common::Rect(234, 74, 308, 82), 0);
+		addButton(Common::Rect(234, 84, 308, 92), 0);
 
 		sound.playSample(nullptr, 0);
 		vocName = isDarkCc ? "see2.voc" : "whaddayo.voc";
@@ -122,11 +122,11 @@ int Town::townAction(int actionId) {
 		// Guild
 		loadStrings("spldesc.bin");
 		_icons1.load("esc.icn");
-		addButton(Common::Rect(261, 100, 285, 120), Common::KEYCODE_ESCAPE, &_icons1, true);
-		addButton(Common::Rect(234, 54, 308, 62), 0, &_icons1, false);
-		addButton(Common::Rect(234, 64, 308, 72), Common::KEYCODE_b, &_icons1, false);
-		addButton(Common::Rect(234, 74, 308, 82), Common::KEYCODE_s, &_icons1, false);
-		addButton(Common::Rect(234, 84, 308, 92), 0, &_icons1, false);
+		addButton(Common::Rect(261, 100, 285, 120), Common::KEYCODE_ESCAPE, &_icons1);
+		addButton(Common::Rect(234, 54, 308, 62), 0);
+		addButton(Common::Rect(234, 64, 308, 72), Common::KEYCODE_b);
+		addButton(Common::Rect(234, 74, 308, 82), Common::KEYCODE_s);
+		addButton(Common::Rect(234, 84, 308, 92), 0);
 		_vm->_mode = MODE_17;
 
 		sound.playSample(nullptr, 0);
@@ -137,12 +137,12 @@ int Town::townAction(int actionId) {
 		// Tavern
 		loadStrings("tavern.bin");
 		_icons1.load("tavern.icn");
-		addButton(Common::Rect(281, 108, 305, 128), Common::KEYCODE_ESCAPE, &_icons1, true);
-		addButton(Common::Rect(242, 108, 266, 128), Common::KEYCODE_s, &_icons1, true);
-		addButton(Common::Rect(234, 54, 308, 62), Common::KEYCODE_d, &_icons1, false);
-		addButton(Common::Rect(234, 64, 308, 72), Common::KEYCODE_f, &_icons1, false);
-		addButton(Common::Rect(234, 74, 308, 82), Common::KEYCODE_t, &_icons1, false);
-		addButton(Common::Rect(234, 84, 308, 92), Common::KEYCODE_r, &_icons1, false);
+		addButton(Common::Rect(281, 108, 305, 128), Common::KEYCODE_ESCAPE, &_icons1);
+		addButton(Common::Rect(242, 108, 266, 128), Common::KEYCODE_s, &_icons1);
+		addButton(Common::Rect(234, 54, 308, 62), Common::KEYCODE_d);
+		addButton(Common::Rect(234, 64, 308, 72), Common::KEYCODE_f);
+		addButton(Common::Rect(234, 74, 308, 82), Common::KEYCODE_t);
+		addButton(Common::Rect(234, 84, 308, 92), Common::KEYCODE_r);
 		_vm->_mode = MODE_17;
 
 		sound.playSample(nullptr, 0);
@@ -152,11 +152,11 @@ int Town::townAction(int actionId) {
 	case 4:
 		// Temple
 		_icons1.load("esc.icn");
-		addButton(Common::Rect(261, 100, 285, 120), Common::KEYCODE_ESCAPE, &_icons1, true);
-		addButton(Common::Rect(234, 54, 308, 62), Common::KEYCODE_h, &_icons1, false);
-		addButton(Common::Rect(234, 64, 308, 72), Common::KEYCODE_d, &_icons1, false);
-		addButton(Common::Rect(234, 74, 308, 82), Common::KEYCODE_u, &_icons1, false);
-		addButton(Common::Rect(234, 84, 308, 92), 0, &_icons1, false);
+		addButton(Common::Rect(261, 100, 285, 120), Common::KEYCODE_ESCAPE, &_icons1);
+		addButton(Common::Rect(234, 54, 308, 62), Common::KEYCODE_h);
+		addButton(Common::Rect(234, 64, 308, 72), Common::KEYCODE_d);
+		addButton(Common::Rect(234, 74, 308, 82), Common::KEYCODE_u);
+		addButton(Common::Rect(234, 84, 308, 92), 0);
 
 		sound.playSample(nullptr, 0);
 		vocName = isDarkCc ? "help2.voc" : "maywe2.voc";
@@ -168,8 +168,8 @@ int Town::townAction(int actionId) {
 		_v2 = 0;
 
 		_icons1.load("train.icn");
-		addButton(Common::Rect(281, 108, 305, 128), Common::KEYCODE_ESCAPE, &_icons1, true);
-		addButton(Common::Rect(242, 108, 266, 128), Common::KEYCODE_t, &_icons1, false);
+		addButton(Common::Rect(281, 108, 305, 128), Common::KEYCODE_ESCAPE, &_icons1);
+		addButton(Common::Rect(242, 108, 266, 128), Common::KEYCODE_t);
 
 		sound.playSample(nullptr, 0);
 		vocName = isDarkCc ? "training.voc" : "youtrn1.voc";


Commit: 4c420a70be9124c224723a787d2335053f4986fe
    https://github.com/scummvm/scummvm/commit/4c420a70be9124c224723a787d2335053f4986fe
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-02-18T22:11:59-05:00

Commit Message:
XEEN: Fix drawing buttons in Spells dialog when switching character

Changed paths:
    engines/xeen/dialogs.h
    engines/xeen/dialogs_spells.cpp
    engines/xeen/dialogs_spells.h
    engines/xeen/town.cpp



diff --git a/engines/xeen/dialogs.h b/engines/xeen/dialogs.h
index e2d8bc9..c04b680 100644
--- a/engines/xeen/dialogs.h
+++ b/engines/xeen/dialogs.h
@@ -55,8 +55,6 @@ protected:
 	void doScroll(XeenEngine *vm, bool drawFlag, bool doFade);
 
 	bool checkEvents(XeenEngine *vm);
-
-	void drawButtons(XSurface *surface);
 public:
 	ButtonContainer() : _buttonValue(0) {}
 
@@ -71,6 +69,8 @@ public:
 	void addButton(const Common::Rect &bounds, int val);
 
 	void addPartyButtons(XeenEngine *vm);
+
+	void drawButtons(XSurface *surface);
 };
 
 class SettingsBaseDialog : public ButtonContainer {
diff --git a/engines/xeen/dialogs_spells.cpp b/engines/xeen/dialogs_spells.cpp
index 6a8b160..e25d839 100644
--- a/engines/xeen/dialogs_spells.cpp
+++ b/engines/xeen/dialogs_spells.cpp
@@ -29,15 +29,16 @@
 
 namespace Xeen {
 
-Character *SpellsDialog::show(XeenEngine *vm, Character *c, int isCasting) {
+Character *SpellsDialog::show(XeenEngine *vm, ButtonContainer *priorDialog, 
+		Character *c, int isCasting) {
 	SpellsDialog *dlg = new SpellsDialog(vm);
-	Character *result = dlg->execute(c, isCasting);
+	Character *result = dlg->execute(priorDialog, c, isCasting);
 	delete dlg;
 
 	return result;
 }
 
-Character *SpellsDialog::execute(Character *c, int isCasting) {
+Character *SpellsDialog::execute(ButtonContainer *priorDialog, Character *c, int isCasting) {
 	EventsManager &events = *_vm->_events;
 	Interface &intf = *_vm->_interface;
 	Party &party = *_vm->_party;
@@ -158,7 +159,8 @@ Character *SpellsDialog::execute(Character *c, int isCasting) {
 							SPELL_GEM_COST[spellId], c->_currentSp));
 					}
 
-					drawButtons(&screen);
+					if (priorDialog != nullptr)
+						priorDialog->drawButtons(&screen);
 					screen._windows[10].update();
 				}
 			}
@@ -299,7 +301,7 @@ void SpellsDialog::loadButtons() {
 	addPartyButtons(_vm);
 }
 
-const char *SpellsDialog::setSpellText(Character *c, int v2) {
+const char *SpellsDialog::setSpellText(Character *c, int isCasting) {
 	Party &party = *_vm->_party;
 	Spells &spells = *_vm->_spells;
 	bool isDarkCc = _vm->_files->_isDarkCc;
@@ -307,7 +309,7 @@ const char *SpellsDialog::setSpellText(Character *c, int v2) {
 	int currLevel = c->getCurrentLevel();
 	int category;
 
-	if ((v2 & 0x7f) == 0) {
+	if ((isCasting & 0x7f) == 0) {
 		switch (c->_class) {
 		case CLASS_PALADIN:
 			expenseFactor = 1;
@@ -344,7 +346,7 @@ const char *SpellsDialog::setSpellText(Character *c, int v2) {
 
 					// Handling if the spell is appropriate for the character's class
 					if (idx < MAX_SPELLS_PER_CLASS) {
-						if (!c->_spells[idx] || (v2 & 0x80)) {
+						if (!c->_spells[idx] || (isCasting & 0x80)) {
 							int cost = spells.calcSpellCost(SPELLS_ALLOWED[category][idx], expenseFactor);
 							_spells.push_back(SpellEntry(Common::String::format("\x3l%s\x3r\x9""000%u",
 								spells._spellNames[SPELLS_ALLOWED[category][idx]], cost), 
@@ -361,7 +363,7 @@ const char *SpellsDialog::setSpellText(Character *c, int v2) {
 						DARK_SPELL_OFFSETS[category][spellId]);
 
 					if (idx < 40) {
-						if (!c->_spells[idx] || (v2 & 0x80)) {
+						if (!c->_spells[idx] || (isCasting & 0x80)) {
 							int cost = spells.calcSpellCost(SPELLS_ALLOWED[category][idx], expenseFactor);
 							_spells.push_back(SpellEntry(Common::String::format("\x3l%s\x3r\x9""000%u",
 								spells._spellNames[SPELLS_ALLOWED[category][idx]], cost), 
@@ -376,7 +378,7 @@ const char *SpellsDialog::setSpellText(Character *c, int v2) {
 						(int)SPELLS_ALLOWED[category][idx] && idx < 40) ;
 
 					if (idx < 40) {
-						if (!c->_spells[idx] || (v2 & 0x80)) {
+						if (!c->_spells[idx] || (isCasting & 0x80)) {
 							int cost = spells.calcSpellCost(SPELLS_ALLOWED[category][idx], expenseFactor);
 							_spells.push_back(SpellEntry(Common::String::format("\x3l%s\x3r\x9""000%u",
 								spells._spellNames[SPELLS_ALLOWED[category][idx]], cost), 
@@ -390,7 +392,7 @@ const char *SpellsDialog::setSpellText(Character *c, int v2) {
 		if (c->getMaxSP() == 0)
 			return NOT_A_SPELL_CASTER;
 
-	} else if ((v2 & 0x7f) == 1) {
+	} else if ((isCasting & 0x7f) == 1) {
 		switch (c->_class) {
 		case 0:
 		case 12:
@@ -546,7 +548,7 @@ int CastSpell::execute(Character *&c, int mode) {
 		case Common::KEYCODE_n:
 			// Select new spell
 			_vm->_mode = oldMode;
-			c = SpellsDialog::show(_vm, c, 1);
+			c = SpellsDialog::show(_vm, this, c, 1);
 			redrawFlag = true;
 			break;
 
diff --git a/engines/xeen/dialogs_spells.h b/engines/xeen/dialogs_spells.h
index f091da6..32d0790 100644
--- a/engines/xeen/dialogs_spells.h
+++ b/engines/xeen/dialogs_spells.h
@@ -48,13 +48,14 @@ private:
 
 	SpellsDialog(XeenEngine *vm) : ButtonContainer(), _vm(vm) {}
 
-	Character *execute(Character *c, int v2);
+	Character *execute(ButtonContainer *priorDialog, Character *c, int isCasting);
 
 	void loadButtons();
 
-	const char *setSpellText(Character *c, int v2);
+	const char *setSpellText(Character *c, int isCasting);
 public:
-	static Character *show(XeenEngine *vm, Character *c, int isCasting);
+	static Character *show(XeenEngine *vm, ButtonContainer *priorDialog, 
+		Character *c, int isCasting);
 };
 
 class CastSpell : public ButtonContainer {
diff --git a/engines/xeen/town.cpp b/engines/xeen/town.cpp
index 2723226..3a8b6d8 100644
--- a/engines/xeen/town.cpp
+++ b/engines/xeen/town.cpp
@@ -567,12 +567,12 @@ Character *Town::doGuildOptions(Character *c) {
 		}
 	} else if (_buttonValue == Common::KEYCODE_s) {
 		if (c->guildMember())
-			c = SpellsDialog::show(_vm, c, 0x80);
+			c = SpellsDialog::show(_vm, nullptr, c, 0x80);
 		_buttonValue = 0;
 	} else if (_buttonValue == Common::KEYCODE_c) {
 		if (!c->noActions()) {
 			if (c->guildMember())
-				c = SpellsDialog::show(_vm, c, 0);
+				c = SpellsDialog::show(_vm, nullptr, c, 0);
 			_buttonValue = 0;
 		}
 	}


Commit: e17d258217f8605d7722927cd0180b59f87717a5
    https://github.com/scummvm/scummvm/commit/e17d258217f8605d7722927cd0180b59f87717a5
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-02-19T07:57:25-05:00

Commit Message:
XEEN: Fix display of spell names in Spells dialog

Changed paths:
    engines/xeen/dialogs_spells.cpp



diff --git a/engines/xeen/dialogs_spells.cpp b/engines/xeen/dialogs_spells.cpp
index e25d839..5084843 100644
--- a/engines/xeen/dialogs_spells.cpp
+++ b/engines/xeen/dialogs_spells.cpp
@@ -394,18 +394,16 @@ const char *SpellsDialog::setSpellText(Character *c, int isCasting) {
 
 	} else if ((isCasting & 0x7f) == 1) {
 		switch (c->_class) {
-		case 0:
-		case 12:
-			category = 0;
-			break;
-		case 1:
-		case 3:
+		case CLASS_ARCHER:
+		case CLASS_SORCERER:
 			category = 1;
 			break;
-		case 7:
-		case 8:
+		case CLASS_DRUID:
+		case CLASS_RANGER:
 			category = 2;
 			break;
+		case CLASS_PALADIN:
+		case CLASS_CLERIC:
 		default:
 			category = 0;
 			break;


Commit: 7c3f373b9b935b71b3006f203a1f75442818673a
    https://github.com/scummvm/scummvm/commit/7c3f373b9b935b71b3006f203a1f75442818673a
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-02-19T08:26:55-05:00

Commit Message:
XEEN: Fix selecting spells to cast in spells dialog

Changed paths:
    engines/xeen/dialogs_spells.cpp



diff --git a/engines/xeen/dialogs_spells.cpp b/engines/xeen/dialogs_spells.cpp
index 5084843..0383886 100644
--- a/engines/xeen/dialogs_spells.cpp
+++ b/engines/xeen/dialogs_spells.cpp
@@ -93,6 +93,8 @@ Character *SpellsDialog::execute(ButtonContainer *priorDialog, Character *c, int
 			}
 		}
 
+		if (selection >= topIndex && selection < (topIndex + 10))
+			colors[selection - topIndex] = 15;
 		if (_spells.size() == 0)
 			names[0] = errorMsg;
 
@@ -225,10 +227,9 @@ Character *SpellsDialog::execute(ButtonContainer *priorDialog, Character *c, int
 				int spellIndex = _spells[newSelection]._spellIndex;
 				int spellCost = spells.calcSpellCost(spellId, expenseFactor);
 				if (isCasting) {
-					// TODO: Confirm this refactoring against against original
-					selection = _buttonValue;
+					selection = newSelection;					
 				} else {
-					Common::String spellName = _spells[_buttonValue]._name;
+					Common::String spellName = _spells[newSelection]._name;
 					Common::String msg = (castingCopy & 0x80) ?
 						Common::String::format(SPELLS_PRESS_A_KEY, msg.c_str()) :
 						Common::String::format(SPELLS_PURCHASE, msg.c_str(), spellCost);
@@ -273,6 +274,9 @@ Character *SpellsDialog::execute(ButtonContainer *priorDialog, Character *c, int
 	} while (!_vm->shouldQuit() && _buttonValue != Common::KEYCODE_ESCAPE);
 
 	screen._windows[25].close();
+
+	if (_vm->shouldQuit())
+		selection = -1;
 	if (isCasting && selection != -1)
 		c->_currentSpell = _spells[selection]._spellIndex;
 
@@ -479,7 +483,6 @@ int CastSpell::execute(Character *&c, int mode) {
 	Window &w = screen._windows[10];
 
 	Mode oldMode = (Mode)mode;
-	int category = c->getClassCategory();
 
 	w.open();
 	loadButtons();
@@ -488,6 +491,7 @@ int CastSpell::execute(Character *&c, int mode) {
 	bool redrawFlag = true;
 	do {
 		if (redrawFlag) {
+			int category = c->getClassCategory();
 			int spellIndex = c->_currentSpell != -1 ? c->_currentSpell : 39;
 			spellId = SPELLS_ALLOWED[category][spellIndex];
 			int gemCost = SPELL_GEM_COST[spellId];


Commit: b66bf1a838b01181c93b19e214c59c810e05955d
    https://github.com/scummvm/scummvm/commit/b66bf1a838b01181c93b19e214c59c810e05955d
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-02-19T21:12:33-05:00

Commit Message:
XEEN: Implemented stopAttack

Changed paths:
    engines/xeen/combat.cpp
    engines/xeen/combat.h



diff --git a/engines/xeen/combat.cpp b/engines/xeen/combat.cpp
index 7ed3499..a9ead95 100644
--- a/engines/xeen/combat.cpp
+++ b/engines/xeen/combat.cpp
@@ -568,15 +568,113 @@ void Combat::attackMonster(int monsterId) {
 
 }
 
-bool Combat::stopAttack(const Common::Point &diffPt) {
+int Combat::stopAttack(const Common::Point &diffPt) {
 	Map &map = *_vm->_map;
+	Party &party = *_vm->_party;
+	Direction dir = party._mazeDirection;
+	const Common::Point &mazePos = party._mazePosition;
 
 	if (map._isOutdoors) {
+		if (diffPt.x > 0) {
+			for (int x = 1; x <= diffPt.x; ++x) {
+				int v = map.mazeLookup(Common::Point(mazePos.x + x, mazePos.y), 0, 8);
+				if (v)
+					return 0;
+			}
+			return (dir == DIR_EAST) ? diffPt.x + 1 : 1;
+
+		} else if (diffPt.x < 0) {
+			for (int x = diffPt.x; x < 0; ++x) {
+				int v = map.mazeLookup(Common::Point(mazePos.x + x, mazePos.y), 4);
+				switch (v) {
+				case 0:
+				case 2:
+				case 4:
+				case 5:
+				case 8:
+				case 11:
+				case 13:
+				case 14:
+					break;
+				default:
+					return 0;
+				}
+			}
+			return dir == DIR_WEST ? diffPt.x * -1 + 1 : 1;
+		
+		} else if (diffPt.y <= 0) {
+			for (int y = diffPt.y; y < 0; ++y) {
+				int v = map.mazeLookup(Common::Point(mazePos.x, mazePos.y + y), 4);
+				switch (v) {
+				case 0:
+				case 2:
+				case 4:
+				case 5:
+				case 8:
+				case 11:
+				case 13:
+				case 14:
+					break;
+				default:
+					return 0;
+				}
+			}
+			return party._mazeDirection == DIR_SOUTH ? diffPt.y * -1 + 1 : 1;
 
-	}
+		} else {
+			for (int y = 1; y <= diffPt.y; ++y) {
+				int v = map.mazeLookup(Common::Point(mazePos.x, mazePos.y + y), 4);
+				switch (v) {
+				case 0:
+				case 2:
+				case 4:
+				case 5:
+				case 8:
+				case 11:
+				case 13:
+				case 14:
+					break;
+				default:
+					return 0;
+				}
+			}
+			return dir == DIR_NORTH ? diffPt.y + 1 : 1;
+		}
+	} else {
+		// Indoors
+		if (diffPt.x > 0) {
+			for (int x = 1; x <= diffPt.x; ++x) {
+				int v = map.mazeLookup(Common::Point(mazePos.x + x, mazePos.y), 0, 8);
+				if (v)
+					return 0;
+			}
+			return dir == DIR_EAST ? diffPt.x + 1 : 1;
 
-	// TODO
-	return false;
+		} else if (diffPt.x < 0) {
+			for (int x = diffPt.x; x < 0; ++x) {
+				int v = map.mazeLookup(Common::Point(mazePos.x + x, mazePos.y), 0, 0x800);
+				if (v)
+					return 0;
+			}
+			return dir == DIR_WEST ? diffPt.x * -1 + 1 : 1;
+		
+		} else if (diffPt.y <= 0) {
+			for (int y = diffPt.y; y < 0; ++y) {
+				int v = map.mazeLookup(Common::Point(mazePos.x, mazePos.y + y), 0, 0x8000);
+				if (v)
+					return 0;
+			}
+			return dir == DIR_SOUTH ? diffPt.y * -1 + 1 : 1;
+
+		} else {
+			for (int y = 1; y <= diffPt.y; ++y) {
+				int v = map.mazeLookup(Common::Point(mazePos.x, mazePos.y + y), 0, 0x80);
+				if (v)
+					return 0;
+			}
+			return dir == DIR_NORTH ? diffPt.y + 1 : 1;
+		}
+	}
 }
 
 /**
diff --git a/engines/xeen/combat.h b/engines/xeen/combat.h
index 5ff6beb..b929323 100644
--- a/engines/xeen/combat.h
+++ b/engines/xeen/combat.h
@@ -99,7 +99,7 @@ public:
 
 	void monsterOvercome();
 	
-	bool stopAttack(const Common::Point &diffPt);
+	int stopAttack(const Common::Point &diffPt);
 public:
 	Combat(XeenEngine *vm);
 


Commit: caf7f376b3fd8bb1bfd3e658139b547695033dde
    https://github.com/scummvm/scummvm/commit/caf7f376b3fd8bb1bfd3e658139b547695033dde
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-02-20T08:47:38-05:00

Commit Message:
XEEN: Implemented monsterAttack

Changed paths:
    engines/xeen/combat.cpp
    engines/xeen/combat.h
    engines/xeen/map.h



diff --git a/engines/xeen/combat.cpp b/engines/xeen/combat.cpp
index a9ead95..b6d1f7f 100644
--- a/engines/xeen/combat.cpp
+++ b/engines/xeen/combat.cpp
@@ -236,6 +236,13 @@ loop:
 	}
 }
 
+/**
+ * Do damage to a specific character
+ */
+void Combat::doCharDamage(Character *c, int monsterDataIndex) {
+	error("TODO");
+}
+
 void Combat::moveMonsters() {
 	Interface &intf = *_vm->_interface;
 	Map &map = *_vm->_map;
@@ -565,7 +572,184 @@ void Combat::monsterOvercome() {
 }
 
 void Combat::attackMonster(int monsterId) {
+	Interface &intf = *_vm->_interface;
+	Map &map = *_vm->_map;
+	Party &party = *_vm->_party;
+	SoundManager &sound = *_vm->_sound;
+	int monRefId;
+
+	if (_monstersAttacking) {
+		warning("TODO: Original used uninitialized variables if flag was set");
+		return;
+	}
+
+	int monsterIndex;
+	switch (_whosTurn - _combatParty.size()) {
+	case 0:
+		monsterIndex = _attackMonsters[0];
+		intf._indoorList[156]._scale = 0;
+		break;
+	case 1:
+		monsterIndex = _attackMonsters[1];
+		intf._indoorList[150]._scale = 0;
+		break;
+	case 2:
+	default:
+		monsterIndex = _attackMonsters[2];
+		intf._indoorList[153]._scale = 0;
+	} 
+
+	MazeMonster &monster = map._mobData._monsters[monsterIndex];
+	MonsterStruct &monsterData = map._monsterData[monster._spriteId];
+	if (monster._field7)
+		return;
+
+	monster._frame = 8;
+	monster._fieldA = 3;
+	monster._field9 = 0;
+	intf.draw3d(true);
+	intf.draw3d(true);
+
+	File f(monsterData._attackVoc);
+	sound.playSample(&f, 0);
+	bool flag = false;
+
+	for (int attackNum = 0; attackNum < monsterData._numberOfAttacks; ++attackNum) {
+		int charNum = -1;
+		bool isHated = false;
+
+		if (monsterData._hatesClass != -1) {
+			if (monsterData._hatesClass == 15)
+				// Monster hates all classes
+				goto loop;
+
+			for (uint charIndex = 0; charIndex < _combatParty.size(); ++charIndex) {
+				Character &c = *_combatParty[charIndex];
+				Condition cond = c.worstCondition();
+				if (cond >= PARALYZED && cond <= ERADICATED)
+					continue;
+
+				bool isHated = false;
+				switch (monsterData._hatesClass) {
+				case CLASS_KNIGHT:
+				case CLASS_PALADIN:
+				case CLASS_ARCHER:
+				case CLASS_CLERIC:
+				case CLASS_SORCERER:
+				case CLASS_ROBBER:
+				case CLASS_NINJA:
+				case CLASS_BARBARIAN:
+				case CLASS_DRUID:
+				case CLASS_RANGER:
+					isHated = c._class == monsterData._hatesClass;
+					break;
+				case 12:
+					isHated = c._race == DWARF;
+					break;
+				default:
+					break;
+				}
+
+				if (isHated) {
+					charNum = charIndex;
+					break;
+				}
+			}
+		}
+
+		if (!isHated) {
+			// No particularly hated foe, so decide which character to start with
+			switch (_combatParty.size()) {
+			case 1:
+				charNum = 0;
+				break;
+			case 2:
+			case 3:
+			case 4:
+			case 5:
+				charNum = _vm->getRandomNumber(0, _combatParty.size() - 1);
+				break;
+			case 6:
+				if (_vm->getRandomNumber(1, 6) == 6)
+					charNum = 5;
+				else
+					charNum = _vm->getRandomNumber(0, 4);
+				break;
+			}
+		}
+
+		// Attacking loop
+		do {
+			if (!flag) {
+				Condition cond = _combatParty[charNum]->worstCondition();
+
+				if (cond >= PARALYZED && cond <= ERADICATED) {
+					Common::Array<int> ableChars;
+					bool skip = false;
+					
+					for (uint idx = 0; idx < _combatParty.size() && !skip; ++idx) {
+						switch (_combatParty[idx]->worstCondition()) {
+						case PARALYZED:
+						case UNCONSCIOUS:
+							if (flag)
+								skip = true;
+							break;
+						case DEAD:
+						case STONED:
+						case ERADICATED:
+							break;
+						default:
+							ableChars.push_back(idx);
+							break;
+						}
+					}
+
+					if (!skip) {
+						if (ableChars.size() == 0) {
+							party._dead = true;
+							_vm->_mode = MODE_1;
+							return;
+						}
+
+						charNum = ableChars[_vm->getRandomNumber(0, ableChars.size() - 1)];
+					}
+				}
+			}
+
+			// Unconditional if to get around goto initialization errors
+			if (true) {
+				Character &c = *_combatParty[charNum];
+				if (monsterData._attackType != DT_PHYSICAL || c._conditions[ASLEEP]) {
+					doCharDamage(&c, monster._spriteId);
+				} else {
+					int v = _vm->getRandomNumber(1, 20);
+					if (v == 1) {
+						sound.playFX(6);
+					} else {
+						if (v == 20)
+							doCharDamage(&c, monster._spriteId);
+						v += monsterData._hitChance / 4 + _vm->getRandomNumber(1,
+							monsterData._hitChance);
+
+						int ac = c.getArmorClass() + (!_charsBlocked[charNum] ? 10 :
+							c.getCurrentLevel() / 2 + 15);
+						if (ac > v) {
+							sound.playFX(6);
+						} else {
+							doCharDamage(&c, monster._spriteId);
+						}
+					}
+				}
+
+				if (flag)
+					break;
+			}
+loop:
+			flag = true;
+		} while (++charNum < (int)_combatParty.size());
+	}
 
+	intf.drawParty(true);
 }
 
 int Combat::stopAttack(const Common::Point &diffPt) {
diff --git a/engines/xeen/combat.h b/engines/xeen/combat.h
index b929323..df42a40 100644
--- a/engines/xeen/combat.h
+++ b/engines/xeen/combat.h
@@ -107,6 +107,8 @@ public:
 
 	void giveCharDamage(int damage, DamageType attackType, int charIndex);
 
+	void doCharDamage(Character *c, int monsterDataIndex);
+
 	void moveMonsters();
 
 	void setupCombatParty();
diff --git a/engines/xeen/map.h b/engines/xeen/map.h
index a43cef5..05ead5b 100644
--- a/engines/xeen/map.h
+++ b/engines/xeen/map.h
@@ -54,7 +54,7 @@ public:
 	int _accuracy;
 	int _speed;
 	int _numberOfAttacks;
-	CharacterClass _hatesClass;
+	int _hatesClass;
 	int _strikes;
 	int _dmgPerStrike;
 	DamageType _attackType;


Commit: ebc134a267046d78b1cef125f2a318e497bdf45f
    https://github.com/scummvm/scummvm/commit/ebc134a267046d78b1cef125f2a318e497bdf45f
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-02-20T20:08:39-05:00

Commit Message:
XEEN: Implement attackMonster and breakAllItems

Changed paths:
    engines/xeen/character.cpp
    engines/xeen/character.h
    engines/xeen/combat.cpp
    engines/xeen/combat.h



diff --git a/engines/xeen/character.cpp b/engines/xeen/character.cpp
index c91b860..04f8325 100644
--- a/engines/xeen/character.cpp
+++ b/engines/xeen/character.cpp
@@ -669,6 +669,24 @@ InventoryItems &InventoryItemsGroup::operator[](ItemCategory category) {
 	return *_itemSets[category];
 }
 
+/**
+ * Breaks all the items in a given character's inventory
+ */
+void InventoryItemsGroup::breakAllItems() {
+	for (int idx = 0; idx < INV_ITEMS_TOTAL; ++idx) {
+		if ((*_itemSets[0])[idx]._id != 34) {
+			(*_itemSets[0])[idx]._bonusFlags |= ITEMFLAG_BROKEN;
+			(*_itemSets[0])[idx]._frame = 0;
+		}
+
+		(*_itemSets[1])[idx]._bonusFlags |= ITEMFLAG_BROKEN;
+		(*_itemSets[2])[idx]._bonusFlags |= ITEMFLAG_BROKEN;
+		(*_itemSets[3])[idx]._bonusFlags |= ITEMFLAG_BROKEN;
+		(*_itemSets[1])[idx]._frame = 0;
+		(*_itemSets[2])[idx]._frame = 0;
+	}
+}
+
 /*------------------------------------------------------------------------*/
 
 
diff --git a/engines/xeen/character.h b/engines/xeen/character.h
index bf77bef..6acd433 100644
--- a/engines/xeen/character.h
+++ b/engines/xeen/character.h
@@ -201,6 +201,8 @@ public:
 		InventoryItems &accessories, InventoryItems &misc);
 
 	InventoryItems &operator[](ItemCategory category);
+
+	void breakAllItems();
 };
 
 
diff --git a/engines/xeen/combat.cpp b/engines/xeen/combat.cpp
index b6d1f7f..5142015 100644
--- a/engines/xeen/combat.cpp
+++ b/engines/xeen/combat.cpp
@@ -239,8 +239,176 @@ loop:
 /**
  * Do damage to a specific character
  */
-void Combat::doCharDamage(Character *c, int monsterDataIndex) {
-	error("TODO");
+void Combat::doCharDamage(Character &c, int charNum, int monsterDataIndex) {
+	EventsManager &events = *_vm->_events;
+	Interface &intf = *_vm->_interface;
+	Map &map = *_vm->_map;
+	Party &party = *_vm->_party;
+	Screen &screen = *_vm->_screen;
+	SoundManager &sound = *_vm->_sound;
+	MonsterStruct &monsterData = map._monsterData[monsterDataIndex];
+
+	// Attacked characters are automatically woken up
+	c._conditions[ASLEEP] = 0;
+
+	// Figure out the damage amount
+	int damage = 0;
+	for (int idx = 0; idx < monsterData._strikes; ++idx)
+		damage += _vm->getRandomNumber(1, monsterData._dmgPerStrike);
+
+
+	int fx = 29, frame = 0;
+	if (monsterData._attackType) {
+		if (c.charSavingThrow(monsterData._attackType))
+			damage /= 2;
+
+		switch (monsterData._attackType) {
+		case DT_MAGICAL:
+			frame = 6;
+			fx = 27;
+			break;
+		case DT_FIRE:
+			damage -= party._fireResistence;
+			frame = 1;
+			fx = 22;
+			break;
+		case DT_ELECTRICAL:
+			damage -= party._electricityResistence;
+			frame = 2;
+			fx = 23;
+			break;
+		case DT_COLD:
+			damage -= party._coldResistence;
+			frame = 3;
+			fx = 24;
+			break;
+		case DT_POISON:
+			damage -= party._poisonResistence;
+			frame = 4;
+			fx = 26;
+			break;
+		case DT_ENERGY:
+			frame = 5;
+			fx = 25;
+			break;
+		default:
+			break;
+		}
+
+		while (damage > 0 && c.charSavingThrow(monsterData._attackType))
+			damage /= 2;
+	}
+
+	sound.playFX(fx);
+	intf._charPowSprites.draw(screen, frame, Common::Point(CHAR_FACES_X[charNum], 150));
+	screen._windows[33].update();
+
+	damage -= party._powerShield;
+	if (damage > 0 && monsterData._specialAttack && !c.charSavingThrow(DT_PHYSICAL)) {
+		switch (monsterData._specialAttack) {
+		case SA_POISON:
+			if (!++c._conditions[POISONED])
+				c._conditions[POISONED] = -1;
+			sound.playFX(26);
+			break;
+		case SA_DISEASE:
+			if (!++c._conditions[DISEASED])
+				c._conditions[DISEASED] = -1;
+			sound.playFX(26);
+			break;
+		case SA_INSANE:
+			if (!++c._conditions[INSANE])
+				c._conditions[INSANE] = -1;
+			sound.playFX(28);
+			break;
+		case SA_SLEEP:
+			if (!++c._conditions[ASLEEP])
+				c._conditions[ASLEEP] = -1;
+			sound.playFX(36);
+			break;
+		case SA_CURSEITEM:
+			for (int idx = 0; idx < INV_ITEMS_TOTAL; ++idx) {
+				if (c._weapons[idx]._id != 34)
+					c._weapons[idx]._bonusFlags |= ITEMFLAG_CURSED;
+				c._armor[idx]._bonusFlags |= ITEMFLAG_CURSED;
+				c._accessories[idx]._bonusFlags |= ITEMFLAG_CURSED;
+				c._misc[idx]._bonusFlags |= ITEMFLAG_CURSED;;
+			}
+			sound.playFX(37);
+			break;
+		case SA_DRAINSP:
+			c._currentSp = 0;
+			sound.playFX(37);
+			break;
+		case SA_CURSE:
+			if (!++c._conditions[CURSED])
+				c._conditions[CURSED] = -1;
+			sound.playFX(37);
+			break;
+		case SA_PARALYZE:
+			if (!++c._conditions[PARALYZED])
+				c._conditions[PARALYZED] = -1;
+			sound.playFX(37);
+			break;
+		case SA_UNCONSCIOUS:
+			if (!++c._conditions[UNCONSCIOUS])
+				c._conditions[UNCONSCIOUS] = -1;
+			sound.playFX(37);
+			break;
+		case SA_CONFUSE:
+			if (!++c._conditions[CONFUSED])
+				c._conditions[CONFUSED] = -1;
+			sound.playFX(28);
+			break;
+		case SA_BREAKWEAPON:
+			for (int idx = 0; idx < INV_ITEMS_TOTAL; ++idx) {
+				XeenItem &weapon = c._weapons[idx];
+				if (weapon._id != 34 && weapon._id != 0 && weapon._frame != 0) {
+					weapon._bonusFlags |= ITEMFLAG_BROKEN;
+					weapon._frame = 0;
+				}
+			}
+			sound.playFX(37);
+			break;
+		case SA_WEAKEN:
+			if (!++c._conditions[WEAK])
+				c._conditions[WEAK] = -1;
+			sound.playFX(36);
+			break;
+		case SA_ERADICATE:
+			if (!++c._conditions[ERADICATED])
+				c._conditions[ERADICATED] = -1;
+			c._items.breakAllItems();
+			sound.playFX(37);
+
+			if (c._currentHp > 0)
+				c._currentHp = 0;
+			break;
+		case SA_AGING:
+			++c._tempAge;
+			sound.playFX(37);
+			break;
+		case SA_DEATH:
+			if (!++c._conditions[DEAD])
+				c._conditions[DEAD] = -1;
+			sound.playFX(38);
+			if (c._currentHp > 0)
+				c._currentHp = 0;
+			break;
+		case SA_STONE:
+			if (!++c._conditions[STONED])
+				c._conditions[STONED] = -1;
+			sound.playFX(38);
+			if (c._currentHp > 0)
+				c._currentHp = 0;
+			break;
+		}
+
+		c.subtractHitPoints(damage);
+	}
+
+	events.ipause(2);
+	intf.drawParty(true);
 }
 
 void Combat::moveMonsters() {
@@ -576,7 +744,6 @@ void Combat::attackMonster(int monsterId) {
 	Map &map = *_vm->_map;
 	Party &party = *_vm->_party;
 	SoundManager &sound = *_vm->_sound;
-	int monRefId;
 
 	if (_monstersAttacking) {
 		warning("TODO: Original used uninitialized variables if flag was set");
@@ -720,14 +887,14 @@ void Combat::attackMonster(int monsterId) {
 			if (true) {
 				Character &c = *_combatParty[charNum];
 				if (monsterData._attackType != DT_PHYSICAL || c._conditions[ASLEEP]) {
-					doCharDamage(&c, monster._spriteId);
+					doCharDamage(c, charNum, monster._spriteId);
 				} else {
 					int v = _vm->getRandomNumber(1, 20);
 					if (v == 1) {
 						sound.playFX(6);
 					} else {
 						if (v == 20)
-							doCharDamage(&c, monster._spriteId);
+							doCharDamage(c, charNum, monster._spriteId);
 						v += monsterData._hitChance / 4 + _vm->getRandomNumber(1,
 							monsterData._hitChance);
 
@@ -736,7 +903,7 @@ void Combat::attackMonster(int monsterId) {
 						if (ac > v) {
 							sound.playFX(6);
 						} else {
-							doCharDamage(&c, monster._spriteId);
+							doCharDamage(c, charNum, monster._spriteId);
 						}
 					}
 				}
diff --git a/engines/xeen/combat.h b/engines/xeen/combat.h
index df42a40..60adbca 100644
--- a/engines/xeen/combat.h
+++ b/engines/xeen/combat.h
@@ -107,7 +107,7 @@ public:
 
 	void giveCharDamage(int damage, DamageType attackType, int charIndex);
 
-	void doCharDamage(Character *c, int monsterDataIndex);
+	void doCharDamage(Character &c, int charNum, int monsterDataIndex);
 
 	void moveMonsters();
 


Commit: 917b143ec9e7fd9f5c9b28088c2b7f6310c16cee
    https://github.com/scummvm/scummvm/commit/917b143ec9e7fd9f5c9b28088c2b7f6310c16cee
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-02-20T21:55:40-05:00

Commit Message:
XEEN: Implement attack method

Changed paths:
    engines/xeen/character.cpp
    engines/xeen/combat.cpp
    engines/xeen/combat.h
    engines/xeen/dialogs_spells.cpp
    engines/xeen/interface_map.cpp
    engines/xeen/map.cpp
    engines/xeen/map.h
    engines/xeen/scripts.cpp



diff --git a/engines/xeen/character.cpp b/engines/xeen/character.cpp
index 04f8325..737c36a 100644
--- a/engines/xeen/character.cpp
+++ b/engines/xeen/character.cpp
@@ -1855,5 +1855,4 @@ int Character::getClassCategory() const {
 	}
 }
 
-
 } // End of namespace Xeen
diff --git a/engines/xeen/combat.cpp b/engines/xeen/combat.cpp
index 5142015..776821a 100644
--- a/engines/xeen/combat.cpp
+++ b/engines/xeen/combat.cpp
@@ -77,6 +77,8 @@ static const int MONSTER_SHOOT_POW[7] = { 12, 14, 0, 4, 8, 10, 13 };
 
 static const int COMBAT_SHOOTING[4] = { 1, 1, 2, 3 };
 
+#define monsterSavingThrow(MONINDEX) (_vm->getRandomNumber(1, 50 + MONINDEX) <= MONINDEX)
+
 /*------------------------------------------------------------------------*/
 
 Combat::Combat(XeenEngine *vm): _vm(vm) {
@@ -91,6 +93,7 @@ Combat::Combat(XeenEngine *vm): _vm(vm) {
 	Common::fill(&_monsterMoved[0], &_monsterMoved[MAX_NUM_MONSTERS], false);
 	Common::fill(&_rangeAttacking[0], &_rangeAttacking[MAX_NUM_MONSTERS], false);
 	Common::fill(&_gmonHit[0], &_gmonHit[36], 0);
+	Common::fill(&_missedShot[0], &_missedShot[MAX_PARTY_COUNT], 0);
 	_globalCombat = 0;
 	_whosTurn = -1;
 	_itemFlag = false;
@@ -102,6 +105,9 @@ Combat::Combat(XeenEngine *vm): _vm(vm) {
 	_whosSpeed = 0;
 	_damageType = DT_PHYSICAL;
 	_oldCharacter = nullptr;
+	_shootType = 0;
+	_monsterDamage = 0;
+	_weaponDamage = 0;
 }
 
 void Combat::clear() {
@@ -455,7 +461,7 @@ void Combat::moveMonsters() {
 								// Check for range attacks
 								if (monsterData._rangeAttack && !_rangeAttacking[idx]
 									&& _attackMonsters[0] != idx && _attackMonsters[1] != idx
-									&& _attackMonsters[2] != idx && !monster._field7) {
+									&& _attackMonsters[2] != idx && !monster._damageType) {
 									// Setup monster for attacking
 									setupMonsterAttack(monster._spriteId, pt);
 									_rangeAttacking[idx] = true;
@@ -683,7 +689,7 @@ void Combat::moveMonster(int monsterId, const Common::Point &pt) {
 	Map &map = *_vm->_map;
 	MazeMonster &monster = map._mobData._monsters[monsterId];
 
-	if (_monsterMap[pt.y][pt.x] < 3 && !monster._field7 && _vm->_moveMonsters) {
+	if (_monsterMap[pt.y][pt.x] < 3 && !monster._damageType && _vm->_moveMonsters) {
 		++_monsterMap[pt.y][pt.x];
 		--_monsterMap[monster._position.y][monster._position.x];
 		monster._position = pt;
@@ -731,10 +737,10 @@ void Combat::monsterOvercome() {
 		MazeMonster &monster = map._mobData._monsters[idx];
 		int dataIndex = monster._spriteId;
 
-		if (monster._field7 != 0 && monster._field7 != 13) {
+		if (monster._damageType != 0 && monster._damageType != 13) {
 			// Do a saving throw for monster
 			if (dataIndex <= _vm->getRandomNumber(1, dataIndex + 50))
-				monster._field7 = 0;
+				monster._damageType = 0;
 		}
 	}
 }
@@ -768,7 +774,7 @@ void Combat::attackMonster(int monsterId) {
 
 	MazeMonster &monster = map._mobData._monsters[monsterIndex];
 	MonsterStruct &monsterData = map._monsterData[monster._spriteId];
-	if (monster._field7)
+	if (monster._damageType)
 		return;
 
 	monster._frame = 8;
@@ -1153,7 +1159,210 @@ Common::String Combat::getMonsterDescriptions() {
 		lines[1].c_str(), lines[2].c_str());
 }
 
-void Combat::attack(Character &c, int v2) {
+void Combat::attack(Character &c, int ranged) {
+	Interface &intf = *_vm->_interface;
+	Map &map = *_vm->_map;
+	Party &party = *_vm->_party;
+	int damage = _monsterDamage;
+
+	if (_monster2Attack == -1)
+		return;
+
+	MazeMonster &monster = map._mobData._monsters[_monster2Attack];
+	int monsterDataIndex = monster._spriteId;
+	MonsterStruct &monsterData = map._monsterData[monsterDataIndex];
+
+	if (ranged) {
+		if (_shootType != 1 || _damageType == DT_MAGIC_ARROW) {
+			if (!monsterData._magicResistence || monsterData._magicResistence <=
+					_vm->getRandomNumber(1, 100 + _oldCharacter->getCurrentLevel())) {
+				if (_monsterDamage != 0) {
+					attack2(damage, ranged);
+					setSpeedTable();
+				} else {
+					switch (_damageType) {
+					case DT_SLEEP:
+						if (monsterData._monsterType == MONSTER_ANIMAL || monsterData._monsterType == MONSTER_HUMANOID) {
+							if (_vm->getRandomNumber(1, 50 + monsterDataIndex) > monsterDataIndex)
+								monster._damageType = DT_SLEEP;
+						}
+						break;
+					case DT_FINGEROFDEATH:
+						if ((monsterData._monsterType == MONSTER_ANIMAL || monsterData._monsterType == MONSTER_HUMANOID)
+							&& !monsterSavingThrow(monsterDataIndex)) {
+							damage = MIN(monster._hp, 50);
+							attack2(damage, 2);
+							setSpeedTable();
+						}
+						break;
+					case DT_HOLYWORD:
+						if (monsterData._monsterType == MONSTER_UNDEAD) {
+							attack2(monster._hp, 2);
+							setSpeedTable();
+						}
+						break;
+					case DT_MASS_DISTORTION:
+						attack2(MAX(monster._hp / 2, 1), 2);
+						setSpeedTable();
+						break;
+					case DT_UNDEAD:
+						if (monsterData._monsterType == MONSTER_UNDEAD)
+							damage = 25;
+						else
+							ranged = 2;
+						attack2(damage, ranged);
+						setSpeedTable();
+						break;
+					case DT_BEASTMASTER:
+						if ((monsterData._monsterType == MONSTER_ANIMAL || monsterData._monsterType == MONSTER_HUMANOID)
+							&& !monsterSavingThrow(monsterDataIndex)) {
+							monster._damageType = DT_BEASTMASTER;
+						}
+						break;
+					case DT_DRAGONSLEEP:
+						if (monsterData._monsterType == MONSTER_DRAGON && !monsterSavingThrow(monsterDataIndex))
+							monster._damageType = DT_DRAGONSLEEP;
+						break;
+					case DT_GOLEMSTOPPER:
+						if (monsterData._monsterType == MONSTER_GOLEM) {
+							attack2(100, ranged);
+							setSpeedTable();
+						}
+						break;
+					case DT_HYPNOTIZE:
+						if ((monsterData._monsterType == MONSTER_ANIMAL || monsterData._monsterType == MONSTER_HUMANOID)
+							&& !monsterSavingThrow(monsterDataIndex)) {
+							monster._damageType = _damageType;
+						}
+						break;
+					case DT_INSECT_SPRAY:
+						if (monsterData._monsterType == MONSTER_INSECT) {
+							attack2(25, ranged);
+							setSpeedTable();
+						}
+						break;
+					case DT_MAGIC_ARROW:
+						attack2(8, ranged);
+						setSpeedTable();
+						break;
+					default:
+						break;
+					}
+				}
+			} 
+		} else {
+			Common::fill(&_elemPow[0], &_elemPow[PARTY_AND_MONSTERS], 0);
+			damage = 0;
+
+			for (uint charIndex = 0; charIndex < party._activeParty.size(); ++charIndex) {
+				Character &c = party._activeParty[charIndex];
+
+				if (_shooting[charIndex] && !_missedShot[charIndex]) {
+					if (!hitMonster(c, ranged)) {
+						++_missedShot[charIndex];
+					} else {
+						damage = _monsterDamage ? _monsterDamage : _weaponDamage;
+						_shooting[charIndex] = 0;
+						attack2(damage, ranged);
+
+						if (map._isOutdoors) {
+							intf._outdoorList._attackImgs1[charIndex]._scale = 0;
+							intf._outdoorList._attackImgs1[charIndex]._sprites = nullptr;
+							intf._outdoorList._attackImgs2[charIndex]._scale = 0;
+							intf._outdoorList._attackImgs2[charIndex]._sprites = nullptr;
+							intf._outdoorList._attackImgs3[charIndex]._scale = 0;
+							intf._outdoorList._attackImgs3[charIndex]._sprites = nullptr;
+							intf._outdoorList._attackImgs4[charIndex]._scale = 0;
+							intf._outdoorList._attackImgs4[charIndex]._sprites = nullptr;
+						} else {
+							intf._indoorList._attackImgs1[charIndex]._scale = 0;
+							intf._indoorList._attackImgs1[charIndex]._sprites = nullptr;
+							intf._indoorList._attackImgs2[charIndex]._scale = 0;
+							intf._indoorList._attackImgs2[charIndex]._sprites = nullptr;
+							intf._indoorList._attackImgs3[charIndex]._scale = 0;
+							intf._indoorList._attackImgs3[charIndex]._sprites = nullptr;
+							intf._indoorList._attackImgs4[charIndex]._scale = 0;
+							intf._indoorList._attackImgs4[charIndex]._sprites = nullptr;
+						}
+
+						if (_monster2Attack == -1)
+							return;
+					}
+				}
+			}
+		}
+	} else {
+		_damageType = DT_PHYSICAL;
+		int divisor = 0;
+		switch (c._class) {
+		case CLASS_BARBARIAN:
+			divisor = 4;
+			break;
+		case CLASS_KNIGHT:
+		case CLASS_NINJA:
+			divisor = 5;
+			break;
+		case CLASS_PALADIN:
+		case CLASS_ARCHER:
+		case CLASS_ROBBER:
+		case CLASS_RANGER:
+			divisor = 6;
+			break;
+		case CLASS_CLERIC:
+		case CLASS_DRUID:
+			divisor = 7;
+			break;
+		case CLASS_SORCERER:
+			divisor = 8;
+			break;
+		}
+
+		int numberOfAttacks = c.getCurrentLevel() / divisor;
+		damage = 0;
+
+		while (numberOfAttacks-- > 0) {
+			if (hitMonster(c, 0))
+				damage += getMonsterDamage(c);
+		}
+
+		for (int itemIndex = 0; itemIndex < INV_ITEMS_TOTAL; ++itemIndex) {
+			XeenItem &weapon = c._weapons[itemIndex];
+			if (weapon._frame != 0) {
+				switch (weapon._bonusFlags & ITEMFLAG_BONUS_MASK) {
+				case 1:
+					if (monsterData._monsterType == MONSTER_DRAGON)
+						damage *= 3;
+					break;
+				case 2:
+					if (monsterData._monsterType == MONSTER_UNDEAD)
+						damage *= 3;
+					break;
+				case 3:
+					if (monsterData._monsterType == MONSTER_GOLEM)
+						damage *= 3;
+					break;
+				case 4:
+					if (monsterData._monsterType == MONSTER_INSECT)
+						damage *= 3;
+					break;
+				case 5:
+					if (monsterData._monsterType == MONSTER_0)
+						damage *= 3;
+					break;
+				case 6:
+					if (monsterData._monsterType == MONSTER_ANIMAL)
+						damage *= 3;
+					break;
+				}
+			}
+		}
+
+		attack2(damage, ranged);
+		setSpeedTable();
+	}
+}
+
+void Combat::attack2(int damage, int ranged) {
 	error("TODO");
 }
 
@@ -1213,4 +1422,17 @@ void Combat::run() {
 	}
 }
 
+bool Combat::hitMonster(Character &c, int ranged) {
+	error("TODO");
+}
+
+bool Combat::getWeaponDamage(Character &c, int ranged) {
+	error("TODO");
+}
+
+int Combat::getMonsterDamage(Character &c) {
+	error("TODO");
+}
+
+
 } // End of namespace Xeen
diff --git a/engines/xeen/combat.h b/engines/xeen/combat.h
index 60adbca..1e1ca82 100644
--- a/engines/xeen/combat.h
+++ b/engines/xeen/combat.h
@@ -30,12 +30,13 @@
 namespace Xeen {
 
 #define MAX_NUM_MONSTERS 107
+#define PARTY_AND_MONSTERS 11
 
 enum DamageType {
 	DT_PHYSICAL = 0, DT_MAGICAL = 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_UNDEAD = 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
 };
@@ -55,6 +56,14 @@ class Character;
 class Combat {
 private:
 	XeenEngine *_vm;
+
+	void attack2(int damage, int ranged);
+
+	bool hitMonster(Character &c, int ranged);
+
+	bool getWeaponDamage(Character &c, int ranged);
+
+	int getMonsterDamage(Character &c);
 public:
 	Common::Array<Character *> _combatParty;
 	Common::Array<bool> _charsBlocked;
@@ -62,11 +71,12 @@ public:
 	SpriteResource _powSprites;
 	int _attackMonsters[26];
 	int _monster2Attack;
-	int _charsArray1[12];
-	bool _monPow[12];
-	int _monsterScale[12];
-	int _elemPow[12];
-	int _elemScale[12];
+	int _charsArray1[PARTY_AND_MONSTERS];
+	bool _monPow[PARTY_AND_MONSTERS];
+	int _monsterScale[PARTY_AND_MONSTERS];
+	int _elemPow[PARTY_AND_MONSTERS];
+	int _elemScale[PARTY_AND_MONSTERS];
+	int _missedShot[8];
 	Common::Array<int> _speedTable;
 	int _shooting[8];
 	int _globalCombat;
@@ -83,23 +93,9 @@ public:
 	int _whosSpeed;
 	DamageType _damageType;
 	Character *_oldCharacter;
-
-	void monstersAttack();
-
-	void setupMonsterAttack(int monsterDataIndex, const Common::Point &pt);
-
-	bool monsterCanMove(const Common::Point &pt, int wallShift,
-		int v1, int v2, int monsterId);
-
-	void moveMonster(int monsterId, const Common::Point &pt);
-
-	void attackMonster(int monsterId);
-
-	void endAttack();
-
-	void monsterOvercome();
-	
-	int stopAttack(const Common::Point &diffPt);
+	int _shootType;
+	int _monsterDamage;
+	int _weaponDamage;
 public:
 	Combat(XeenEngine *vm);
 
@@ -121,7 +117,7 @@ public:
 
 	Common::String getMonsterDescriptions();
 
-	void attack(Character &c, int v2);
+	void attack(Character &c, int ranged);
 
 	void block();
 
@@ -130,6 +126,23 @@ public:
 	void giveTreasure();
 
 	void run();
+
+	void monstersAttack();
+
+	void setupMonsterAttack(int monsterDataIndex, const Common::Point &pt);
+
+	bool monsterCanMove(const Common::Point &pt, int wallShift,
+		int v1, int v2, int monsterId);
+
+	void moveMonster(int monsterId, const Common::Point &pt);
+
+	void attackMonster(int monsterId);
+
+	void endAttack();
+
+	void monsterOvercome();
+
+	int stopAttack(const Common::Point &diffPt);
 };
 
 } // End of namespace Xeen
diff --git a/engines/xeen/dialogs_spells.cpp b/engines/xeen/dialogs_spells.cpp
index 0383886..ea423aa 100644
--- a/engines/xeen/dialogs_spells.cpp
+++ b/engines/xeen/dialogs_spells.cpp
@@ -51,7 +51,7 @@ Character *SpellsDialog::execute(ButtonContainer *priorDialog, Character *c, int
 	int castingCopy = isCasting;
 	isCasting &= 0x7f;
 	int selection = -1;
-	uint topIndex = 0;
+	int topIndex = 0;
 	int newSelection;
 	screen._windows[25].open();
 
@@ -87,7 +87,7 @@ Character *SpellsDialog::execute(ButtonContainer *priorDialog, Character *c, int
 		Common::fill(&colors[0], &colors[10], 9);
 
 		for (int idx = 0; idx < 10; ++idx) {
-			if ((topIndex + idx) < _spells.size()) {
+			if ((topIndex + idx) < (int)_spells.size()) {
 				names[idx] = _spells[topIndex + idx]._name.c_str();
 				colors[idx] = _spells[topIndex + idx]._color;
 			}
@@ -256,7 +256,7 @@ Character *SpellsDialog::execute(ButtonContainer *priorDialog, Character *c, int
 
 		case Common::KEYCODE_PAGEDOWN:
 		case Common::KEYCODE_KP3:
-			topIndex = MIN(topIndex + 10, ((_spells.size() - 1) / 10) * 10);
+			topIndex = MIN(topIndex + 10, (((int)_spells.size() - 1) / 10) * 10);
 			break;
 
 		case Common::KEYCODE_UP:
@@ -267,7 +267,7 @@ Character *SpellsDialog::execute(ButtonContainer *priorDialog, Character *c, int
 
 		case Common::KEYCODE_DOWN:
 		case Common::KEYCODE_KP2:
-			if (topIndex < (_spells.size() - 10))
+			if (topIndex < ((int)_spells.size() - 10))
 				++topIndex;
 			break;
 		}
diff --git a/engines/xeen/interface_map.cpp b/engines/xeen/interface_map.cpp
index d6d15d6..8032369 100644
--- a/engines/xeen/interface_map.cpp
+++ b/engines/xeen/interface_map.cpp
@@ -705,7 +705,7 @@ void InterfaceMap::animate3d() {
 
 	for (uint idx = 0; idx < map._mobData._monsters.size(); ++idx) {
 		MazeMonster &monster = map._mobData._monsters[idx];
-		if (!monster._field7) {
+		if (!monster._damageType) {
 			if (monster._frame < 8) {
 				MonsterStruct &monsterData = map._monsterData[monster._spriteId];
 				if (!monsterData._loopAnimation) {
diff --git a/engines/xeen/map.cpp b/engines/xeen/map.cpp
index 01c050a..10fba6d 100644
--- a/engines/xeen/map.cpp
+++ b/engines/xeen/map.cpp
@@ -652,7 +652,7 @@ MazeMonster::MazeMonster() {
 	_id = 0;
 	_spriteId = 0;
 	_isAttacking = false;
-	_field7 = 0;
+	_damageType = DT_PHYSICAL;
 	_field9 = 0;
 	_fieldA = 0;
 	_hp = 0;
diff --git a/engines/xeen/map.h b/engines/xeen/map.h
index 05ead5b..7faf59f 100644
--- a/engines/xeen/map.h
+++ b/engines/xeen/map.h
@@ -245,7 +245,7 @@ struct MazeMonster {
 	int _id;
 	int _spriteId;
 	bool _isAttacking;
-	int _field7;
+	int _damageType;
 	int _field9;
 	int _fieldA;
 	int _hp;
diff --git a/engines/xeen/scripts.cpp b/engines/xeen/scripts.cpp
index 37222a3..8b38889 100644
--- a/engines/xeen/scripts.cpp
+++ b/engines/xeen/scripts.cpp
@@ -508,7 +508,7 @@ void Scripts::cmdSpawn(Common::Array<byte> &params) {
 	monster._position.x = params[1];
 	monster._position.y = params[2];
 	monster._frame = _vm->getRandomNumber(7);
-	monster._field7 = 0;
+	monster._damageType = 0;
 	monster._isAttacking = params[1] != 0;
 	monster._hp = monsterData._hp;
 


Commit: b790e9bac1ee20482cbea6056dcf084bd85c0da5
    https://github.com/scummvm/scummvm/commit/b790e9bac1ee20482cbea6056dcf084bd85c0da5
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-02-20T23:57:45-05:00

Commit Message:
XEEN: Implemented attack2

Changed paths:
    engines/xeen/character.h
    engines/xeen/combat.cpp
    engines/xeen/combat.h
    engines/xeen/items.cpp
    engines/xeen/items.h
    engines/xeen/module.mk
    engines/xeen/party.cpp
    engines/xeen/party.h
    engines/xeen/scripts.cpp
    engines/xeen/scripts.h
    engines/xeen/xeen.h



diff --git a/engines/xeen/character.h b/engines/xeen/character.h
index 6acd433..372014f 100644
--- a/engines/xeen/character.h
+++ b/engines/xeen/character.h
@@ -74,11 +74,6 @@ enum Condition {
 	NO_CONDITION = 16
 };
 
-enum ElementalCategory { 
-	ELEM_FIRE = 0, ELEM_ELECTRICITY = 1, ELEM_COLD = 2,
-	ELEM_ACID_POISON = 3, ELEM_ENERGY = 4, ELEM_MAGIC = 5 
-};
-
 enum AttributeCategory {
 	ATTR_MIGHT = 0, ATTR_INTELLECT = 1, ATTR_PERSONALITY = 2, ATTR_SPEED = 3,
 	ATTR_ACCURACY = 4, ATTR_LUCK = 5, ATTR_HIT_POINTS = 6, ATTR_SPELL_POINTS = 7,
diff --git a/engines/xeen/combat.cpp b/engines/xeen/combat.cpp
index 776821a..a8b5a50 100644
--- a/engines/xeen/combat.cpp
+++ b/engines/xeen/combat.cpp
@@ -77,16 +77,27 @@ static const int MONSTER_SHOOT_POW[7] = { 12, 14, 0, 4, 8, 10, 13 };
 
 static const int COMBAT_SHOOTING[4] = { 1, 1, 2, 3 };
 
-#define monsterSavingThrow(MONINDEX) (_vm->getRandomNumber(1, 50 + MONINDEX) <= MONINDEX)
+static const int DAMAGE_TYPE_EFFECTS[19] = {
+	3, 10, 4, 11, 1, 2, 5, 9, 5, 14, 5, 14, 10, 8, 3, 9, 2, 2, 3
+};
+
+static const int POW_WEAPON_VOCS[35] = {
+	0, 5, 4, 5, 5, 5, 5, 2, 4, 5, 3, 5, 4, 2, 3, 2, 2, 4, 5, 5,
+	5, 5, 5, 1, 3, 2, 5, 1, 1, 1, 0, 0, 0, 2, 2
+};
+
+static const int MONSTER_ITEM_RANGES[6] = { 10, 20, 50, 100, 100, 100 };
+
+#define monsterSavingThrow(MONINDEX) (_vm->getRandomNumber(1, 50 + (MONINDEX)) <= (MONINDEX))
 
 /*------------------------------------------------------------------------*/
 
-Combat::Combat(XeenEngine *vm): _vm(vm) {
+Combat::Combat(XeenEngine *vm): _vm(vm), _missVoc("miss.voc"), _pow1Voc("pow1.voc") {
 	Common::fill(&_attackMonsters[0], &_attackMonsters[26], 0);
 	Common::fill(&_charsArray1[0], &_charsArray1[12], 0);
 	Common::fill(&_monPow[0], &_monPow[12], 0);
 	Common::fill(&_monsterScale[0], &_monsterScale[12], 0);
-	Common::fill(&_elemPow[0], &_elemPow[12], 0);
+	Common::fill(&_elemPow[0], &_elemPow[12], ELEM_FIRE);
 	Common::fill(&_elemScale[0], &_elemScale[12], 0);
 	Common::fill(&_shooting[0], &_shooting[8], 0);
 	Common::fill(&_monsterMap[0][0], &_monsterMap[32][32], 0);
@@ -108,6 +119,7 @@ Combat::Combat(XeenEngine *vm): _vm(vm) {
 	_shootType = 0;
 	_monsterDamage = 0;
 	_weaponDamage = 0;
+	_attackWeapon = nullptr;
 }
 
 void Combat::clear() {
@@ -1251,7 +1263,7 @@ void Combat::attack(Character &c, int ranged) {
 				}
 			} 
 		} else {
-			Common::fill(&_elemPow[0], &_elemPow[PARTY_AND_MONSTERS], 0);
+			Common::fill(&_elemPow[0], &_elemPow[PARTY_AND_MONSTERS], ELEM_FIRE);
 			damage = 0;
 
 			for (uint charIndex = 0; charIndex < party._activeParty.size(); ++charIndex) {
@@ -1363,7 +1375,193 @@ void Combat::attack(Character &c, int ranged) {
 }
 
 void Combat::attack2(int damage, int ranged) {
-	error("TODO");
+	Interface &intf = *_vm->_interface;
+	Map &map = *_vm->_map;
+	Party &party = *_vm->_party;
+	SoundManager &sound = *_vm->_sound;
+	bool isDarkCc = _vm->_files->_isDarkCc;
+	MazeMonster &monster = map._mobData._monsters[_monster2Attack];
+	MonsterStruct &monsterData = map._monsterData[monster._spriteId];
+	bool monsterDied = false;
+
+	if (!isDarkCc && damage && ranged && monster._spriteId == 89)
+		damage = 0;
+
+	if (!damage) {
+		sound.playSample(&_missVoc, 1);
+		sound.playFX(6);
+	} else {
+		if (!isDarkCc && monster._spriteId == 89)
+			damage += 100;
+		if (monster._damageType == DT_SLEEP || monster._damageType == DT_DRAGONSLEEP)
+			monster._damageType = DT_PHYSICAL;
+		
+		if ((!ranged || !_damageType) && _attackWeapon->_id != 34) {
+			if (monsterData._phsyicalResistence != 0) {
+				if (monsterData._phsyicalResistence == 100) {
+					damage = 0;
+				} else {
+					// This doesn't seem to have any effect?
+					damage = (damage * 100) / 100;
+				}
+			}
+		}
+
+		if (damage) {
+			_charsArray1[_monsterIndex] = 3;
+			_monPow[_monsterIndex] = _damageType == DT_PHYSICAL && (ranged == 3 || ranged == 0);
+			monster._frame = 11;
+			monster._fieldA = 5;
+		}
+
+		int monsterResist = getMonsterResistence(ranged);
+		damage += monsterResist;
+		if (monsterResist > 0) {
+			_elemPow[_monsterIndex] = _attackWeapon->getElementalCategory();
+			_elemScale[_monsterIndex] = getDamageScale(monsterResist);
+		} else if (ranged != 3) {
+			_elemPow[_monsterIndex] = ELEM_FIRE;
+		}
+
+		if (ranged != 0 && ranged != 3) {
+			monster._effect2 = DAMAGE_TYPE_EFFECTS[_damageType];
+			monster._effect1 = 0;
+		}
+
+		if (ranged && monsterSavingThrow(monster._spriteId)) {
+			switch (_damageType) {
+			case DT_FINGEROFDEATH:
+			case DT_MASS_DISTORTION:
+				damage = 5;
+				break;
+			case DT_SLEEP:
+			case DT_HOLYWORD:
+			case DT_UNDEAD:
+			case DT_BEASTMASTER:
+			case DT_DRAGONSLEEP:
+			case DT_GOLEMSTOPPER:
+			case DT_HYPNOTIZE:
+			case DT_INSECT_SPRAY:
+			case DT_MAGIC_ARROW:
+				break;
+			default:
+				damage /= 2;
+				break;
+			}
+		}
+		
+		if (damage < 1) {
+			sound.playSample(&_missVoc, 1);
+			sound.playFX(6);
+		} else {
+			_monsterScale[_monsterIndex] = getDamageScale(damage);
+			intf.draw3d(true);
+			
+			sound.playSample(nullptr, 0);
+			File powVoc(Common::String::format("pow%d.voc",
+				POW_WEAPON_VOCS[_attackWeapon->_id]));
+			sound.playFX(60 + POW_WEAPON_VOCS[_attackWeapon->_id]);
+			sound.playSample(&powVoc, 1);
+
+			if (monster._hp > damage) {
+				monster._hp -= damage;
+			} else {
+				monster._hp = 0;
+				monsterDied = true;
+			}
+		}
+	}
+
+	intf.draw3d(true);
+
+	if (monsterDied) {
+		if (!isDarkCc) {
+			if (_monster2Attack == 20 && party._mazeId == 41)
+				party._gameFlags[11] = true;
+			if (_monster2Attack == 8 && party._mazeId == 78) {
+				party._gameFlags[60] = true;
+				party._quests[23] = false;
+
+				for (uint idx = 0; idx < party._activeParty.size(); ++idx)
+					party._activeParty[idx].setAward(42, true);
+
+				if (_monster2Attack == 27 && party._mazeId == 29)
+					party._gameFlags[104] = true;
+			}
+		}
+
+		giveExperience(monsterData._experience);
+
+		if (party._mazeId != 85) {
+			party._treasure._gold = monsterData._gold;
+			party._treasure._gems = monsterData._gems;
+
+			if (!isDarkCc && monster._spriteId == 89) {
+				party._treasure._weapons[0]._id = 90;
+				party._treasure._weapons[0]._bonusFlags = 0;
+				party._treasure._weapons[0]._material = 0;
+				party._treasure._hasItems = true;
+				party._questItems[8]++;
+			}
+
+			int itemDrop = monsterData._itemDrop;
+			if (itemDrop) {
+				if (MONSTER_ITEM_RANGES[itemDrop] >= _vm->getRandomNumber(1, 100)) {
+					Character tempChar;
+					int category = tempChar.makeItem(itemDrop, 0, 0);
+					
+					switch (category) {
+					case CATEGORY_WEAPON:
+						for (int idx = 0; idx < MAX_TREASURE_ITEMS; ++idx) {
+							if (party._treasure._weapons[idx]._id == 0) {
+								party._treasure._weapons[idx] = tempChar._weapons[0];
+								party._treasure._hasItems = 1;
+								break;
+							}
+						}
+						break;
+					case CATEGORY_ARMOR:
+						for (int idx = 0; idx < MAX_TREASURE_ITEMS; ++idx) {
+							if (party._treasure._armor[idx]._id == 0) {
+								party._treasure._armor[idx] = tempChar._armor[0];
+								party._treasure._hasItems = 1;
+								break;
+							}
+						}
+						break;
+					case CATEGORY_ACCESSORY:
+						for (int idx = 0; idx < MAX_TREASURE_ITEMS; ++idx) {
+							if (party._treasure._accessories[idx]._id == 0) {
+								party._treasure._accessories[idx] = tempChar._accessories[0];
+								party._treasure._hasItems = 1;
+								break;
+							}
+						}
+						break;
+					case CATEGORY_MISC:
+						for (int idx = 0; idx < MAX_TREASURE_ITEMS; ++idx) {
+							if (party._treasure._accessories[idx]._id == 0) {
+								party._treasure._accessories[idx] = tempChar._accessories[0];
+								party._treasure._hasItems = 1;
+								break;
+							}
+						}
+						break;
+					}
+				}
+			}
+		}
+
+		monster._position = Common::Point(0x80, 0x80);
+		_charsArray1[_monsterIndex] = 0;
+		_monster2Attack = -1;
+		intf.draw3d(true);
+
+		if (_attackMonsters[0] != -1) {
+			_monster2Attack = _attackMonsters[0];
+			_monsterIndex = 0;
+		}
+	}
 }
 
 /**
@@ -1434,5 +1632,22 @@ int Combat::getMonsterDamage(Character &c) {
 	error("TODO");
 }
 
+int Combat::getDamageScale(int v) {
+	if (v < 10)
+		return 5;
+	else if (v < 100)
+		return 0;
+	else
+		return 0x8000;
+}
+
+int Combat::getMonsterResistence(int ranged) {
+	error("TODO");
+}
+
+void Combat::giveExperience(int experience) {
+	error("TODO");
+}
+
 
 } // End of namespace Xeen
diff --git a/engines/xeen/combat.h b/engines/xeen/combat.h
index 1e1ca82..75614cc 100644
--- a/engines/xeen/combat.h
+++ b/engines/xeen/combat.h
@@ -25,6 +25,7 @@
 
 #include "common/scummsys.h"
 #include "common/rect.h"
+#include "xeen/files.h"
 #include "xeen/sprites.h"
 
 namespace Xeen {
@@ -50,8 +51,14 @@ enum SpecialAttack {
 	SA_ERADICATE = 19, SA_AGING = 20, SA_DEATH = 21, SA_STONE = 22
 };
 
+enum ElementalCategory {
+	ELEM_FIRE = 0, ELEM_ELECTRICITY = 1, ELEM_COLD = 2,
+	ELEM_ACID_POISON = 3, ELEM_ENERGY = 4, ELEM_MAGIC = 5
+};
+
 class XeenEngine;
 class Character;
+class XeenItem;
 
 class Combat {
 private:
@@ -64,6 +71,12 @@ private:
 	bool getWeaponDamage(Character &c, int ranged);
 
 	int getMonsterDamage(Character &c);
+
+	int getDamageScale(int v);
+
+	int getMonsterResistence(int ranged);
+
+	void giveExperience(int experience);
 public:
 	Common::Array<Character *> _combatParty;
 	Common::Array<bool> _charsBlocked;
@@ -74,7 +87,7 @@ public:
 	int _charsArray1[PARTY_AND_MONSTERS];
 	bool _monPow[PARTY_AND_MONSTERS];
 	int _monsterScale[PARTY_AND_MONSTERS];
-	int _elemPow[PARTY_AND_MONSTERS];
+	ElementalCategory _elemPow[PARTY_AND_MONSTERS];
 	int _elemScale[PARTY_AND_MONSTERS];
 	int _missedShot[8];
 	Common::Array<int> _speedTable;
@@ -96,6 +109,8 @@ public:
 	int _shootType;
 	int _monsterDamage;
 	int _weaponDamage;
+	XeenItem *_attackWeapon;
+	File _missVoc, _pow1Voc;
 public:
 	Combat(XeenEngine *vm);
 
diff --git a/engines/xeen/items.cpp b/engines/xeen/items.cpp
index b9b531d..e8c0249 100644
--- a/engines/xeen/items.cpp
+++ b/engines/xeen/items.cpp
@@ -25,8 +25,5 @@
 
 namespace Xeen {
 
-Treasure::Treasure() {
-	_hasItems = false;
-}
 
 } // End of namespace Xeen
diff --git a/engines/xeen/items.h b/engines/xeen/items.h
index 1e20861..bfbd9e4 100644
--- a/engines/xeen/items.h
+++ b/engines/xeen/items.h
@@ -27,18 +27,7 @@
 
 namespace Xeen {
 
-#define TOTAL_ITEMS 10
 
-class Treasure {
-public:
-	XeenItem _misc[TOTAL_ITEMS];
-	XeenItem _accessories[TOTAL_ITEMS];
-	XeenItem _armor[TOTAL_ITEMS];
-	XeenItem _weapons[TOTAL_ITEMS];
-	bool _hasItems;
-public:
-	Treasure();
-};
 
 } // End of namespace Xeen
 
diff --git a/engines/xeen/module.mk b/engines/xeen/module.mk
index a17311c..1fe29c6 100644
--- a/engines/xeen/module.mk
+++ b/engines/xeen/module.mk
@@ -32,7 +32,6 @@ MODULE_OBJS := \
 	font.o \
 	interface.o \
 	interface_map.o \
-	items.o \
 	map.o \
 	party.o \
 	resources.o \
diff --git a/engines/xeen/party.cpp b/engines/xeen/party.cpp
index 993f156..ab8abd7 100644
--- a/engines/xeen/party.cpp
+++ b/engines/xeen/party.cpp
@@ -57,6 +57,13 @@ void Roster::synchronize(Common::Serializer &s) {
 
 /*------------------------------------------------------------------------*/
 
+Treasure::Treasure() {
+	_hasItems = false;
+	_gold = _gems = 0;
+}
+
+/*------------------------------------------------------------------------*/
+
 XeenEngine *Party::_vm;
 
 Party::Party(XeenEngine *vm) {
diff --git a/engines/xeen/party.h b/engines/xeen/party.h
index 5d98c55..841fcd3 100644
--- a/engines/xeen/party.h
+++ b/engines/xeen/party.h
@@ -48,6 +48,7 @@ enum Difficulty { ADVENTURER = 0, WARRIOR = 1 };
 #define TOTAL_STATS 7
 #define TOTAL_QUEST_ITEMS 85
 #define TOTAL_QUEST_FLAGS 56
+#define MAX_TREASURE_ITEMS 10
 
 class Roster: public Common::Array<Character> {
 public:
@@ -58,6 +59,18 @@ public:
 	void synchronize(Common::Serializer &s);
 };
 
+class Treasure {
+public:
+	XeenItem _misc[MAX_TREASURE_ITEMS];
+	XeenItem _accessories[MAX_TREASURE_ITEMS];
+	XeenItem _armor[MAX_TREASURE_ITEMS];
+	XeenItem _weapons[MAX_TREASURE_ITEMS];
+	bool _hasItems;
+	int _gems, _gold;
+public:
+	Treasure();
+};
+
 class Party {
 	friend class Character;
 	friend class InventoryItems;
@@ -124,6 +137,7 @@ public:
 	int _fallDamage;
 	DamageType _damageType;
 	bool _dead;
+	Treasure _treasure;
 public:
 	Party(XeenEngine *vm);
 
diff --git a/engines/xeen/scripts.cpp b/engines/xeen/scripts.cpp
index 8b38889..7aab04c 100644
--- a/engines/xeen/scripts.cpp
+++ b/engines/xeen/scripts.cpp
@@ -92,8 +92,6 @@ Scripts::Scripts(XeenEngine *vm) : _vm(vm) {
 	_whoWill = 0;
 	_itemType = 0;
 	_treasureItems = 0;
-	_treasureGold = 0;
-	_treasureGems = 0;
 	_lineNum = 0;
 	_charIndex = 0;
 	_v2 = 0;
@@ -125,7 +123,7 @@ int Scripts::checkEvents() {
 	Common::fill(&_charFX[0], &_charFX[MAX_ACTIVE_PARTY], 0);
 	//int items = _treasureItems;
 	
-	if (_treasureGold & _treasureItems) {
+	if (party._treasure._gold & party._treasure._gems) {
 		// TODO
 	} else {
 		// TODO
@@ -591,6 +589,7 @@ void Scripts::cmdGiveExtended(Common::Array<byte> &params) {
 
 void Scripts::cmdConfirmWord(Common::Array<byte> &params) { 
 	Map &map = *_vm->_map;
+	Party &party = *_vm->_party;
 	Common::String msg1 = params[2] ? map._events._text[params[2]] :
 		_vm->_interface->_interfaceText;
 	Common::String msg2;
@@ -621,13 +620,13 @@ void Scripts::cmdConfirmWord(Common::Array<byte> &params) {
 			doWorldEnd();
 		} else {		
 			if (result == 59 && !_vm->_files->_isDarkCc) {
-				for (int idx = 0; idx < TOTAL_ITEMS; ++idx) {
-					XeenItem &item = _vm->_treasure._weapons[idx];
+				for (int idx = 0; idx < MAX_TREASURE_ITEMS; ++idx) {
+					XeenItem &item = party._treasure._weapons[idx];
 					if (!item._id) {
 						item._id = 34;
 						item._material = 0;
 						item._bonusFlags = 0;
-						_vm->_treasure._hasItems = true;
+						party._treasure._hasItems = true;
 						
 						cmdExit(params);
 						return;
diff --git a/engines/xeen/scripts.h b/engines/xeen/scripts.h
index cc32a96..1db672b 100644
--- a/engines/xeen/scripts.h
+++ b/engines/xeen/scripts.h
@@ -141,8 +141,6 @@ private:
 	XeenEngine *_vm;
 	int _charFX[6];
 	int _treasureItems;
-	int _treasureGold;
-	int _treasureGems;
 	int _lineNum;
 	int _charIndex;
 	int _mirrorId;
diff --git a/engines/xeen/xeen.h b/engines/xeen/xeen.h
index d0a72f5..76cb1c1 100644
--- a/engines/xeen/xeen.h
+++ b/engines/xeen/xeen.h
@@ -149,7 +149,6 @@ public:
 	SoundManager *_sound;
 	Spells *_spells;
 	Town *_town;
-	Treasure _treasure;
 	Mode _mode;
 	GameEvent _gameEvent;
 	Common::SeekableReadStream *_eventData;


Commit: c5a98b0093330589dc269fe337a60cf0e1508785
    https://github.com/scummvm/scummvm/commit/c5a98b0093330589dc269fe337a60cf0e1508785
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-02-21T10:43:27-05:00

Commit Message:
XEEN: Implement more combat methods

Changed paths:
    engines/xeen/combat.cpp
    engines/xeen/combat.h
    engines/xeen/interface.cpp
    engines/xeen/party.cpp
    engines/xeen/party.h



diff --git a/engines/xeen/combat.cpp b/engines/xeen/combat.cpp
index a8b5a50..4b9ddd6 100644
--- a/engines/xeen/combat.cpp
+++ b/engines/xeen/combat.cpp
@@ -119,7 +119,10 @@ Combat::Combat(XeenEngine *vm): _vm(vm), _missVoc("miss.voc"), _pow1Voc("pow1.vo
 	_shootType = 0;
 	_monsterDamage = 0;
 	_weaponDamage = 0;
+	_weaponDie = _weaponDice = 0;
 	_attackWeapon = nullptr;
+	_attackWeaponId = 0;
+	_hitChanceBonus = 0;
 }
 
 void Combat::clear() {
@@ -1171,7 +1174,7 @@ Common::String Combat::getMonsterDescriptions() {
 		lines[1].c_str(), lines[2].c_str());
 }
 
-void Combat::attack(Character &c, int ranged) {
+void Combat::attack(Character &c, RangeType rangeType) {
 	Interface &intf = *_vm->_interface;
 	Map &map = *_vm->_map;
 	Party &party = *_vm->_party;
@@ -1184,12 +1187,12 @@ void Combat::attack(Character &c, int ranged) {
 	int monsterDataIndex = monster._spriteId;
 	MonsterStruct &monsterData = map._monsterData[monsterDataIndex];
 
-	if (ranged) {
+	if (rangeType) {
 		if (_shootType != 1 || _damageType == DT_MAGIC_ARROW) {
 			if (!monsterData._magicResistence || monsterData._magicResistence <=
 					_vm->getRandomNumber(1, 100 + _oldCharacter->getCurrentLevel())) {
 				if (_monsterDamage != 0) {
-					attack2(damage, ranged);
+					attack2(damage, rangeType);
 					setSpeedTable();
 				} else {
 					switch (_damageType) {
@@ -1203,26 +1206,26 @@ void Combat::attack(Character &c, int ranged) {
 						if ((monsterData._monsterType == MONSTER_ANIMAL || monsterData._monsterType == MONSTER_HUMANOID)
 							&& !monsterSavingThrow(monsterDataIndex)) {
 							damage = MIN(monster._hp, 50);
-							attack2(damage, 2);
+							attack2(damage, RT_2);
 							setSpeedTable();
 						}
 						break;
 					case DT_HOLYWORD:
 						if (monsterData._monsterType == MONSTER_UNDEAD) {
-							attack2(monster._hp, 2);
+							attack2(monster._hp, RT_2);
 							setSpeedTable();
 						}
 						break;
 					case DT_MASS_DISTORTION:
-						attack2(MAX(monster._hp / 2, 1), 2);
+						attack2(MAX(monster._hp / 2, 1), RT_2);
 						setSpeedTable();
 						break;
 					case DT_UNDEAD:
 						if (monsterData._monsterType == MONSTER_UNDEAD)
 							damage = 25;
 						else
-							ranged = 2;
-						attack2(damage, ranged);
+							rangeType = RT_2;
+						attack2(damage, rangeType);
 						setSpeedTable();
 						break;
 					case DT_BEASTMASTER:
@@ -1237,7 +1240,7 @@ void Combat::attack(Character &c, int ranged) {
 						break;
 					case DT_GOLEMSTOPPER:
 						if (monsterData._monsterType == MONSTER_GOLEM) {
-							attack2(100, ranged);
+							attack2(100, rangeType);
 							setSpeedTable();
 						}
 						break;
@@ -1249,12 +1252,12 @@ void Combat::attack(Character &c, int ranged) {
 						break;
 					case DT_INSECT_SPRAY:
 						if (monsterData._monsterType == MONSTER_INSECT) {
-							attack2(25, ranged);
+							attack2(25, rangeType);
 							setSpeedTable();
 						}
 						break;
 					case DT_MAGIC_ARROW:
-						attack2(8, ranged);
+						attack2(8, rangeType);
 						setSpeedTable();
 						break;
 					default:
@@ -1270,12 +1273,12 @@ void Combat::attack(Character &c, int ranged) {
 				Character &c = party._activeParty[charIndex];
 
 				if (_shooting[charIndex] && !_missedShot[charIndex]) {
-					if (!hitMonster(c, ranged)) {
+					if (!hitMonster(c, rangeType)) {
 						++_missedShot[charIndex];
 					} else {
 						damage = _monsterDamage ? _monsterDamage : _weaponDamage;
 						_shooting[charIndex] = 0;
-						attack2(damage, ranged);
+						attack2(damage, rangeType);
 
 						if (map._isOutdoors) {
 							intf._outdoorList._attackImgs1[charIndex]._scale = 0;
@@ -1333,7 +1336,7 @@ void Combat::attack(Character &c, int ranged) {
 		damage = 0;
 
 		while (numberOfAttacks-- > 0) {
-			if (hitMonster(c, 0))
+			if (hitMonster(c, RT_0))
 				damage += getMonsterDamage(c);
 		}
 
@@ -1369,12 +1372,12 @@ void Combat::attack(Character &c, int ranged) {
 			}
 		}
 
-		attack2(damage, ranged);
+		attack2(damage, rangeType);
 		setSpeedTable();
 	}
 }
 
-void Combat::attack2(int damage, int ranged) {
+void Combat::attack2(int damage, RangeType rangeType) {
 	Interface &intf = *_vm->_interface;
 	Map &map = *_vm->_map;
 	Party &party = *_vm->_party;
@@ -1384,7 +1387,7 @@ void Combat::attack2(int damage, int ranged) {
 	MonsterStruct &monsterData = map._monsterData[monster._spriteId];
 	bool monsterDied = false;
 
-	if (!isDarkCc && damage && ranged && monster._spriteId == 89)
+	if (!isDarkCc && damage && rangeType && monster._spriteId == 89)
 		damage = 0;
 
 	if (!damage) {
@@ -1396,7 +1399,7 @@ void Combat::attack2(int damage, int ranged) {
 		if (monster._damageType == DT_SLEEP || monster._damageType == DT_DRAGONSLEEP)
 			monster._damageType = DT_PHYSICAL;
 		
-		if ((!ranged || !_damageType) && _attackWeapon->_id != 34) {
+		if ((!rangeType || !_damageType) && _attackWeaponId != 34) {
 			if (monsterData._phsyicalResistence != 0) {
 				if (monsterData._phsyicalResistence == 100) {
 					damage = 0;
@@ -1409,26 +1412,26 @@ void Combat::attack2(int damage, int ranged) {
 
 		if (damage) {
 			_charsArray1[_monsterIndex] = 3;
-			_monPow[_monsterIndex] = _damageType == DT_PHYSICAL && (ranged == 3 || ranged == 0);
+			_monPow[_monsterIndex] = _damageType == DT_PHYSICAL && (rangeType == 3 || rangeType == 0);
 			monster._frame = 11;
 			monster._fieldA = 5;
 		}
 
-		int monsterResist = getMonsterResistence(ranged);
+		int monsterResist = getMonsterResistence(rangeType);
 		damage += monsterResist;
 		if (monsterResist > 0) {
 			_elemPow[_monsterIndex] = _attackWeapon->getElementalCategory();
 			_elemScale[_monsterIndex] = getDamageScale(monsterResist);
-		} else if (ranged != 3) {
+		} else if (rangeType != 3) {
 			_elemPow[_monsterIndex] = ELEM_FIRE;
 		}
 
-		if (ranged != 0 && ranged != 3) {
+		if (rangeType != 0 && rangeType != 3) {
 			monster._effect2 = DAMAGE_TYPE_EFFECTS[_damageType];
 			monster._effect1 = 0;
 		}
 
-		if (ranged && monsterSavingThrow(monster._spriteId)) {
+		if (rangeType && monsterSavingThrow(monster._spriteId)) {
 			switch (_damageType) {
 			case DT_FINGEROFDEATH:
 			case DT_MASS_DISTORTION:
@@ -1459,8 +1462,8 @@ void Combat::attack2(int damage, int ranged) {
 			
 			sound.playSample(nullptr, 0);
 			File powVoc(Common::String::format("pow%d.voc",
-				POW_WEAPON_VOCS[_attackWeapon->_id]));
-			sound.playFX(60 + POW_WEAPON_VOCS[_attackWeapon->_id]);
+				POW_WEAPON_VOCS[_attackWeaponId]));
+			sound.playFX(60 + POW_WEAPON_VOCS[_attackWeaponId]);
 			sound.playSample(&powVoc, 1);
 
 			if (monster._hp > damage) {
@@ -1580,7 +1583,7 @@ void Combat::quickFight() {
 
 	switch (c->_quickOption) {
 	case QUICK_ATTACK:
-		attack(*c, 0);
+		attack(*c, RT_0);
 		break;
 	case QUICK_SPELL:
 		if (c->_currentSpell != -1) {
@@ -1598,10 +1601,6 @@ void Combat::quickFight() {
 	}
 }
 
-void Combat::giveTreasure() {
-	error("TODO: giveTreasure");
-}
-
 /**
  * Current selected character is trying to run away
  */
@@ -1620,16 +1619,98 @@ void Combat::run() {
 	}
 }
 
-bool Combat::hitMonster(Character &c, int ranged) {
-	error("TODO");
+bool Combat::hitMonster(Character &c, RangeType rangeType) {
+	Map &map = *_vm->_map;
+	getWeaponDamage(c, rangeType);
+	int chance = c.statBonus(c.getStat(ACCURACY)) + _hitChanceBonus;
+	int divisor;
+	
+	switch (c._class) {
+	case CLASS_KNIGHT:
+	case CLASS_BARBARIAN:
+		divisor = 1;
+		break;
+	case CLASS_PALADIN :
+	case CLASS_ARCHER:
+	case CLASS_ROBBER:
+	case CLASS_NINJA:
+	case CLASS_RANGER:
+		divisor = 2;
+		break;
+	case CLASS_CLERIC:
+	case CLASS_DRUID:
+		divisor = 3;
+		break;
+	case CLASS_SORCERER:
+		divisor = 4;
+		break;
+	}
+
+	chance += c.getCurrentLevel() / divisor;
+	chance -= c._conditions[CURSED];
+
+	// Add on a random amount
+	int v;
+	do {
+		v = _vm->getRandomNumber(1, 20);
+		chance += v;
+	} while (v == 20);
+
+	assert(_monster2Attack != -1);
+	MazeMonster &monster = map._mobData._monsters[_monster2Attack];
+	MonsterStruct &monsterData = map._monsterData[monster._spriteId];
+
+	if (monster._damageType != DT_PHYSICAL)
+		chance += 20;
+
+	return chance >= (monsterData._accuracy + 10);
 }
 
-bool Combat::getWeaponDamage(Character &c, int ranged) {
-	error("TODO");
+void Combat::getWeaponDamage(Character &c, RangeType rangeType) {
+	Party &party = *_vm->_party;
+	_attackWeapon = nullptr;
+	_weaponDie = _weaponDice = 0;
+	_weaponDamage = 0;
+	_hitChanceBonus = 0;
+
+	for (int idx = 0; idx < INV_ITEMS_TOTAL; ++idx) {
+		bool flag;
+		if (rangeType) {
+			flag = c._weapons[idx]._frame == 4;
+		} else {
+			flag = c._weapons[idx]._frame == 1 || c._weapons[idx]._frame == 13;
+		}
+
+		if (flag) {
+			if (!(c._weapons[idx]._bonusFlags & (ITEMFLAG_BROKEN | ITEMFLAG_CURSED))) {
+				_attackWeapon = &c._weapons[idx];
+
+				if (c._weapons[idx]._material >= 37 && c._weapons[idx]._material < 59) {
+					_hitChanceBonus = METAL_DAMAGE_PERCENT[c._weapons[idx]._material - 37];
+					_weaponDamage = METAL_DAMAGE[c._weapons[idx]._material - 37];
+				}
+			}
+
+			_hitChanceBonus += party._heroism;
+			_attackWeaponId = c._weapons[idx]._id;
+			_weaponDice = WEAPON_DAMAGE_BASE[_attackWeaponId];
+			_weaponDie = WEAPON_DAMAGE_MULTIPLIER[_attackWeaponId];
+
+			for (int diceIdx = 0; diceIdx < _weaponDice; ++diceIdx)
+				_weaponDamage += _vm->getRandomNumber(1, _weaponDie);
+		}
+	}
+
+	if (_weaponDamage < 1)
+		_weaponDamage = 0;
+	if (!party._difficulty) {
+		_hitChanceBonus += 5;
+		_weaponDamage *= 3;
+	}
 }
 
 int Combat::getMonsterDamage(Character &c) {
-	error("TODO");
+	return (c.statBonus(c.getStat(MIGHT)) + _weaponDamage) < 1;
 }
 
 int Combat::getDamageScale(int v) {
@@ -1641,13 +1722,97 @@ int Combat::getDamageScale(int v) {
 		return 0x8000;
 }
 
-int Combat::getMonsterResistence(int ranged) {
-	error("TODO");
+int Combat::getMonsterResistence(RangeType rangeType) {
+	Map &map = *_vm->_map;
+	assert(_monster2Attack != -1);
+	MazeMonster &monster = map._mobData._monsters[_monster2Attack];
+	MonsterStruct &monsterData = map._monsterData[monster._spriteId];
+	int resistence = 0, damage = 0;
+
+	if (rangeType != RT_0 && rangeType != RT_3) {
+		switch (_damageType) {
+		case DT_PHYSICAL:
+			resistence = monsterData._phsyicalResistence;
+			break;
+		case DT_MAGICAL:
+			resistence = monsterData._magicResistence;
+			break;
+		case DT_FIRE:
+			resistence = monsterData._fireResistence;
+			break;
+		case DT_ELECTRICAL:
+			resistence = monsterData._electricityResistence;
+			break;
+		case DT_COLD:
+			resistence = monsterData._coldResistence;
+			break;
+		case DT_POISON:
+			resistence = monsterData._poisonResistence;
+			break;
+		case DT_ENERGY:
+			resistence = monsterData._energyResistence;
+			break;
+		default:
+			break;
+		}
+	} else {
+		int material = !_attackWeapon ? 0 : _attackWeapon->_material;
+		damage = ELEMENTAL_DAMAGE[material];
+
+		if (material != 0) {
+			if (material < 9)
+				resistence = monsterData._fireResistence;
+			else if (material < 16)
+				resistence = monsterData._electricityResistence;
+			else if (material < 21)
+				resistence = monsterData._coldResistence;
+			else if (material < 26)
+				resistence = monsterData._poisonResistence;
+			else if (material < 34)
+				resistence = monsterData._energyResistence;
+			else
+				resistence = monsterData._magicResistence;			
+		}
+	}
+
+	if (resistence != 0) {
+		if (resistence == 100)
+			return 0;
+		else
+			return ((100 - resistence) * damage) / 100;
+	} 
+
+	return damage;
 }
 
+/**
+ * Distribute experience between active party members
+ */
 void Combat::giveExperience(int experience) {
-	error("TODO");
-}
+	Party &party = *_vm->_party;
+	bool inCombat = _vm->_mode == MODE_COMBAT;
+	int count = 0;
 
+	// Two loops: first to figure out how many active characters there are,
+	// and the second to distribute the experience between them
+	for (int loopNum = 0; loopNum < 2; ++loopNum) {
+		for (uint charIndex = 0; charIndex < (inCombat ? _combatParty.size() :
+				party._activeParty.size()); ++charIndex) {
+			Character &c = inCombat ? *_combatParty[charIndex] : party._activeParty[charIndex];
+			Condition condition = c.worstCondition();
+
+			if (condition != DEAD && condition != STONED && condition != ERADICATED) {
+				if (loopNum == 0) {
+					++count;
+				} else {
+					int exp = experience / count;
+					if (c._level._permanent < 15)
+						exp /= 2;
+					c._experience += exp;
+				}
+			}
+		}
+	}
+}
 
 } // End of namespace Xeen
diff --git a/engines/xeen/combat.h b/engines/xeen/combat.h
index 75614cc..466152a 100644
--- a/engines/xeen/combat.h
+++ b/engines/xeen/combat.h
@@ -56,6 +56,10 @@ enum ElementalCategory {
 	ELEM_ACID_POISON = 3, ELEM_ENERGY = 4, ELEM_MAGIC = 5
 };
 
+enum RangeType {
+	RT_0 = 0, RT_1 = 1, RT_2 = 2, RT_3 = 3
+};
+
 class XeenEngine;
 class Character;
 class XeenItem;
@@ -64,17 +68,17 @@ class Combat {
 private:
 	XeenEngine *_vm;
 
-	void attack2(int damage, int ranged);
+	void attack2(int damage, RangeType rangeType);
 
-	bool hitMonster(Character &c, int ranged);
+	bool hitMonster(Character &c, RangeType rangeType);
 
-	bool getWeaponDamage(Character &c, int ranged);
+	void getWeaponDamage(Character &c, RangeType rangeType);
 
 	int getMonsterDamage(Character &c);
 
 	int getDamageScale(int v);
 
-	int getMonsterResistence(int ranged);
+	int getMonsterResistence(RangeType rangeType);
 
 	void giveExperience(int experience);
 public:
@@ -109,8 +113,11 @@ public:
 	int _shootType;
 	int _monsterDamage;
 	int _weaponDamage;
+	int _weaponDie, _weaponDice;
 	XeenItem *_attackWeapon;
+	int _attackWeaponId;
 	File _missVoc, _pow1Voc;
+	int _hitChanceBonus;
 public:
 	Combat(XeenEngine *vm);
 
@@ -132,14 +139,12 @@ public:
 
 	Common::String getMonsterDescriptions();
 
-	void attack(Character &c, int ranged);
+	void attack(Character &c, RangeType rangeType);
 
 	void block();
 
 	void quickFight();
 
-	void giveTreasure();
-
 	void run();
 
 	void monstersAttack();
diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp
index 0420658..1b3ee4f3 100644
--- a/engines/xeen/interface.cpp
+++ b/engines/xeen/interface.cpp
@@ -1957,7 +1957,7 @@ void Interface::doCombat() {
 
 			case Common::KEYCODE_a:
 				// Attack
-				combat.attack(*combat._combatParty[combat._whosTurn], 0);
+				combat.attack(*combat._combatParty[combat._whosTurn], RT_0);
 				nextChar();
 				break;
 
@@ -2113,7 +2113,7 @@ void Interface::doCombat() {
 
 		_vm->_mode = MODE_COMBAT;
 		draw3d(true);
-		combat.giveTreasure();
+		party.giveTreasure();
 		_vm->_mode = MODE_1;
 		party._stepped = true;
 		unhighlightChar();
diff --git a/engines/xeen/party.cpp b/engines/xeen/party.cpp
index ab8abd7..aede424 100644
--- a/engines/xeen/party.cpp
+++ b/engines/xeen/party.cpp
@@ -559,4 +559,32 @@ void Party::moveToRunLocation() {
 	_mazePosition = _vm->_map->mazeData()._runPosition;
 }
 
+/**
+ * Give treasure to the party
+ */
+void Party::giveTreasure() {
+	Combat &combat = *_vm->_combat;
+	Interface &intf = *_vm->_interface;
+	SoundManager &sound = *_vm->_sound;
+
+	if (!_treasure._gold && !_treasure._gems)
+		return;
+
+	bool monstersPresent = false;
+	for (int idx = 0; idx < 26 && !monstersPresent; ++idx)
+		monstersPresent = combat._attackMonsters[idx] != -1;
+
+	if (_vm->_mode != MODE_9 && monstersPresent)
+		return;
+
+	Common::fill(&combat._shooting[0], &combat._shooting[MAX_PARTY_COUNT], 0);
+	intf._charsShooting = false;
+	intf.draw3d(true);
+
+	if (_treasure._gold || _treasure._gems)
+		sound.playFX(54);
+
+	error("TODO");
+}
+
 } // End of namespace Xeen
diff --git a/engines/xeen/party.h b/engines/xeen/party.h
index 841fcd3..483476c 100644
--- a/engines/xeen/party.h
+++ b/engines/xeen/party.h
@@ -166,6 +166,8 @@ public:
 	void checkPartyDead();
 
 	void moveToRunLocation();
+
+	void giveTreasure();
 };
 
 } // End of namespace Xeen


Commit: f49b1f9b4377af9693c5b1c1fdea162425c0c2b6
    https://github.com/scummvm/scummvm/commit/f49b1f9b4377af9693c5b1c1fdea162425c0c2b6
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-02-21T14:34:49-05:00

Commit Message:
XEEN: Implemented giveTreasure

Changed paths:
    engines/xeen/character.cpp
    engines/xeen/character.h
    engines/xeen/party.cpp
    engines/xeen/party.h
    engines/xeen/resources.cpp
    engines/xeen/resources.h



diff --git a/engines/xeen/character.cpp b/engines/xeen/character.cpp
index 737c36a..e005a35 100644
--- a/engines/xeen/character.cpp
+++ b/engines/xeen/character.cpp
@@ -228,6 +228,14 @@ void InventoryItems::enchantItem(int itemIndex, int amount) {
 	ErrorScroll::show(vm, Common::String::format(NOT_ENCHANTABLE, SPELL_FAILED));
 }
 
+/**
+ * Return if the given inventory items list is full
+ */
+bool InventoryItems::isFull() const {
+	return operator[](size() - 1)._id != 0;
+}
+
+
 /*------------------------------------------------------------------------*/
 
 /**
diff --git a/engines/xeen/character.h b/engines/xeen/character.h
index 372014f..9e858da 100644
--- a/engines/xeen/character.h
+++ b/engines/xeen/character.h
@@ -39,7 +39,8 @@ enum BonusFlags {
 };
 
 enum ItemCategory {
-	CATEGORY_WEAPON = 0, CATEGORY_ARMOR = 1, CATEGORY_ACCESSORY = 2, CATEGORY_MISC = 3
+	CATEGORY_WEAPON = 0, CATEGORY_ARMOR = 1, CATEGORY_ACCESSORY = 2, CATEGORY_MISC = 3,
+	NUM_ITEM_CATEGORIES = 4
 };
 
 enum Sex { MALE = 0, FEMALE = 1, YES_PLEASE = 2 };
@@ -140,6 +141,8 @@ public:
 	void sort();
 
 	virtual void enchantItem(int itemIndex, int amount);
+
+	bool isFull() const;
 };
 
 class WeaponItems: public InventoryItems {
diff --git a/engines/xeen/party.cpp b/engines/xeen/party.cpp
index aede424..268dfcc 100644
--- a/engines/xeen/party.cpp
+++ b/engines/xeen/party.cpp
@@ -60,6 +60,11 @@ void Roster::synchronize(Common::Serializer &s) {
 Treasure::Treasure() {
 	_hasItems = false;
 	_gold = _gems = 0;
+
+	_categories[0] = &_weapons[0];
+	_categories[1] = &_armor[0];
+	_categories[2] = &_accessories[0];
+	_categories[3] = &_misc[0];
 }
 
 /*------------------------------------------------------------------------*/
@@ -564,8 +569,12 @@ void Party::moveToRunLocation() {
  */
 void Party::giveTreasure() {
 	Combat &combat = *_vm->_combat;
+	EventsManager &events = *_vm->_events;
 	Interface &intf = *_vm->_interface;
+	Screen &screen = *_vm->_screen;
+	Scripts &scripts = *_vm->_scripts;
 	SoundManager &sound = *_vm->_sound;
+	Window &w = screen._windows[10];
 
 	if (!_treasure._gold && !_treasure._gems)
 		return;
@@ -584,7 +593,146 @@ void Party::giveTreasure() {
 	if (_treasure._gold || _treasure._gems)
 		sound.playFX(54);
 
-	error("TODO");
+	events.clearEvents();
+	w.close();
+	w.open();
+	w.writeString(Common::String::format(PARTY_FOUND, _treasure._gold, _treasure._gems));
+	w.update();
+
+	if (_vm->_mode != MODE_COMBAT)
+		_vm->_mode = MODE_7;
+
+	if (arePacksFull())
+		ErrorScroll::show(_vm, BACKPACKS_FULL_PRESS_KEY, WT_NONFREEZED_WAIT);
+
+	for (int categoryNum = 0; categoryNum < NUM_ITEM_CATEGORIES; ++categoryNum) {
+		for (int itemNum = 0; itemNum < MAX_TREASURE_ITEMS; ++itemNum) {
+			if (arePacksFull()) {
+				if (_treasure._weapons[itemNum]._id == 34) {
+					// Important item, so clear a slot for it
+					_activeParty[0]._weapons[INV_ITEMS_TOTAL - 1].clear();
+				} else {
+					// Otherwise, clear all the remaining treasure items, 
+					// since all the party's packs are full
+					for (int idx = 0; idx < MAX_TREASURE_ITEMS; ++idx) {
+						_treasure._weapons[idx].clear();
+						_treasure._armor[idx].clear();
+						_treasure._accessories[idx].clear();
+						_treasure._armor[idx].clear();
+					}
+				}
+			}
+
+			// If there's no treasure item to be distributed, skip to next slot
+			if (!_treasure._categories[categoryNum][itemNum]._id)
+				continue;
+
+			int charIndex = scripts._whoWill - 1;
+			if (charIndex >= 0 && charIndex < (int)_activeParty.size()) {
+				// Check the designated character first
+				Character &c = _activeParty[charIndex];
+				if (!c._items[(ItemCategory)categoryNum].isFull() && !c.isDisabledOrDead()) {
+					giveTreasureToCharacter(c, (ItemCategory)categoryNum, itemNum);
+					continue;
+				}
+
+				// Fall back on checking the entire conscious party
+				for (charIndex = 0; charIndex < (int)_activeParty.size(); ++charIndex) {
+					Character &c = _activeParty[charIndex];
+					if (!c._items[(ItemCategory)categoryNum].isFull() && !c.isDisabledOrDead()) {
+						giveTreasureToCharacter(c, (ItemCategory)categoryNum, itemNum);
+						break;
+					}
+				}
+				if (charIndex != (int)_activeParty.size())
+					continue;
+			}
+
+			// At this point, find an empty pack for any character, irrespective
+			// of whether the character is conscious or not
+			for (charIndex = 0; charIndex < (int)_activeParty.size(); ++charIndex) {
+				Character &c = _activeParty[charIndex];
+				if (!c._items[(ItemCategory)categoryNum].isFull() && !c.isDisabledOrDead()) {
+					giveTreasureToCharacter(c, (ItemCategory)categoryNum, itemNum);
+					continue;
+				}
+			}
+		}
+	}
+
+	w.writeString(HIT_A_KEY);
+	w.update();
+
+	do {
+		events.updateGameCounter();
+		intf.draw3d(true);
+
+		while (!events.isKeyMousePressed() && events.timeElapsed() < 1)
+			events.pollEventsAndWait();
+	} while (!_vm->shouldQuit() && events.timeElapsed() == 1);
+	
+	if (_vm->_mode != MODE_COMBAT)
+		_vm->_mode = MODE_1;
+
+	w.close();
+	_gold += _treasure._gold;
+	_gems += _treasure._gems;
+	_treasure._gold = 0;
+	_treasure._gems = 0;
+	
+	_treasure._hasItems = false;
+	for (int idx = 0; idx < MAX_TREASURE_ITEMS; ++idx) {
+		_treasure._weapons[idx].clear();
+		_treasure._armor[idx].clear();
+		_treasure._accessories[idx].clear();
+		_treasure._armor[idx].clear();
+	}
+
+	scripts._v2 = 1;
+}
+
+/**
+ * Returns true if all the packs for all the characters are full
+ */
+bool Party::arePacksFull() const {
+	uint total = 0;
+	for (uint idx = 0; idx < _activeParty.size(); ++idx) {
+		const Character &c = _activeParty[idx];
+		total += (c._weapons[INV_ITEMS_TOTAL - 1]._id != 0 ? 1 : 0)
+			+ (c._armor[INV_ITEMS_TOTAL - 1]._id != 0 ? 1 : 0)
+			+ (c._accessories[INV_ITEMS_TOTAL - 1]._id != 0 ? 1 : 0)
+			+ (c._misc[INV_ITEMS_TOTAL - 1]._id != 0 ? 1 : 0);
+	}
+
+	return total == (_activeParty.size() * NUM_ITEM_CATEGORIES);
+}
+
+/**
+ * Give a treasure item to the given character's inventory
+ */
+void Party::giveTreasureToCharacter(Character &c, ItemCategory category, int itemIndex) {
+	EventsManager &events = *_vm->_events;
+	Screen &screen = *_vm->_screen;
+	SoundManager &sound = *_vm->_sound;
+	Window &w = screen._windows[10];
+	XeenItem &treasureItem = _treasure._categories[category][itemIndex];
+	sound.playFX(20);
+	
+	if (treasureItem._id < 82) {
+		// Copy item into the character's inventory
+		c._items[category][INV_ITEMS_TOTAL - 1] = treasureItem;
+		c._items[category].sort();
+	}
+
+	w.writeString(GIVE_TREASURE_FORMATTING);
+	w.update();
+	events.ipause(5);
+
+	w.writeString(Common::String::format(X_FOUND_Y, c._name.c_str(),
+		ITEM_NAMES[category][treasureItem._id]));
+	w.update();
+
+	events.ipause(5);
 }
 
 } // End of namespace Xeen
diff --git a/engines/xeen/party.h b/engines/xeen/party.h
index 483476c..b5e31f9 100644
--- a/engines/xeen/party.h
+++ b/engines/xeen/party.h
@@ -65,6 +65,7 @@ public:
 	XeenItem _accessories[MAX_TREASURE_ITEMS];
 	XeenItem _armor[MAX_TREASURE_ITEMS];
 	XeenItem _weapons[MAX_TREASURE_ITEMS];
+	XeenItem *_categories[4];
 	bool _hasItems;
 	int _gems, _gold;
 public:
@@ -76,6 +77,8 @@ class Party {
 	friend class InventoryItems;
 private:
 	static XeenEngine *_vm;
+
+	void giveTreasureToCharacter(Character &c, ItemCategory category, int itemIndex);
 public:
 	// Dynamic data that's saved
 	Direction _mazeDirection;
@@ -168,6 +171,8 @@ public:
 	void moveToRunLocation();
 
 	void giveTreasure();
+
+	bool arePacksFull() const;
 };
 
 } // End of namespace Xeen
diff --git a/engines/xeen/resources.cpp b/engines/xeen/resources.cpp
index da57a80..bcf408d 100644
--- a/engines/xeen/resources.cpp
+++ b/engines/xeen/resources.cpp
@@ -1097,6 +1097,7 @@ const char *const BONUS_NAMES[7] = {
 	"", "Dragon Slayer", "Undead Eater", "Golem Smasher",
 	"Bug Zapper", "Monster Masher", "Beast Bopper"
 };
+
 const char *const WEAPON_NAMES[35] = {
 	nullptr, "long sword ", "short sword ", "broad sword ", "scimitar ", 
 	"cutlass ", "sabre ", "club ", "hand axe ", "katana ", "nunchakas ", 
@@ -1124,6 +1125,10 @@ const char *const MISC_NAMES[22] = {
 	"bogus", "bogus", "bogus", "bogus"
 };
 
+const char *const *ITEM_NAMES[4] = {
+	&WEAPON_NAMES[0], &ARMOR_NAMES[0], &ACCESSORY_NAMES[0], &MISC_NAMES[0]
+};
+
 const char *const ELEMENTAL_NAMES[6] = {
 	"Fire", "Elec", "Cold", "Acid/Poison", "Energy", "Magic"
 };
@@ -1501,4 +1506,26 @@ const char *const CAST_SPELL_DETAILS =
 	"\v082Cost\x3r\t000%u/%u\x3l\n"
 	"Cur SP\x3r\t000%u\x1";
 
+const char *const PARTY_FOUND =
+	"\x3""cThe Party Found:\n"
+	"\n"
+	"\x3r\t000%lu Gold\n"
+	"%lu Gems";
+
+const char *const BACKPACKS_FULL_PRESS_KEY =
+	"\v007\f12Warning!  BackPacks Full!\fd\n"
+	"Press a Key";
+
+const char *const HIT_A_KEY = "\x3l\v120\t000\x4""077\x3""c\f37Hit a key\f'd";
+
+const char *const GIVE_TREASURE_FORMATTING =
+	"\x3l\v060\t000\x4""077\n"
+	"\x4""077\n"
+	"\x4""077\n"
+	"\x4""077\n"
+	"\x4""077\n"
+	"\x4""077";
+
+const char *const X_FOUND_Y = "\v060\t000\x03c%s found: %s";
+
 } // End of namespace Xeen
diff --git a/engines/xeen/resources.h b/engines/xeen/resources.h
index c617844..c98db7f 100644
--- a/engines/xeen/resources.h
+++ b/engines/xeen/resources.h
@@ -384,6 +384,8 @@ extern const char *const WEAPON_NAMES[35];
 extern const char *const ARMOR_NAMES[14];
 extern const char *const ACCESSORY_NAMES[11];
 extern const char *const MISC_NAMES[22];
+extern const char *const *ITEM_NAMES[4];
+
 extern const char *const ELEMENTAL_NAMES[6];
 extern const char *const ATTRIBUTE_NAMES[10];
 extern const char *const EFFECTIVENESS_NAMES[7];
@@ -527,6 +529,16 @@ extern const char *SPELL_CAST_COMPONENTS[2];
 
 extern const char *const CAST_SPELL_DETAILS;
 
+extern const char *const PARTY_FOUND;
+
+extern const char *const BACKPACKS_FULL_PRESS_KEY;
+
+extern const char *const HIT_A_KEY;
+
+extern const char *const GIVE_TREASURE_FORMATTING;
+
+extern const char *const X_FOUND_Y;
+
 } // End of namespace Xeen
 
 #endif	/* XEEN_RESOURCES_H */


Commit: c99a901f65dbb61ad961d8c70be41fd6620ca840
    https://github.com/scummvm/scummvm/commit/c99a901f65dbb61ad961d8c70be41fd6620ca840
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-02-21T14:41:57-05:00

Commit Message:
XEEN: More code for dismiss dialog

Changed paths:
    engines/xeen/dialogs_dismiss.cpp



diff --git a/engines/xeen/dialogs_dismiss.cpp b/engines/xeen/dialogs_dismiss.cpp
index 1317d84..9323b46 100644
--- a/engines/xeen/dialogs_dismiss.cpp
+++ b/engines/xeen/dialogs_dismiss.cpp
@@ -45,7 +45,8 @@ void Dismiss::execute() {
 	_iconSprites.draw(w, 0, Common::Point(225, 120));
 	w.update();
 
-	while (!_vm->shouldQuit()) {
+	bool breakFlag = false;
+	while (!_vm->shouldQuit() && !breakFlag) {
 		do {
 			events.updateGameCounter();
 			intf.draw3d(false);
@@ -70,17 +71,14 @@ void Dismiss::execute() {
 					ErrorScroll::show(_vm, CANT_DISMISS_LAST_CHAR, WT_NONFREEZED_WAIT);
 					w.open();
 				} else {
-					Character tempChar = party._activeParty[_buttonValue];
-					int charIndex = party._activeParty[_buttonValue]._rosterId;
-
-//					party.sortParty();
-
-					// TODO
+					// Remove the character from the party
+					party._activeParty.remove_at(_buttonValue);
+					breakFlag = true;
 				}
 				break;
 			}
 		} else if (_buttonValue == Common::KEYCODE_ESCAPE) {
-			
+			breakFlag = true;
 		}
 	}
 }


Commit: 458bf83097036f90a090eb97194fad395ca3c8e1
    https://github.com/scummvm/scummvm/commit/458bf83097036f90a090eb97194fad395ca3c8e1
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-02-21T22:11:23-05:00

Commit Message:
XEEN: Restrict sprite drawing to window bounds

Changed paths:
    engines/xeen/dialogs.cpp
    engines/xeen/dialogs.h
    engines/xeen/screen.h
    engines/xeen/sprites.cpp
    engines/xeen/sprites.h



diff --git a/engines/xeen/dialogs.cpp b/engines/xeen/dialogs.cpp
index 116054d..77cdd92 100644
--- a/engines/xeen/dialogs.cpp
+++ b/engines/xeen/dialogs.cpp
@@ -24,6 +24,7 @@
 #include "xeen/dialogs.h"
 #include "xeen/events.h"
 #include "xeen/resources.h"
+#include "xeen/screen.h"
 #include "xeen/xeen.h"
 
 namespace Xeen {
diff --git a/engines/xeen/dialogs.h b/engines/xeen/dialogs.h
index c04b680..6e809ba 100644
--- a/engines/xeen/dialogs.h
+++ b/engines/xeen/dialogs.h
@@ -27,6 +27,7 @@
 #include "common/stack.h"
 #include "common/rect.h"
 #include "xeen/sprites.h"
+#include "xeen/xsurface.h"
 
 namespace Xeen {
 
diff --git a/engines/xeen/screen.h b/engines/xeen/screen.h
index 526fd6f..f8f11a4 100644
--- a/engines/xeen/screen.h
+++ b/engines/xeen/screen.h
@@ -80,6 +80,8 @@ public:
 
 	void setBounds(const Common::Rect &r);
 
+	const Common::Rect &getBounds() { return _bounds; }
+
 	void open();
 
 	void close();
diff --git a/engines/xeen/sprites.cpp b/engines/xeen/sprites.cpp
index 7bffa68..2c5279b 100644
--- a/engines/xeen/sprites.cpp
+++ b/engines/xeen/sprites.cpp
@@ -25,6 +25,7 @@
 #include "common/memstream.h"
 #include "common/textconsole.h"
 #include "xeen/xeen.h"
+#include "xeen/screen.h"
 #include "xeen/sprites.h"
 
 namespace Xeen {
@@ -110,7 +111,8 @@ void SpriteResource::clear() {
 /**
  * Draws a frame using data at a specific offset in the sprite resource
  */
-void SpriteResource::drawOffset(XSurface &dest, uint16 offset, const Common::Point &destPos, int flags) const {
+void SpriteResource::drawOffset(XSurface &dest, uint16 offset, const Common::Point &destPos, 
+		const Common::Rect &bounds, int flags) const {
 	// Get cell header
 	Common::MemoryReadStream f(_data, _filesize);
 	f.seek(offset);
@@ -139,14 +141,14 @@ void SpriteResource::drawOffset(XSurface &dest, uint16 offset, const Common::Poi
 		if (lineLength == 0) {
 			// Skip the specified number of scan lines
 			yPos += f.readByte();
-		} else if ((destPos.y + yPos) < 0 || (destPos.y + yPos) >= dest.h) {
+		} else if ((destPos.y + yPos) < bounds.top || (destPos.y + yPos) >= bounds.bottom) {
 			// Skip over the bytes of the line
 			f.skip(lineLength);
 		} else {
 			// Skip the transparent pixels at the beginning of the scan line
 			int xPos = f.readByte() + xOffset; ++byteCount;
-			const byte *lineStartP = (const byte *)dest.getBasePtr(0, destPos.y + yPos);
-			const byte *lineEndP = (const byte *)dest.getBasePtr(dest.w, destPos.y + yPos);
+			const byte *lineStartP = (const byte *)dest.getBasePtr(bounds.left, destPos.y + yPos);
+			const byte *lineEndP = (const byte *)dest.getBasePtr(bounds.right, destPos.y + yPos);
 			byte *destP = !flipped ?
 				(byte *)dest.getBasePtr(destPos.x + xPos, destPos.y + yPos) :
 				(byte *)dest.getBasePtr(destPos.x + width - xPos, destPos.y + yPos);
@@ -247,17 +249,27 @@ void SpriteResource::drawOffset(XSurface &dest, uint16 offset, const Common::Poi
 		dest.addDirtyRect(r);
 }
 
+void SpriteResource::draw(XSurface &dest, int frame, const Common::Point &destPos,
+		int flags, int scale) const {
+	draw(dest, frame, destPos, Common::Rect(0, 0, dest.w, dest.h), flags, scale);
+}
+
+void SpriteResource::draw(Window &dest, int frame, const Common::Point &destPos,
+		int flags, int scale) const {
+	draw(dest, frame, destPos, dest.getBounds(), flags, scale);
+}
+
 /**
  * Draw the sprite onto the given surface
  */
 void SpriteResource::draw(XSurface &dest, int frame, const Common::Point &destPos, 
-		int flags, int scale) const {
+		const Common::Rect &bounds, int flags, int scale) const {
 	assert(scale != 0x8000); // TODO: TO test when I find scale value used
 
 	if (scale == 0) {
-		drawOffset(dest, _index[frame]._offset1, destPos, flags);
+		drawOffset(dest, _index[frame]._offset1, destPos, bounds, flags);
 		if (_index[frame]._offset2)
-			drawOffset(dest, _index[frame]._offset2, destPos, flags);
+			drawOffset(dest, _index[frame]._offset2, destPos, bounds, flags);
 	} else {
 		// Get the bounds for the surface and create a temporary one
 		Common::MemoryReadStream f(_data, _filesize);
@@ -267,12 +279,13 @@ void SpriteResource::draw(XSurface &dest, int frame, const Common::Point &destPo
 		int yOffset = f.readUint16LE();
 		int height = f.readUint16LE();
 		XSurface tempSurface(xOffset + width, yOffset + height);
+		Common::Rect tempBounds(0, 0, tempSurface.w, tempSurface.h);
 
 		// Draw sprite into temporary surface
 		tempSurface.fillRect(Common::Rect(0, 0, width, height), 0);
-		drawOffset(tempSurface, _index[frame]._offset1, Common::Point(), flags);
+		drawOffset(tempSurface, _index[frame]._offset1, Common::Point(), tempBounds, flags);
 		if (_index[frame]._offset2)
-			drawOffset(tempSurface, _index[frame]._offset2, Common::Point(), flags);
+			drawOffset(tempSurface, _index[frame]._offset2, Common::Point(), tempBounds, flags);
 
 		// TODO: I don't currently know the algorithm the original used for scaling.
 		// This is a best fit estimate that every increment of the scale field
diff --git a/engines/xeen/sprites.h b/engines/xeen/sprites.h
index 15a3b7c..7fc6793 100644
--- a/engines/xeen/sprites.h
+++ b/engines/xeen/sprites.h
@@ -32,6 +32,7 @@
 namespace Xeen {
 
 class XeenEngine;
+class Window;
 
 enum SpriteFlags { SPRFLAG_2000 = 0x2000, SPRFLAG_4000 = 0x4000, 
 	SPRFLAG_HORIZ_FLIPPED = 0x8000, SPRFLAG_RESIZE = 0x10000 };
@@ -47,7 +48,11 @@ private:
 
 	void load(Common::SeekableReadStream &f);
 
-	void drawOffset(XSurface &dest, uint16 offset, const Common::Point &destPos, int flags) const;
+	void draw(XSurface &dest, int frame, const Common::Point &destPos,
+		const Common::Rect &bounds, int flags = 0, int scale = 0) const;
+
+	void drawOffset(XSurface &dest, uint16 offset, const Common::Point &destPos, 
+		const Common::Rect &bounds, int flags) const;
 public:
 	SpriteResource();
 	SpriteResource(const Common::String &filename);
@@ -65,6 +70,9 @@ public:
 	void draw(XSurface &dest, int frame, const Common::Point &destPos, 
 		int flags = 0, int scale = 0) const;
 
+	void draw(Window &dest, int frame, const Common::Point &destPos,
+		int flags = 0, int scale = 0) const;
+
 	void draw(XSurface &dest, int frame) const;
 
 	int size() const { return _index.size(); }


Commit: 6126d45b0b4fdc50ca81308f80181550da0f455c
    https://github.com/scummvm/scummvm/commit/6126d45b0b4fdc50ca81308f80181550da0f455c
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-02-22T10:57:15-05:00

Commit Message:
XEEN: Remove redundant comment from drawList method

Changed paths:
    engines/xeen/screen.cpp



diff --git a/engines/xeen/screen.cpp b/engines/xeen/screen.cpp
index 3b3ea69..ac1f0c4 100644
--- a/engines/xeen/screen.cpp
+++ b/engines/xeen/screen.cpp
@@ -196,7 +196,6 @@ void Window::drawList(DrawStruct *items, int count) {
 		pt.x += _innerBounds.left;
 		pt.y += _innerBounds.top;
 
-		// TODO: There are two sprite calls in this method. Figure out why
 		items->_sprites->draw(*this, items->_frame, pt, items->_flags, items->_scale);
 	}
 }


Commit: 3f27fd8bb766f9ac76fb5e450e62c4493ef121a9
    https://github.com/scummvm/scummvm/commit/3f27fd8bb766f9ac76fb5e450e62c4493ef121a9
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-02-22T11:45:00-05:00

Commit Message:
XEEN: Fix horizontal positioning for flipped images

Changed paths:
    engines/xeen/sprites.cpp



diff --git a/engines/xeen/sprites.cpp b/engines/xeen/sprites.cpp
index 2c5279b..93c7e42 100644
--- a/engines/xeen/sprites.cpp
+++ b/engines/xeen/sprites.cpp
@@ -151,7 +151,7 @@ void SpriteResource::drawOffset(XSurface &dest, uint16 offset, const Common::Poi
 			const byte *lineEndP = (const byte *)dest.getBasePtr(bounds.right, destPos.y + yPos);
 			byte *destP = !flipped ?
 				(byte *)dest.getBasePtr(destPos.x + xPos, destPos.y + yPos) :
-				(byte *)dest.getBasePtr(destPos.x + width - xPos, destPos.y + yPos);
+				(byte *)dest.getBasePtr(destPos.x + xOffset + width - xPos, destPos.y + yPos);
 
 			while (byteCount < lineLength) {
 				// The next byte is an opcode that determines what 


Commit: c15ca5ca50d42ad73ab32243a9bd092a0c86cb72
    https://github.com/scummvm/scummvm/commit/c15ca5ca50d42ad73ab32243a9bd092a0c86cb72
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-02-22T18:33:36-05:00

Commit Message:
XEEN: Fix compiler warning

Changed paths:
    engines/xeen/combat.cpp



diff --git a/engines/xeen/combat.cpp b/engines/xeen/combat.cpp
index 4b9ddd6..471fefd 100644
--- a/engines/xeen/combat.cpp
+++ b/engines/xeen/combat.cpp
@@ -1623,7 +1623,7 @@ bool Combat::hitMonster(Character &c, RangeType rangeType) {
 	Map &map = *_vm->_map;
 	getWeaponDamage(c, rangeType);
 	int chance = c.statBonus(c.getStat(ACCURACY)) + _hitChanceBonus;
-	int divisor;
+	int divisor = 0;
 	
 	switch (c._class) {
 	case CLASS_KNIGHT:


Commit: 3e05d9008e88b108a55455643900939f91174670
    https://github.com/scummvm/scummvm/commit/3e05d9008e88b108a55455643900939f91174670
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-02-22T20:37:56-05:00

Commit Message:
XEEN: Merge scaling code from XSurface into sprite drawing code

Changed paths:
    engines/xeen/sprites.cpp
    engines/xeen/sprites.h
    engines/xeen/xsurface.cpp
    engines/xeen/xsurface.h



diff --git a/engines/xeen/sprites.cpp b/engines/xeen/sprites.cpp
index 93c7e42..d75eb9c 100644
--- a/engines/xeen/sprites.cpp
+++ b/engines/xeen/sprites.cpp
@@ -33,10 +33,14 @@ namespace Xeen {
 SpriteResource::SpriteResource() {
 	_filesize = 0;
 	_data = nullptr;
+	_scaledWidth = _scaledHeight = 0;
+	Common::fill(&_lineDist[0], &_lineDist[SCREEN_WIDTH], false);
 }
 
 SpriteResource::SpriteResource(const Common::String &filename) {
 	_data = nullptr;
+	_scaledWidth = _scaledHeight = 0;
+	Common::fill(&_lineDist[0], &_lineDist[SCREEN_WIDTH], false);
 	load(filename);
 }
 
@@ -112,7 +116,7 @@ void SpriteResource::clear() {
  * Draws a frame using data at a specific offset in the sprite resource
  */
 void SpriteResource::drawOffset(XSurface &dest, uint16 offset, const Common::Point &destPos, 
-		const Common::Rect &bounds, int flags) const {
+		const Common::Rect &bounds, int flags, int scale) {
 	// Get cell header
 	Common::MemoryReadStream f(_data, _filesize);
 	f.seek(offset);
@@ -121,6 +125,14 @@ void SpriteResource::drawOffset(XSurface &dest, uint16 offset, const Common::Poi
 	int yOffset = f.readUint16LE();
 	int height = f.readUint16LE();
 
+	// TODO: I don't currently know the algorithm the original used for scaling.
+	// This is a best fit estimate that every increment of the scale field
+	// reduces the size of a sprite by approximately 6.6%
+	int newScale = MAX(100.0 - 6.6 * scale, 0.0);
+	if (newScale == 0)
+		return;
+	setupScaling(newScale, xOffset + width, yOffset + height);
+
 	bool flipped = (flags & SPRFLAG_HORIZ_FLIPPED) != 0;
 	int xInc = flipped ? -1 : 1;
 
@@ -134,24 +146,34 @@ void SpriteResource::drawOffset(XSurface &dest, uint16 offset, const Common::Poi
 	// Main loop
 	int opr1, opr2;
 	int32 pos;
-	for (int yPos = yOffset, byteCount = 0; yPos < height + yOffset; yPos++, byteCount = 0) {
+	int yIndex = yOffset;
+	int yPos = destPos.y + getScaledValue(yOffset);
+	for (int yCtr = 0, byteCount = 0; yCtr < height; ++yCtr, ++yIndex, byteCount = 0) {
 		// The number of bytes in this scan line
 		int lineLength = f.readByte();
 
 		if (lineLength == 0) {
 			// Skip the specified number of scan lines
-			yPos += f.readByte();
-		} else if ((destPos.y + yPos) < bounds.top || (destPos.y + yPos) >= bounds.bottom) {
+			int numLines = f.readByte();
+			for (int idx = 0; idx < numLines; ++idx, ++yIndex, ++yCtr) {
+				if (_lineDist[yIndex])
+					++yPos;
+			}
+		} else if (destPos.y < bounds.top || yPos >= bounds.bottom 
+				|| !_lineDist[yIndex]) {
 			// Skip over the bytes of the line
 			f.skip(lineLength);
 		} else {
+			const byte *lineStartP = (const byte *)dest.getBasePtr(bounds.left, yPos);
+			const byte *lineEndP = (const byte *)dest.getBasePtr(bounds.right, yPos);
+
 			// Skip the transparent pixels at the beginning of the scan line
 			int xPos = f.readByte() + xOffset; ++byteCount;
-			const byte *lineStartP = (const byte *)dest.getBasePtr(bounds.left, destPos.y + yPos);
-			const byte *lineEndP = (const byte *)dest.getBasePtr(bounds.right, destPos.y + yPos);
-			byte *destP = !flipped ?
-				(byte *)dest.getBasePtr(destPos.x + xPos, destPos.y + yPos) :
-				(byte *)dest.getBasePtr(destPos.x + xOffset + width - xPos, destPos.y + yPos);
+			int xAmt = getScaledValue(flipped ? xOffset + width - xPos : xPos);
+			int xIndex = 0;
+
+			byte *destP = (byte *)dest.getBasePtr(destPos.x + xAmt, yPos);
+			++yPos;
 
 			while (byteCount < lineLength) {
 				// The next byte is an opcode that determines what 
@@ -169,18 +191,22 @@ void SpriteResource::drawOffset(XSurface &dest, uint16 offset, const Common::Poi
 						byte b = f.readByte();
 						++byteCount;
 
-						if (destP >= lineStartP && destP < lineEndP)
-							*destP = b;
-						destP += xInc;
+						if (_lineDist[xIndex++]) {
+							if (destP >= lineStartP && destP < lineEndP)
+								*destP = b;
+							destP += xInc;
+						}
 					}
 					break;
 
 				case 2:   // The following byte is an index into the color table, draw it len + 3 times.
 					opr1 = f.readByte(); ++byteCount;
 					for (int i = 0; i < len + 3; ++i, ++xPos) {
-						if (destP >= lineStartP && destP < lineEndP)
-							*destP = opr1;
-						destP += xInc;
+						if (_lineDist[xIndex++]) {
+							if (destP >= lineStartP && destP < lineEndP)
+								*destP = opr1;
+							destP += xInc;
+						}
 					}
 					break;
 
@@ -191,9 +217,11 @@ void SpriteResource::drawOffset(XSurface &dest, uint16 offset, const Common::Poi
 
 					for (int i = 0; i < len + 4; ++i, ++xPos) {
 						byte b = f.readByte();
-						if (destP >= lineStartP && destP < lineEndP)
-							*destP = b;
-						destP += xInc;
+						if (_lineDist[xIndex++]) {
+							if (destP >= lineStartP && destP < lineEndP)
+								*destP = b;
+							destP += xInc;
+						}
 					}
 
 					f.seek(pos, SEEK_SET);
@@ -204,19 +232,29 @@ void SpriteResource::drawOffset(XSurface &dest, uint16 offset, const Common::Poi
 					opr2 = f.readByte(); ++byteCount;
 					for (int i = 0; i < len + 2; ++i, xPos += 2) {
 						if (destP < lineStartP || destP >= (lineEndP - 1)) {
-							destP += 2 * xInc;
+							if (_lineDist[xIndex++])
+								destP += xInc;
+							if (_lineDist[xIndex++])
+								destP += xInc;
 						} else {
-							*destP = opr1;
-							destP += xInc;
-							*destP = opr2;
-							destP += xInc;
+							if (_lineDist[xIndex++]) {
+								*destP = opr1;
+								destP += xInc;
+							}
+							if (_lineDist[xIndex++]) {
+								*destP = opr2;
+								destP += xInc;
+							}
 						}
 					}
 					break;
 
 				case 5:   // Skip len + 1 pixels filling them with the transparent color.
-					xPos += len + 1;
-					destP += (len + 1) * xInc;
+					for (int idx = 0; idx < (len + 1); ++idx) {
+						if (_lineDist[xIndex++])
+							destP += xInc;
+						++xPos;
+					}
 					break;
 
 				case 6:   // Pattern command.
@@ -227,9 +265,11 @@ void SpriteResource::drawOffset(XSurface &dest, uint16 offset, const Common::Poi
 
 					opr1 = f.readByte(); ++byteCount;
 					for (int i = 0; i < len + 3; ++i, ++xPos) {
-						if (destP >= lineStartP && destP < lineEndP)
-							*destP = opr1;
-						destP += xInc;
+						if (_lineDist[xIndex++]) {
+							if (destP >= lineStartP && destP < lineEndP)
+								*destP = opr1;
+							destP += xInc;
+						}
 						opr1 += patternSteps[cmd + (i % 2)];
 					}
 					break;
@@ -242,20 +282,21 @@ void SpriteResource::drawOffset(XSurface &dest, uint16 offset, const Common::Poi
 		}
 	}
 	
-	Common::Rect r(Common::Rect(destPos.x + xOffset, destPos.y + yOffset,
-		destPos.x + xOffset + width, destPos.y + yOffset + height));
+	Common::Rect r(Common::Rect(
+		destPos.x + getScaledValue(xOffset), destPos.y + getScaledValue(yOffset),
+		destPos.x + getScaledValue(xOffset + width), destPos.y + getScaledValue(yOffset + height)));
 	r.clip(Common::Rect(0, 0, dest.w, dest.h));
 	if (!r.isEmpty())
 		dest.addDirtyRect(r);
 }
 
 void SpriteResource::draw(XSurface &dest, int frame, const Common::Point &destPos,
-		int flags, int scale) const {
+		int flags, int scale) {
 	draw(dest, frame, destPos, Common::Rect(0, 0, dest.w, dest.h), flags, scale);
 }
 
 void SpriteResource::draw(Window &dest, int frame, const Common::Point &destPos,
-		int flags, int scale) const {
+		int flags, int scale) {
 	draw(dest, frame, destPos, dest.getBounds(), flags, scale);
 }
 
@@ -263,44 +304,58 @@ void SpriteResource::draw(Window &dest, int frame, const Common::Point &destPos,
  * Draw the sprite onto the given surface
  */
 void SpriteResource::draw(XSurface &dest, int frame, const Common::Point &destPos, 
-		const Common::Rect &bounds, int flags, int scale) const {
-	assert(scale != 0x8000); // TODO: TO test when I find scale value used
-
-	if (scale == 0) {
-		drawOffset(dest, _index[frame]._offset1, destPos, bounds, flags);
-		if (_index[frame]._offset2)
-			drawOffset(dest, _index[frame]._offset2, destPos, bounds, flags);
-	} else {
-		// Get the bounds for the surface and create a temporary one
-		Common::MemoryReadStream f(_data, _filesize);
-		f.seek(_index[frame]._offset1);
-		int xOffset = f.readUint16LE();
-		int width = f.readUint16LE();
-		int yOffset = f.readUint16LE();
-		int height = f.readUint16LE();
-		XSurface tempSurface(xOffset + width, yOffset + height);
-		Common::Rect tempBounds(0, 0, tempSurface.w, tempSurface.h);
-
-		// Draw sprite into temporary surface
-		tempSurface.fillRect(Common::Rect(0, 0, width, height), 0);
-		drawOffset(tempSurface, _index[frame]._offset1, Common::Point(), tempBounds, flags);
-		if (_index[frame]._offset2)
-			drawOffset(tempSurface, _index[frame]._offset2, Common::Point(), tempBounds, flags);
-
-		// TODO: I don't currently know the algorithm the original used for scaling.
-		// This is a best fit estimate that every increment of the scale field
-		// reduces the size of a sprite by approximately 6.6%
-		int newScale = MAX(100.0 - 6.6 * scale, 0.0);
-		if (newScale > 0)
-			tempSurface.transBlitTo(dest, Common::Point(), newScale, 0);
-	}
+		const Common::Rect &bounds, int flags, int scale) {
+	// TODO: TO test when I find sprites using scale values and flags
+	assert(scale != 0x8000); 
+	assert(scale >= 0);
+//	assert((flags & SPRFLAG_2000) == 0);
+
+	drawOffset(dest, _index[frame]._offset1, destPos, bounds, flags, scale);
+	if (_index[frame]._offset2)
+		drawOffset(dest, _index[frame]._offset2, destPos, bounds, flags, scale);
 }
 
 /**
  * Draw the sprite onto the given surface
  */
-void SpriteResource::draw(XSurface &dest, int frame) const {
+void SpriteResource::draw(XSurface &dest, int frame) {
 	draw(dest, frame, Common::Point());
 }
 
+void SpriteResource::setupScaling(int scale, int frameWidth, int frameHeight) {
+	int highestDim = MAX(frameWidth, frameHeight);
+	int distCtr = 0;
+	int distIndex = 0;
+	_scaledWidth = _scaledHeight = 0;
+
+	do {
+		distCtr += scale;
+		if (distCtr < 100) {
+			_lineDist[distIndex] = false;
+		} else {
+			_lineDist[distIndex] = true;
+			distCtr -= 100;
+
+			if (distIndex < frameWidth)
+				++_scaledWidth;
+
+			if (distIndex < frameHeight)
+				++_scaledHeight;
+		}
+	} while (++distIndex < highestDim);
+}
+
+/**
+ * Returns a scaled value based on a passed in x or y distance
+ */
+int SpriteResource::getScaledValue(int xy) {
+	int newVal = 0;
+	for (int idx = 0; idx < xy; ++idx) {
+		if (_lineDist[idx])
+			++newVal;
+	}
+
+	return newVal;
+}
+
 } // End of namespace Xeen
diff --git a/engines/xeen/sprites.h b/engines/xeen/sprites.h
index 7fc6793..2d9fe2f 100644
--- a/engines/xeen/sprites.h
+++ b/engines/xeen/sprites.h
@@ -45,14 +45,20 @@ private:
 	Common::Array<IndexEntry> _index;
 	int32 _filesize;
 	byte *_data;
+	bool _lineDist[320];
+	int _scaledWidth, _scaledHeight;
 
 	void load(Common::SeekableReadStream &f);
 
 	void draw(XSurface &dest, int frame, const Common::Point &destPos,
-		const Common::Rect &bounds, int flags = 0, int scale = 0) const;
+		const Common::Rect &bounds, int flags = 0, int scale = 0);
 
 	void drawOffset(XSurface &dest, uint16 offset, const Common::Point &destPos, 
-		const Common::Rect &bounds, int flags) const;
+		const Common::Rect &bounds, int flags, int scale);
+
+	void setupScaling(int scale, int frameWidth, int frameHeight);
+
+	int getScaledValue(int xy);
 public:
 	SpriteResource();
 	SpriteResource(const Common::String &filename);
@@ -68,12 +74,12 @@ public:
 	void clear();
 
 	void draw(XSurface &dest, int frame, const Common::Point &destPos, 
-		int flags = 0, int scale = 0) const;
+		int flags = 0, int scale = 0);
 
 	void draw(Window &dest, int frame, const Common::Point &destPos,
-		int flags = 0, int scale = 0) const;
+		int flags = 0, int scale = 0);
 
-	void draw(XSurface &dest, int frame) const;
+	void draw(XSurface &dest, int frame);
 
 	int size() const { return _index.size(); }
 
diff --git a/engines/xeen/xsurface.cpp b/engines/xeen/xsurface.cpp
index 7060a63..04a264a 100644
--- a/engines/xeen/xsurface.cpp
+++ b/engines/xeen/xsurface.cpp
@@ -55,152 +55,10 @@ void XSurface::create(XSurface *s, const Common::Rect &bounds) {
 	_freeFlag = false;
 }
 
-
-void XSurface::transBlitTo(XSurface &dest) const {
-	transBlitTo(dest, Common::Point());
-}
-
 void XSurface::blitTo(XSurface &dest) const {
 	blitTo(dest, Common::Point());
 }
 
-void XSurface::transBlitTo(XSurface &dest, const Common::Point &destPos) const {
-	if (dest.getPixels() == nullptr)
-		dest.create(w, h);
-
-	for (int yp = 0; yp < h; ++yp) {
-		const byte *srcP = (const byte *)getBasePtr(0, yp);
-		byte *destP = (byte *)dest.getBasePtr(destPos.x, destPos.y + yp);
-
-		for (int xp = 0; xp < w; ++xp, ++srcP, ++destP) {
-			if (*srcP != 0)
-				*destP = *srcP;
-		}
-	}
-
-	dest.addDirtyRect(Common::Rect(destPos.x, destPos.y, destPos.x + w, destPos.y));
-}
-
-void XSurface::transBlitTo(XSurface &dest, const Common::Point &destPos, 
-		int scale, int transparentColor) {
-	int destX = destPos.x, destY = destPos.y;
-	int frameWidth = this->w;
-	int frameHeight = this->h;
-	int direction = 1;
-
-	int highestDim = MAX(frameWidth, frameHeight);
-	bool lineDist[SCREEN_WIDTH];
-	int distXCount = 0, distYCount = 0;
-
-	if (scale != 0) {
-		int distCtr = 0;
-		int distIndex = 0;
-		do {
-			distCtr += scale;
-			if (distCtr < 100) {
-				lineDist[distIndex] = false;
-			}
-			else {
-				lineDist[distIndex] = true;
-				distCtr -= 100;
-
-				if (distIndex < frameWidth)
-					++distXCount;
-
-				if (distIndex < frameHeight)
-					++distYCount;
-			}
-		} while (++distIndex < highestDim);
-
-		destX += (this->w - distXCount) / 2;
-		destY += (this->h - distYCount) / 2;
-	}
-
-	// Start of draw logic for scaled sprites
-	const byte *srcPixelsP = (const byte *)getPixels();
-
-	int destRight = dest.w - 1;
-	int destBottom = dest.h - 1;
-
-	// Check x bounding area
-	int spriteLeft = 0;
-	int spriteWidth = distXCount;
-	int widthAmount = destX + distXCount - 1;
-
-	if (destX < 0) {
-		spriteWidth += destX;
-		spriteLeft -= destX;
-	}
-	widthAmount -= destRight;
-	if (widthAmount > 0)
-		spriteWidth -= widthAmount;
-
-	if (spriteWidth <= 0)
-		return;
-
-	// Check y bounding area
-	int spriteTop = 0;
-	int spriteHeight = distYCount;
-	int heightAmount = destY + distYCount - 1;
-
-	if (destY < 0) {
-		spriteHeight += destY;
-		spriteTop -= destY;
-	}
-	heightAmount -= destBottom;
-	if (heightAmount > 0)
-		spriteHeight -= heightAmount;
-	int spriteBottom = spriteTop + spriteHeight;
-
-	if (spriteHeight <= 0)
-		return;
-
-	byte *destPixelsP = (byte *)dest.getBasePtr(destX + spriteLeft, destY + spriteTop);
-	int destWidth = 0, destHeight = 0;
-
-	spriteLeft = spriteLeft * direction;
-
-	// Loop through the lines of the sprite
-	for (int yp = 0, sprY = -1; yp < frameHeight; ++yp, srcPixelsP += this->pitch) {
-		if (!lineDist[yp])
-			// Not a display line, so skip it
-			continue;
-		// Check whether the sprite line is in the display range
-		++sprY;
-		if ((sprY >= spriteBottom) || (sprY < spriteTop))
-			continue;
-
-		// Found a line to display. Loop through the pixels
-		const byte *srcP = srcPixelsP;
-		byte *destP = destPixelsP;
-		++destHeight;
-
-		for (int xp = 0, sprX = 0; xp < frameWidth; ++xp, ++srcP) {
-			if (xp < spriteLeft)
-				// Not yet reached start of display area
-				continue;
-			if (!lineDist[sprX++])
-				// Not a display pixel
-				continue;
-
-			if (*srcP != transparentColor)
-				*destP = *srcP;
-
-			destP += direction;
-		}
-
-		// Keep track of widest line drawn
-		destWidth = MAX(destP - destPixelsP, destWidth);
-
-		// Move to the next destination line
-		destPixelsP += dest.pitch;
-	}
-
-	// Add a dirty rect for the affected area
-	dest.addDirtyRect(Common::Rect(destX + spriteLeft, destY + spriteTop,
-		destX + spriteLeft + destWidth, destY + spriteTop + destHeight));
-}
-
 void XSurface::blitTo(XSurface &dest, const Common::Point &destPos) const {
 	if (dest.getPixels() == nullptr)
 		dest.create(w, h);
diff --git a/engines/xeen/xsurface.h b/engines/xeen/xsurface.h
index 61f4f96..d8747d4 100644
--- a/engines/xeen/xsurface.h
+++ b/engines/xeen/xsurface.h
@@ -44,13 +44,6 @@ public:
 
 	void create(XSurface *s, const Common::Rect &bounds);
 
-	void transBlitTo(XSurface &dest) const;
-
-	void transBlitTo(XSurface &dest, const Common::Point &destPos) const;
-
-	void transBlitTo(XSurface &dest, const Common::Point &destPos,
-		int scale, int transparentColor);
-
 	void blitTo(XSurface &dest, const Common::Point &destPos) const;
 
 	void blitTo(XSurface &dest) const;


Commit: 2d2fc3f9ed100fab85e736555048a62ac1e00dcd
    https://github.com/scummvm/scummvm/commit/2d2fc3f9ed100fab85e736555048a62ac1e00dcd
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-02-22T22:58:37-05:00

Commit Message:
XEEN: Add horizontal placement fix for scaled sprites

Changed paths:
    engines/xeen/sprites.cpp
    engines/xeen/sprites.h



diff --git a/engines/xeen/sprites.cpp b/engines/xeen/sprites.cpp
index d75eb9c..b596432 100644
--- a/engines/xeen/sprites.cpp
+++ b/engines/xeen/sprites.cpp
@@ -115,7 +115,7 @@ void SpriteResource::clear() {
 /**
  * Draws a frame using data at a specific offset in the sprite resource
  */
-void SpriteResource::drawOffset(XSurface &dest, uint16 offset, const Common::Point &destPos, 
+void SpriteResource::drawOffset(XSurface &dest, uint16 offset, const Common::Point &pt, 
 		const Common::Rect &bounds, int flags, int scale) {
 	// Get cell header
 	Common::MemoryReadStream f(_data, _filesize);
@@ -133,6 +133,9 @@ void SpriteResource::drawOffset(XSurface &dest, uint16 offset, const Common::Poi
 		return;
 	setupScaling(newScale, xOffset + width, yOffset + height);
 
+	Common::Point destPos = pt;
+	destPos.x += (xOffset + width - _scaledWidth) / 2;
+
 	bool flipped = (flags & SPRFLAG_HORIZ_FLIPPED) != 0;
 	int xInc = flipped ? -1 : 1;
 
diff --git a/engines/xeen/sprites.h b/engines/xeen/sprites.h
index 2d9fe2f..0e3a3c3 100644
--- a/engines/xeen/sprites.h
+++ b/engines/xeen/sprites.h
@@ -53,7 +53,7 @@ private:
 	void draw(XSurface &dest, int frame, const Common::Point &destPos,
 		const Common::Rect &bounds, int flags = 0, int scale = 0);
 
-	void drawOffset(XSurface &dest, uint16 offset, const Common::Point &destPos, 
+	void drawOffset(XSurface &dest, uint16 offset, const Common::Point &pt, 
 		const Common::Rect &bounds, int flags, int scale);
 
 	void setupScaling(int scale, int frameWidth, int frameHeight);


Commit: ddf71710016baaf9989c10b79e5e313464adbdf9
    https://github.com/scummvm/scummvm/commit/ddf71710016baaf9989c10b79e5e313464adbdf9
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-02-22T22:59:05-05:00

Commit Message:
XEEN: Fix placement of objects in setIndoorsObjects

Changed paths:
    engines/xeen/interface_map.cpp



diff --git a/engines/xeen/interface_map.cpp b/engines/xeen/interface_map.cpp
index 8032369..249dc3a 100644
--- a/engines/xeen/interface_map.cpp
+++ b/engines/xeen/interface_map.cpp
@@ -2760,8 +2760,8 @@ void InterfaceMap::setIndoorsObjects() {
 			} else if (_wo[20] && _wo[17]) {
 			} else if (_wo[23] && _wo[17]) {
 			} else if (!_wo[12] && !_wo[8] && _indoorList._objects9._frame == -1) {
-				_indoorList._objects9._x = INDOOR_OBJECT_X[listOffset][9];
-				_indoorList._objects9._y = MAP_OBJECT_Y[listOffset][9];
+				_indoorList._objects9._x = INDOOR_OBJECT_X[listOffset][10];
+				_indoorList._objects9._y = MAP_OBJECT_Y[listOffset][10];
 				_indoorList._objects9._frame = mazeObject._frame;
 				_indoorList._objects9._sprites = mazeObject._sprites;
 				_indoorList._objects9._flags &= ~SPRFLAG_HORIZ_FLIPPED;
@@ -2779,8 +2779,8 @@ void InterfaceMap::setIndoorsObjects() {
 			} else if (_wo[14] && _wo[9]) {
 			} else if (_wo[19] && _wo[9]) {
 			} else if (_indoorList._objects10._frame == -1) {
-				_indoorList._objects10._x = INDOOR_OBJECT_X[listOffset][10];
-				_indoorList._objects10._y = MAP_OBJECT_Y[listOffset][10];
+				_indoorList._objects10._x = INDOOR_OBJECT_X[listOffset][9];
+				_indoorList._objects10._y = MAP_OBJECT_Y[listOffset][9];
 				_indoorList._objects10._frame = mazeObject._frame;
 				_indoorList._objects10._sprites = mazeObject._sprites;
 				_indoorList._objects10._flags &= ~SPRFLAG_HORIZ_FLIPPED;


Commit: 9725fc57252b6dd4529e5f8e45519ac6fc480a12
    https://github.com/scummvm/scummvm/commit/9725fc57252b6dd4529e5f8e45519ac6fc480a12
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-02-22T23:45:11-05:00

Commit Message:
XEEN: Renaming and move flags used for UI indicators

Changed paths:
    engines/xeen/combat.cpp
    engines/xeen/combat.h
    engines/xeen/interface.cpp
    engines/xeen/interface.h
    engines/xeen/spells.cpp
    engines/xeen/sprites.cpp
    engines/xeen/town.cpp
    engines/xeen/xeen.cpp
    engines/xeen/xeen.h



diff --git a/engines/xeen/combat.cpp b/engines/xeen/combat.cpp
index 471fefd..254c33f 100644
--- a/engines/xeen/combat.cpp
+++ b/engines/xeen/combat.cpp
@@ -123,6 +123,8 @@ Combat::Combat(XeenEngine *vm): _vm(vm), _missVoc("miss.voc"), _pow1Voc("pow1.vo
 	_attackWeapon = nullptr;
 	_attackWeaponId = 0;
 	_hitChanceBonus = 0;
+	_dangerPresent = false;
+	_moveMonsters = false;
 }
 
 void Combat::clear() {
@@ -437,7 +439,7 @@ void Combat::moveMonsters() {
 	Map &map = *_vm->_map;
 	Party &party = *_vm->_party;
 
-	if (!_vm->_moveMonsters)
+	if (!_moveMonsters)
 		return;
 
 	intf._tillMove = 0;
@@ -448,7 +450,7 @@ void Combat::moveMonsters() {
 	Common::fill(&_monsterMoved[0], &_monsterMoved[MAX_NUM_MONSTERS], false);
 	Common::fill(&_rangeAttacking[0], &_rangeAttacking[MAX_NUM_MONSTERS], false);
 	Common::fill(&_gmonHit[0], &_gmonHit[36], -1);
-	_vm->_dangerSenseAllowed = false;
+	_dangerPresent = false;
 
 	for (uint idx = 0; idx < map._mobData._monsters.size(); ++idx) {
 		MazeMonster &monster = map._mobData._monsters[idx];
@@ -469,7 +471,7 @@ void Combat::moveMonsters() {
 					MonsterStruct &monsterData = map._monsterData[monster._spriteId];
 
 					if (pt == monster._position) {
-						_vm->_dangerSenseAllowed = true;
+						_dangerPresent = true;
 						if ((monster._isAttacking || _vm->_mode == MODE_SLEEPING)
 								&& !_monsterMoved[idx]) {
 							if (party._mazePosition.x == pt.x || party._mazePosition.y == pt.y) {
@@ -704,7 +706,7 @@ void Combat::moveMonster(int monsterId, const Common::Point &pt) {
 	Map &map = *_vm->_map;
 	MazeMonster &monster = map._mobData._monsters[monsterId];
 
-	if (_monsterMap[pt.y][pt.x] < 3 && !monster._damageType && _vm->_moveMonsters) {
+	if (_monsterMap[pt.y][pt.x] < 3 && !monster._damageType && _moveMonsters) {
 		++_monsterMap[pt.y][pt.x];
 		--_monsterMap[monster._position.y][monster._position.x];
 		monster._position = pt;
diff --git a/engines/xeen/combat.h b/engines/xeen/combat.h
index 466152a..f78e928 100644
--- a/engines/xeen/combat.h
+++ b/engines/xeen/combat.h
@@ -118,6 +118,8 @@ public:
 	int _attackWeaponId;
 	File _missVoc, _pow1Voc;
 	int _hitChanceBonus;
+	bool _dangerPresent;
+	bool _moveMonsters;
 public:
 	Combat(XeenEngine *vm);
 
diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp
index 1b3ee4f3..4343207 100644
--- a/engines/xeen/interface.cpp
+++ b/engines/xeen/interface.cpp
@@ -143,7 +143,7 @@ Interface::Interface(XeenEngine *vm) : ButtonContainer(), InterfaceMap(vm),
 	_flipUIFrame = 0;
 	_face1UIFrame = 0;
 	_face2UIFrame = 0;
-	_batUIFrame = 0;
+	_levitateUIFrame = 0;
 	_spotDoorsUIFrame = 0;
 	_dangerSenseUIFrame = 0;
 	_face1State = _face2State = 0;
@@ -327,11 +327,11 @@ void Interface::perform() {
 	switch (_buttonValue) {
 	case Common::KEYCODE_TAB:
 		// Stop mosters doing any movement
-		_vm->_moveMonsters = false;
+		combat._moveMonsters = false;
 		if (ControlPanel::show(_vm) == -1) {
 			_vm->_quitMode = 2;
 		} else {
-			_vm->_moveMonsters = 1;
+			combat._moveMonsters = 1;
 		}
 		break;
 
@@ -488,9 +488,9 @@ void Interface::perform() {
 	case Common::KEYCODE_EQUALS:
 	case Common::KEYCODE_KP_EQUALS:
 		// Toggle minimap
-		_vm->_moveMonsters = false;
+		combat._moveMonsters = false;
 		party._automapOn = !party._automapOn;
-		_vm->_moveMonsters = true;
+		combat._moveMonsters = true;
 		break;
 
 	case Common::KEYCODE_b:
@@ -547,9 +547,9 @@ void Interface::perform() {
 
 	case Common::KEYCODE_i:
 		// Show Info dialog
-		_vm->_moveMonsters = false;
+		combat._moveMonsters = false;
 		InfoDialog::show(_vm);
-		_vm->_moveMonsters = true;
+		combat._moveMonsters = true;
 		break;
 
 	case Common::KEYCODE_m:
@@ -1237,7 +1237,7 @@ void Interface::draw3d(bool updateFlag) {
 	if (_flipUIFrame == 0)
 		_flipWater = !_flipWater;
 	if (_tillMove && (_vm->_mode == MODE_1 || _vm->_mode == MODE_COMBAT) &&
-		!combat._monstersAttacking && _vm->_moveMonsters) {
+		!combat._monstersAttacking && combat._moveMonsters) {
 		if (--_tillMove == 0)
 			combat.moveMonsters();
 	}
@@ -1270,7 +1270,7 @@ void Interface::draw3d(bool updateFlag) {
 	if (combat._attackMonsters[0] != -1 || combat._attackMonsters[1] != -1
 			|| combat._attackMonsters[2] != -1) {
 		if ((_vm->_mode == MODE_1 || _vm->_mode == MODE_SLEEPING) && 
-				!combat._monstersAttacking && !_charsShooting && _vm->_moveMonsters) {
+				!combat._monstersAttacking && !_charsShooting && combat._moveMonsters) {
 			doCombat();
 			if (scripts._eventSkipped)
 				scripts.checkEvents();
@@ -1743,16 +1743,18 @@ void Interface::drawMiniMap() {
  * Draw the display borders
  */
 void Interface::assembleBorder() {
+	Combat &combat = *_vm->_combat;
 	Resources &res = *_vm->_resources;
 	Screen &screen = *_vm->_screen;
 
 	// Draw the outer frame
 	res._globalSprites.draw(screen._windows[0], 0, Common::Point(8, 8));
 
-	// Draw the animating bat character used to show when levitate is active
-	_borderSprites.draw(screen._windows[0], _vm->_party->_levitateActive ? _batUIFrame + 16 : 16,
+	// Draw the animating bat character on the left screen edge to indicate
+	// that the party is being levitated
+	_borderSprites.draw(screen._windows[0], _vm->_party->_levitateActive ? _levitateUIFrame + 16 : 16,
 		Common::Point(0, 82));
-	_batUIFrame = (_batUIFrame + 1) % 12;
+	_levitateUIFrame = (_levitateUIFrame + 1) % 12;
 
 	// Draw UI element to indicate whether can spot hidden doors
 	_borderSprites.draw(screen,
@@ -1762,7 +1764,7 @@ void Interface::assembleBorder() {
 
 	// Draw UI element to indicate whether can sense danger
 	_borderSprites.draw(screen,
-		(_vm->_dangerSenseAllowed && _vm->_party->checkSkill(DANGER_SENSE)) ? _spotDoorsUIFrame + 40 : 40,
+		(combat._dangerPresent && _vm->_party->checkSkill(DANGER_SENSE)) ? _spotDoorsUIFrame + 40 : 40,
 		Common::Point(107, 9));
 	_dangerSenseUIFrame = (_dangerSenseUIFrame + 1) % 12;
 
diff --git a/engines/xeen/interface.h b/engines/xeen/interface.h
index 80b7980..66a40c2 100644
--- a/engines/xeen/interface.h
+++ b/engines/xeen/interface.h
@@ -115,7 +115,7 @@ public:
 	int _face1UIFrame, _face2UIFrame;
 	int _spotDoorsUIFrame;
 	int _dangerSenseUIFrame;
-	int _batUIFrame;
+	int _levitateUIFrame;
 	bool _upDoorText;
 	Common::String _screenText;
 	byte _tillMove;
diff --git a/engines/xeen/spells.cpp b/engines/xeen/spells.cpp
index d2a2af3..25aae11 100644
--- a/engines/xeen/spells.cpp
+++ b/engines/xeen/spells.cpp
@@ -151,7 +151,7 @@ int Spells::castSpell(Character *c, int spellId) {
 		}
 	}
 
-	_vm->_moveMonsters = 1;
+	combat._moveMonsters = 1;
 	intf._tillMove = oldTillMove;
 	return result;
 }
diff --git a/engines/xeen/sprites.cpp b/engines/xeen/sprites.cpp
index b596432..597d4df 100644
--- a/engines/xeen/sprites.cpp
+++ b/engines/xeen/sprites.cpp
@@ -134,7 +134,9 @@ void SpriteResource::drawOffset(XSurface &dest, uint16 offset, const Common::Poi
 	setupScaling(newScale, xOffset + width, yOffset + height);
 
 	Common::Point destPos = pt;
-	destPos.x += (xOffset + width - _scaledWidth) / 2;
+	if (!(flags & SPRFLAG_2000)) {
+		destPos.x += (xOffset + width - _scaledWidth) / 2;
+	}
 
 	bool flipped = (flags & SPRFLAG_HORIZ_FLIPPED) != 0;
 	int xInc = flipped ? -1 : 1;
diff --git a/engines/xeen/town.cpp b/engines/xeen/town.cpp
index 3a8b6d8..0934aef 100644
--- a/engines/xeen/town.cpp
+++ b/engines/xeen/town.cpp
@@ -217,7 +217,7 @@ int Town::townAction(int actionId) {
 	intf._face1UIFrame = intf._face2UIFrame = 0;
 	intf._dangerSenseUIFrame = 0; 
 	intf._spotDoorsUIFrame = 0;
-	intf._batUIFrame = 0;
+	intf._levitateUIFrame = 0;
 
 	_townSprites[_drawFrameIndex / 8].draw(screen, _drawFrameIndex % 8, _townPos);
 	if (actionId == 0 && isDarkCc) {
@@ -1148,7 +1148,7 @@ void Town::drawTownAnim(bool flag) {
 		intf._face2UIFrame = 0;
 		intf._dangerSenseUIFrame = 0;
 		intf._spotDoorsUIFrame = 0;
-		intf._batUIFrame = 0;
+		intf._levitateUIFrame = 0;
 
 		intf.assembleBorder();
 	}
diff --git a/engines/xeen/xeen.cpp b/engines/xeen/xeen.cpp
index a3240bf..1410d65 100644
--- a/engines/xeen/xeen.cpp
+++ b/engines/xeen/xeen.cpp
@@ -52,9 +52,7 @@ XeenEngine::XeenEngine(OSystem *syst, const XeenGameDescription *gameDesc)
 	_town = nullptr;
 	_eventData = nullptr;
 	_quitMode = 0;
-	_dangerSenseAllowed = false;
 	_noDirectionSense = false;
-	_moveMonsters = false;
 	_mode = MODE_0;
 	_startupWindowActive = false;
 }
@@ -315,13 +313,13 @@ void XeenEngine::play() {
 	_screen->_windows[0].update();
 	_events->setCursor(0);
 
-	_moveMonsters = true;
+	_combat->_moveMonsters = true;
 	if (_mode == MODE_0) {
 		_mode = MODE_1;
 		_screen->fadeIn(4);
 	}
 
-	_moveMonsters = true;
+	_combat->_moveMonsters = true;
 
 	gameLoop();
 }
diff --git a/engines/xeen/xeen.h b/engines/xeen/xeen.h
index 76cb1c1..2d995a1 100644
--- a/engines/xeen/xeen.h
+++ b/engines/xeen/xeen.h
@@ -153,9 +153,7 @@ public:
 	GameEvent _gameEvent;
 	Common::SeekableReadStream *_eventData;
 	int _quitMode;
-	bool _dangerSenseAllowed;
 	bool _noDirectionSense;
-	bool _moveMonsters;
 	bool _startupWindowActive;
 public:
 	XeenEngine(OSystem *syst, const XeenGameDescription *gameDesc);


Commit: cba25ea458e428d2e9c1e6e30bb86a5c9da72b54
    https://github.com/scummvm/scummvm/commit/cba25ea458e428d2e9c1e6e30bb86a5c9da72b54
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-02-23T19:35:24-05:00

Commit Message:
XEEN: Fix placement of enemies

Changed paths:
    engines/xeen/interface_map.cpp
    engines/xeen/sprites.cpp



diff --git a/engines/xeen/interface_map.cpp b/engines/xeen/interface_map.cpp
index 249dc3a..a54b95f 100644
--- a/engines/xeen/interface_map.cpp
+++ b/engines/xeen/interface_map.cpp
@@ -2555,6 +2555,68 @@ void InterfaceMap::setIndoorsMonsters() {
 			}
 		}
 	}
+
+	_indoorList[153]._x += 58;
+	_indoorList[131]._x += 25;
+	_indoorList[105]._x += 9;
+	_indoorList[69]._x--;
+	_indoorList[61]._x -= 26;
+	_indoorList[64]._x += 23;
+	_indoorList[66]._x -= 58;
+	_indoorList[67]._x += 40;
+	_indoorList[100]._x -= 65;
+	_indoorList[101]._x -= 85;
+	_indoorList[102]._x += 49;
+	_indoorList[103]._x += 65;
+	_indoorList[128]._x -= 112;
+	_indoorList[129]._x += 98;
+
+	if (combat._attackMonsters[1] != -1 && combat._attackMonsters[2] == -1) {
+		_indoorList[156]._x += 31;
+		_indoorList[150]._x -= 36;
+	} else {
+		_indoorList[156]._x -= 5;
+		_indoorList[150]._x -= 67;
+	}
+
+	if (combat._attackMonsters[4] != -1 && combat._attackMonsters[5] == -1) {
+		_indoorList[132]._x += 8;
+		_indoorList[130]._x -= 23;
+	} else {
+		_indoorList[132]._x -= 7;
+		_indoorList[130]._x -= 38;
+	}
+
+	if (combat._attackMonsters[7] != -1 && combat._attackMonsters[8] == -1) {
+		_indoorList[104]._x -= 16;
+	} else {
+		_indoorList[106]._x -= 8;
+		_indoorList[104]._x -= 24;
+	}
+
+	if (combat._attackMonsters[10] != -1 && combat._attackMonsters[11] == -1) {
+		_indoorList[70]._x -= 5;
+		_indoorList[68]._x -= 13;
+	} else {
+		_indoorList[70]._x -= 9;
+		_indoorList[68]._x -= 17;
+	}
+
+	if (combat._attackMonsters[22] == -1 && combat._attackMonsters[24] == -1) {
+		_indoorList[62]._x -= 27;
+		_indoorList[60]._x -= 37;
+	} else {
+		_indoorList[62]._x -= 34;
+		_indoorList[60]._x -= 41;
+	}
+
+	if (combat._attackMonsters[23] != -1 && combat._attackMonsters[25] == -1) {
+		_indoorList[65]._x += 20;
+		_indoorList[63]._x -= 12;
+	} else {
+		_indoorList[65]._x += 16;
+		_indoorList[63]._x -= 16;
+	}
 }
 
 /**
@@ -2577,7 +2639,7 @@ void InterfaceMap::setMonsterSprite(DrawStruct &drawStruct, MazeMonster &monster
 		drawStruct._x = 0;
 	}
 
-	drawStruct._flags &= SPRFLAG_HORIZ_FLIPPED | SPRFLAG_4000 | SPRFLAG_2000;
+	drawStruct._flags &= ~0xFFF;
 	if (monster._effect2)
 		drawStruct._flags = MONSTER_EFFECT_FLAGS[monster._effect2][monster._effect3];
 }
diff --git a/engines/xeen/sprites.cpp b/engines/xeen/sprites.cpp
index 597d4df..b596432 100644
--- a/engines/xeen/sprites.cpp
+++ b/engines/xeen/sprites.cpp
@@ -134,9 +134,7 @@ void SpriteResource::drawOffset(XSurface &dest, uint16 offset, const Common::Poi
 	setupScaling(newScale, xOffset + width, yOffset + height);
 
 	Common::Point destPos = pt;
-	if (!(flags & SPRFLAG_2000)) {
-		destPos.x += (xOffset + width - _scaledWidth) / 2;
-	}
+	destPos.x += (xOffset + width - _scaledWidth) / 2;
 
 	bool flipped = (flags & SPRFLAG_HORIZ_FLIPPED) != 0;
 	int xInc = flipped ? -1 : 1;


Commit: 20bdb154f60f590759627b4782e72e88d34bef2d
    https://github.com/scummvm/scummvm/commit/20bdb154f60f590759627b4782e72e88d34bef2d
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-02-23T20:04:52-05:00

Commit Message:
XEEN: Fix _newDay initialization

Changed paths:
    engines/xeen/interface.cpp



diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp
index 4343207..e6305bf 100644
--- a/engines/xeen/interface.cpp
+++ b/engines/xeen/interface.cpp
@@ -182,7 +182,7 @@ void Interface::setup() {
 
 	Party &party = *_vm->_party;
 	party.loadActiveParty();
-	party._newDay = party._minutes >= 300;
+	party._newDay = party._minutes < 300;
 }
 
 void Interface::startup() {
@@ -581,7 +581,7 @@ void Interface::perform() {
 }
 
 void Interface::chargeStep() {
-	if (_vm->_party->_partyDead) {
+	if (!_vm->_party->_partyDead) {
 		_vm->_party->changeTime(_vm->_map->_isOutdoors ? 10 : 1);
 		if (!_tillMove) {
 			_vm->_combat->moveMonsters();


Commit: 5bb494fff10b17c6070cdd21e4f27903a6c1df74
    https://github.com/scummvm/scummvm/commit/5bb494fff10b17c6070cdd21e4f27903a6c1df74
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-02-25T07:37:09-05:00

Commit Message:
XEEN: Fix mosnters moving towards party

Changed paths:
    engines/xeen/combat.cpp
    engines/xeen/combat.h



diff --git a/engines/xeen/combat.cpp b/engines/xeen/combat.cpp
index 254c33f..69ffd72 100644
--- a/engines/xeen/combat.cpp
+++ b/engines/xeen/combat.cpp
@@ -462,7 +462,7 @@ void Combat::moveMonsters() {
 	for (int loopNum = 0; loopNum < 2; ++loopNum) {
 		int arrIndex = -1;
 		for (int yDiff = 3; yDiff >= -3; --yDiff) {
-			for (int xDiff = 3; xDiff >= -3; --xDiff) {
+			for (int xDiff = -3; xDiff <= 3; ++xDiff) {
 				Common::Point pt = party._mazePosition + Common::Point(xDiff, yDiff);
 				++arrIndex;
 
@@ -484,43 +484,43 @@ void Combat::moveMonsters() {
 									_rangeAttacking[idx] = true;
 								}
 							}
-						}
-					}
 
-					switch (party._mazeDirection) {
-					case DIR_NORTH:
-					case DIR_SOUTH:
-						if (monsterCanMove(pt, MONSTER_GRID_BITMASK[MONSTER_GRID_BITINDEX1[arrIndex]],
-								MONSTER_GRID_X[arrIndex], MONSTER_GRID_Y[arrIndex], idx)) {
-							// Move the monster
-							moveMonster(idx, Common::Point(MONSTER_GRID_X[arrIndex], MONSTER_GRID_Y[arrIndex]));
-						} else {
-							if (monsterCanMove(pt, MONSTER_GRID_BITMASK[MONSTER_GRID_BITINDEX2[arrIndex]],
-								arrIndex >= 21 && arrIndex <= 27 ? MONSTER_GRID3[arrIndex] : 0,
-								arrIndex >= 21 && arrIndex <= 27 ? 0 : MONSTER_GRID3[arrIndex],
-								idx))
-							if (arrIndex >= 21 && arrIndex <= 27) {
-								moveMonster(idx, Common::Point(MONSTER_GRID3[arrIndex], 0));
-							} else {
-								moveMonster(idx, Common::Point(0, MONSTER_GRID3[arrIndex]));
-							}
-						}
-						break;
+							switch (party._mazeDirection) {
+							case DIR_NORTH:
+							case DIR_SOUTH:
+								if (monsterCanMove(pt, MONSTER_GRID_BITMASK[MONSTER_GRID_BITINDEX1[arrIndex]],
+										MONSTER_GRID_X[arrIndex], MONSTER_GRID_Y[arrIndex], idx)) {
+									// Move the monster
+									moveMonster(idx, Common::Point(MONSTER_GRID_X[arrIndex], MONSTER_GRID_Y[arrIndex]));
+								} else {
+									if (monsterCanMove(pt, MONSTER_GRID_BITMASK[MONSTER_GRID_BITINDEX2[arrIndex]],
+										arrIndex >= 21 && arrIndex <= 27 ? MONSTER_GRID3[arrIndex] : 0,
+										arrIndex >= 21 && arrIndex <= 27 ? 0 : MONSTER_GRID3[arrIndex],
+										idx))
+									if (arrIndex >= 21 && arrIndex <= 27) {
+										moveMonster(idx, Common::Point(MONSTER_GRID3[arrIndex], 0));
+									} else {
+										moveMonster(idx, Common::Point(0, MONSTER_GRID3[arrIndex]));
+									}
+								}
+								break;
 
-					case DIR_EAST:
-					case DIR_WEST:
-						if (monsterCanMove(pt, MONSTER_GRID_BITMASK[MONSTER_GRID_BITINDEX2[arrIndex]],
-							arrIndex >= 21 && arrIndex <= 27 ? MONSTER_GRID3[arrIndex] : 0,
-							arrIndex >= 21 && arrIndex <= 27 ? 0 : MONSTER_GRID3[arrIndex],
-							idx)) {
-							if (arrIndex >= 21 && arrIndex <= 27) {
-								moveMonster(idx, Common::Point(MONSTER_GRID3[arrIndex], 0));
-							} else {
-								moveMonster(idx, Common::Point(0, MONSTER_GRID3[arrIndex]));
+							case DIR_EAST:
+							case DIR_WEST:
+								if (monsterCanMove(pt, MONSTER_GRID_BITMASK[MONSTER_GRID_BITINDEX2[arrIndex]],
+									arrIndex >= 21 && arrIndex <= 27 ? MONSTER_GRID3[arrIndex] : 0,
+									arrIndex >= 21 && arrIndex <= 27 ? 0 : MONSTER_GRID3[arrIndex],
+									idx)) {
+									if (arrIndex >= 21 && arrIndex <= 27) {
+										moveMonster(idx, Common::Point(MONSTER_GRID3[arrIndex], 0));
+									} else {
+										moveMonster(idx, Common::Point(0, MONSTER_GRID3[arrIndex]));
+									}
+								} else if (monsterCanMove(pt, MONSTER_GRID_BITMASK[MONSTER_GRID_BITINDEX1[arrIndex]],
+										MONSTER_GRID_X[arrIndex], MONSTER_GRID_Y[arrIndex], idx)) {
+									moveMonster(idx, Common::Point(MONSTER_GRID_X[arrIndex], MONSTER_GRID_Y[arrIndex]));
+								}
 							}
-						} else if (monsterCanMove(pt, MONSTER_GRID_BITMASK[MONSTER_GRID_BITINDEX1[arrIndex]],
-								MONSTER_GRID_X[arrIndex], MONSTER_GRID_Y[arrIndex], idx)) {
-							moveMonster(idx, Common::Point(MONSTER_GRID_X[arrIndex], MONSTER_GRID_Y[arrIndex]));
 						}
 					}
 				}
@@ -660,6 +660,9 @@ void Combat::setupMonsterAttack(int monsterDataIndex, const Common::Point &pt) {
 	}
 }
 
+/**
+ * Determines whether a given monster can move
+ */
 bool Combat::monsterCanMove(const Common::Point &pt, int wallShift,
 		int xDiff, int yDiff, int monsterId) {
 	Map &map = *_vm->_map;
@@ -702,14 +705,19 @@ bool Combat::monsterCanMove(const Common::Point &pt, int wallShift,
 	}
 }
 
-void Combat::moveMonster(int monsterId, const Common::Point &pt) {
+/**
+ * Moves a monster by a given delta amount if it's a valid move
+ */
+void Combat::moveMonster(int monsterId, const Common::Point &moveDelta) {
 	Map &map = *_vm->_map;
 	MazeMonster &monster = map._mobData._monsters[monsterId];
+	Common::Point newPos = monster._position + moveDelta;
 
-	if (_monsterMap[pt.y][pt.x] < 3 && !monster._damageType && _moveMonsters) {
-		++_monsterMap[pt.y][pt.x];
+	if (_monsterMap[newPos.y][newPos.x] < 3 && !monster._damageType && _moveMonsters) {
+		// Adjust monster's position
+		++_monsterMap[newPos.y][newPos.x];
 		--_monsterMap[monster._position.y][monster._position.x];
-		monster._position = pt;
+		monster._position = newPos;
 		_monsterMoved[monsterId] = true;
 	}
 }
@@ -754,7 +762,7 @@ void Combat::monsterOvercome() {
 		MazeMonster &monster = map._mobData._monsters[idx];
 		int dataIndex = monster._spriteId;
 
-		if (monster._damageType != 0 && monster._damageType != 13) {
+		if (monster._damageType != DT_PHYSICAL && monster._damageType != DT_DRAGONSLEEP) {
 			// Do a saving throw for monster
 			if (dataIndex <= _vm->getRandomNumber(1, dataIndex + 50))
 				monster._damageType = 0;
diff --git a/engines/xeen/combat.h b/engines/xeen/combat.h
index f78e928..d4cb87e 100644
--- a/engines/xeen/combat.h
+++ b/engines/xeen/combat.h
@@ -156,7 +156,7 @@ public:
 	bool monsterCanMove(const Common::Point &pt, int wallShift,
 		int v1, int v2, int monsterId);
 
-	void moveMonster(int monsterId, const Common::Point &pt);
+	void moveMonster(int monsterId, const Common::Point &moveDelta);
 
 	void attackMonster(int monsterId);
 


Commit: 0e1bd4951b4912ab4b555228d2da410da8ad4697
    https://github.com/scummvm/scummvm/commit/0e1bd4951b4912ab4b555228d2da410da8ad4697
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-02-25T07:54:57-05:00

Commit Message:
XEEN: Prevent double call to moveMonsters

Changed paths:
    engines/xeen/interface.cpp



diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp
index e6305bf..d69abef 100644
--- a/engines/xeen/interface.cpp
+++ b/engines/xeen/interface.cpp
@@ -583,7 +583,7 @@ void Interface::perform() {
 void Interface::chargeStep() {
 	if (!_vm->_party->_partyDead) {
 		_vm->_party->changeTime(_vm->_map->_isOutdoors ? 10 : 1);
-		if (!_tillMove) {
+		if (_tillMove) {
 			_vm->_combat->moveMonsters();
 		}
 


Commit: ad33b8bb824803630bc37766da30047efa3f3f13
    https://github.com/scummvm/scummvm/commit/ad33b8bb824803630bc37766da30047efa3f3f13
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-02-25T19:42:29-05:00

Commit Message:
XEEN: Fixed display of attacking monster names

Changed paths:
    engines/xeen/combat.cpp
    engines/xeen/map.cpp
    engines/xeen/map.h
    engines/xeen/resources.cpp



diff --git a/engines/xeen/combat.cpp b/engines/xeen/combat.cpp
index 69ffd72..df9ba9b 100644
--- a/engines/xeen/combat.cpp
+++ b/engines/xeen/combat.cpp
@@ -1073,11 +1073,8 @@ void Combat::setupCombatParty() {
 void Combat::setSpeedTable() {
 	Map &map = *_vm->_map;
 	Common::Array<int> charSpeeds;
-	bool flag = _whosSpeed != -1;
-	int oldSpeed = (_whosSpeed == -1) ? 0 : _speedTable[_whosSpeed];
-
-	Common::fill(&_speedTable[0], &_speedTable[12], -1);
-	Common::fill(&charSpeeds[0], &charSpeeds[12], -1);
+	bool hasSpeed = _whosSpeed != -1 && _whosSpeed < _speedTable.size();
+	int oldSpeed = hasSpeed ? _speedTable[_whosSpeed] : 0;
 
 	// Set up speeds for party membres
 	int maxSpeed = 0;
@@ -1101,6 +1098,8 @@ void Combat::setSpeedTable() {
 		}
 	}
 
+	// Populate the _speedTable list with the character/monster indexes
+	// in order of attacking speed
 	_speedTable.clear();
 	for (; maxSpeed >= 0; --maxSpeed) {
 		for (uint idx = 0; idx < charSpeeds.size(); ++idx) {
@@ -1109,7 +1108,7 @@ void Combat::setSpeedTable() {
 		}
 	}
 
-	if (flag) {
+	if (hasSpeed) {
 		if (_speedTable[_whosSpeed] != oldSpeed) {
 			for (uint idx = 0; idx < charSpeeds.size(); ++idx) {
 				if (oldSpeed == _speedTable[idx]) {
@@ -1164,10 +1163,12 @@ Common::String Combat::getMonsterDescriptions() {
 		if (_attackMonsters[idx] != -1) {
 			MazeMonster &monster = map._mobData._monsters[_attackMonsters[idx]];
 			MonsterStruct &monsterData = map._monsterData[monster._spriteId];
+			int textColor = monster.getTextColor();
 
 			Common::String format = "\n\v020\f%2u%s\fd";
 			format.setChar('2' + idx, 3);
-			lines[idx] = Common::String::format(format.c_str(), monsterData._name.c_str());
+			lines[idx] = Common::String::format(format.c_str(), textColor,
+				monsterData._name.c_str());
 		}
 	}
 
diff --git a/engines/xeen/map.cpp b/engines/xeen/map.cpp
index 10fba6d..439d5a8 100644
--- a/engines/xeen/map.cpp
+++ b/engines/xeen/map.cpp
@@ -662,6 +662,11 @@ MazeMonster::MazeMonster() {
 	_attackSprites = nullptr;
 }
 
+int MazeMonster::getTextColor() const {
+	warning("TODO: getTextColor");
+	return 0;
+}
+
 /*------------------------------------------------------------------------*/
 
 MazeWallItem::MazeWallItem() {
diff --git a/engines/xeen/map.h b/engines/xeen/map.h
index 7faf59f..85a1b8b 100644
--- a/engines/xeen/map.h
+++ b/engines/xeen/map.h
@@ -255,6 +255,8 @@ struct MazeMonster {
 	SpriteResource *_attackSprites;
 
 	MazeMonster();
+
+	int getTextColor() const;
 };
 
 class MazeWallItem {
diff --git a/engines/xeen/resources.cpp b/engines/xeen/resources.cpp
index bcf408d..2716f24 100644
--- a/engines/xeen/resources.cpp
+++ b/engines/xeen/resources.cpp
@@ -1489,7 +1489,7 @@ const int NEW_CHARACTER_SPELLS[10][4] = {
 	{ 20, 1, -1, -1 }
 };
 
-const char *const COMBAT_DETAILS = "\r\f00\x03c\v000\t000\x02Combat%s%s%s\x1";
+const char *const COMBAT_DETAILS = "\r\f00\x3""c\v000\t000\x2""Combat%s%s%s\x1";
 
 const char *NOT_ENOUGH_TO_CAST = "\x03c\v010Not enough %s to Cast %s";
 const char *SPELL_CAST_COMPONENTS[2] = { "Spell Points", "Gems" };


Commit: 9a8c4c55a3c4b243b95efb04eb72ca3808275b84
    https://github.com/scummvm/scummvm/commit/9a8c4c55a3c4b243b95efb04eb72ca3808275b84
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-02-25T20:08:26-05:00

Commit Message:
XEEN: Add a MonsterStruct pointer to the MazeMonster class

Changed paths:
    engines/xeen/combat.cpp
    engines/xeen/interface.cpp
    engines/xeen/interface_map.cpp
    engines/xeen/map.cpp
    engines/xeen/map.h
    engines/xeen/scripts.cpp



diff --git a/engines/xeen/combat.cpp b/engines/xeen/combat.cpp
index df9ba9b..c3590e7 100644
--- a/engines/xeen/combat.cpp
+++ b/engines/xeen/combat.cpp
@@ -468,7 +468,7 @@ void Combat::moveMonsters() {
 
 				for (int idx = 0; idx < (int)map._mobData._monsters.size(); ++idx) {
 					MazeMonster &monster = map._mobData._monsters[idx];
-					MonsterStruct &monsterData = map._monsterData[monster._spriteId];
+					MonsterStruct &monsterData = *monster._monsterData;
 
 					if (pt == monster._position) {
 						_dangerPresent = true;
@@ -667,7 +667,7 @@ bool Combat::monsterCanMove(const Common::Point &pt, int wallShift,
 		int xDiff, int yDiff, int monsterId) {
 	Map &map = *_vm->_map;
 	MazeMonster &monster = map._mobData._monsters[monsterId];
-	MonsterStruct &monsterData = map._monsterData[monster._spriteId];
+	MonsterStruct &monsterData = *monster._monsterData;
 
 	Common::Point tempPos = pt;
 	if (map._isOutdoors) {
@@ -798,7 +798,7 @@ void Combat::attackMonster(int monsterId) {
 	} 
 
 	MazeMonster &monster = map._mobData._monsters[monsterIndex];
-	MonsterStruct &monsterData = map._monsterData[monster._spriteId];
+	MonsterStruct &monsterData = *monster._monsterData;
 	if (monster._damageType)
 		return;
 
@@ -1089,7 +1089,7 @@ void Combat::setSpeedTable() {
 	for (int monsterNum = 0; monsterNum < 3; ++monsterNum) {
 		if (_attackMonsters[monsterNum] != -1) {
 			MazeMonster &monster = map._mobData._monsters[_attackMonsters[monsterNum]];
-			MonsterStruct &monsterData = map._monsterData[monster._spriteId];
+			MonsterStruct &monsterData = *monster._monsterData;
 			charSpeeds.push_back(monsterData._speed);
 
 			maxSpeed = MAX(maxSpeed, monsterData._speed);
@@ -1162,7 +1162,7 @@ Common::String Combat::getMonsterDescriptions() {
 	for (int idx = 0; idx < 3; ++idx) {
 		if (_attackMonsters[idx] != -1) {
 			MazeMonster &monster = map._mobData._monsters[_attackMonsters[idx]];
-			MonsterStruct &monsterData = map._monsterData[monster._spriteId];
+			MonsterStruct &monsterData = *monster._monsterData;
 			int textColor = monster.getTextColor();
 
 			Common::String format = "\n\v020\f%2u%s\fd";
@@ -1395,7 +1395,7 @@ void Combat::attack2(int damage, RangeType rangeType) {
 	SoundManager &sound = *_vm->_sound;
 	bool isDarkCc = _vm->_files->_isDarkCc;
 	MazeMonster &monster = map._mobData._monsters[_monster2Attack];
-	MonsterStruct &monsterData = map._monsterData[monster._spriteId];
+	MonsterStruct &monsterData = *monster._monsterData;
 	bool monsterDied = false;
 
 	if (!isDarkCc && damage && rangeType && monster._spriteId == 89)
@@ -1669,7 +1669,7 @@ bool Combat::hitMonster(Character &c, RangeType rangeType) {
 
 	assert(_monster2Attack != -1);
 	MazeMonster &monster = map._mobData._monsters[_monster2Attack];
-	MonsterStruct &monsterData = map._monsterData[monster._spriteId];
+	MonsterStruct &monsterData = *monster._monsterData;
 
 	if (monster._damageType != DT_PHYSICAL)
 		chance += 20;
@@ -1737,7 +1737,7 @@ int Combat::getMonsterResistence(RangeType rangeType) {
 	Map &map = *_vm->_map;
 	assert(_monster2Attack != -1);
 	MazeMonster &monster = map._mobData._monsters[_monster2Attack];
-	MonsterStruct &monsterData = map._monsterData[monster._spriteId];
+	MonsterStruct &monsterData = *monster._monsterData;
 	int resistence = 0, damage = 0;
 
 	if (rangeType != RT_0 && rangeType != RT_3) {
diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp
index d69abef..611eccb 100644
--- a/engines/xeen/interface.cpp
+++ b/engines/xeen/interface.cpp
@@ -1924,7 +1924,7 @@ void Interface::doCombat() {
 
 				if (++index == 5 && combat._attackMonsters[0] != -1) {
 					MazeMonster &monster = map._mobData._monsters[combat._monster2Attack];
-					MonsterStruct &monsterData = map._monsterData[monster._spriteId];
+					MonsterStruct &monsterData = *monster._monsterData;
 					sound.playFX(monsterData._fx);
 				}
 
diff --git a/engines/xeen/interface_map.cpp b/engines/xeen/interface_map.cpp
index a54b95f..de19a99 100644
--- a/engines/xeen/interface_map.cpp
+++ b/engines/xeen/interface_map.cpp
@@ -707,7 +707,7 @@ void InterfaceMap::animate3d() {
 		MazeMonster &monster = map._mobData._monsters[idx];
 		if (!monster._damageType) {
 			if (monster._frame < 8) {
-				MonsterStruct &monsterData = map._monsterData[monster._spriteId];
+				MonsterStruct &monsterData = *monster._monsterData;
 				if (!monsterData._loopAnimation) {
 					// Monster isn't specially looped, so cycle through the 8 frames
 					monster._frame = (monster._frame + 1) % 8;
@@ -755,7 +755,7 @@ void InterfaceMap::animate3d() {
 		} else {
 			monster._effect3 = (monster._effect3 + 1) % 8;
 			if (monster._effect3 == 0) {
-				MonsterStruct &monsterData = map._monsterData[monster._spriteId];
+				MonsterStruct &monsterData = *monster._monsterData;
 				monster._effect1 = monster._effect2 = monsterData._animationEffect;
 			}
 		}
@@ -2625,7 +2625,7 @@ void InterfaceMap::setIndoorsMonsters() {
  */
 void InterfaceMap::setMonsterSprite(DrawStruct &drawStruct, MazeMonster &monster, SpriteResource *sprites, 
 		int frame, int defaultY) {
-	MonsterStruct &monsterData = _vm->_map->_monsterData[monster._spriteId];
+	MonsterStruct &monsterData = *monster._monsterData;
 	bool flying = monsterData._flying;
 
 	drawStruct._frame = frame;
@@ -3331,7 +3331,7 @@ void InterfaceMap::setOutdoorsMonsters() {
 
 			// TODO: Double-check.. this section looks *weird*
 			MazeMonster &monster = map._mobData._monsters[ds._frame];
-			MonsterStruct &monsterData = map._monsterData[monster._spriteId];
+			MonsterStruct &monsterData = *monster._monsterData;
 
 			ds._frame = monster._frame;
 
diff --git a/engines/xeen/map.cpp b/engines/xeen/map.cpp
index 439d5a8..2017978 100644
--- a/engines/xeen/map.cpp
+++ b/engines/xeen/map.cpp
@@ -660,11 +660,20 @@ MazeMonster::MazeMonster() {
 	_effect3 = 0;
 	_sprites = nullptr;
 	_attackSprites = nullptr;
+	_monsterData = nullptr;
 }
 
+/**
+ * Return the text color to use when displaying the monster's name in combat
+ * to indicate how damaged they are
+ */
 int MazeMonster::getTextColor() const {
-	warning("TODO: getTextColor");
-	return 0;
+	if (_hp == _monsterData->_hp)
+		return 15;
+	else if (_hp >= (_monsterData->_hp / 2))
+		return 9;
+	else
+		return 32;
 }
 
 /*------------------------------------------------------------------------*/
@@ -682,7 +691,7 @@ MazeWallItem::MazeWallItem() {
 MonsterObjectData::MonsterObjectData(XeenEngine *vm): _vm(vm) {
 }
 
-void MonsterObjectData::synchronize(XeenSerializer &s, MonsterData monsterData) {
+void MonsterObjectData::synchronize(XeenSerializer &s, MonsterData &monsterData) {
 	Common::Array<MobStruct> mobStructs;
 	MobStruct mobStruct;
 	byte b;
@@ -781,10 +790,11 @@ void MonsterObjectData::synchronize(XeenSerializer &s, MonsterData monsterData)
 			mon._spriteId = _monsterSprites[mon._id]._spriteId;
 			mon._sprites = &_monsterSprites[mon._id]._sprites;
 			mon._attackSprites = &_monsterSprites[mon._id]._attackSprites;
+			mon._monsterData = &monsterData[mon._spriteId];
+			mon._frame = _vm->getRandomNumber(7);
 
-			MonsterStruct &md = monsterData[mon._spriteId];
+			MonsterStruct &md = *mon._monsterData;
 			mon._hp = md._hp;
-			mon._frame = _vm->getRandomNumber(7);
 			mon._effect1 = mon._effect2 = md._animationEffect;
 			if (md._animationEffect)
 				mon._effect3 = _vm->getRandomNumber(7);
diff --git a/engines/xeen/map.h b/engines/xeen/map.h
index 85a1b8b..bd74837 100644
--- a/engines/xeen/map.h
+++ b/engines/xeen/map.h
@@ -253,6 +253,7 @@ struct MazeMonster {
 	int _effect3;
 	SpriteResource *_sprites;
 	SpriteResource *_attackSprites;
+	MonsterStruct *_monsterData;
 
 	MazeMonster();
 
@@ -306,7 +307,7 @@ public:
 public:
 	MonsterObjectData(XeenEngine *vm);
 
-	void synchronize(XeenSerializer &s, MonsterData monsterData);
+	void synchronize(XeenSerializer &s, MonsterData &monsterData);
 };
 
 class HeadData {
diff --git a/engines/xeen/scripts.cpp b/engines/xeen/scripts.cpp
index 7aab04c..0d701fe 100644
--- a/engines/xeen/scripts.cpp
+++ b/engines/xeen/scripts.cpp
@@ -503,6 +503,7 @@ void Scripts::cmdSpawn(Common::Array<byte> &params) {
 
 	MazeMonster &monster = _vm->_map->_mobData._monsters[params[0]];
 	MonsterStruct &monsterData = _vm->_map->_monsterData[monster._spriteId];
+	monster._monsterData = &monsterData;
 	monster._position.x = params[1];
 	monster._position.y = params[2];
 	monster._frame = _vm->getRandomNumber(7);


Commit: 9b6749cab8908b45a9c7176faa5d142b72bcde0b
    https://github.com/scummvm/scummvm/commit/9b6749cab8908b45a9c7176faa5d142b72bcde0b
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-02-25T20:25:27-05:00

Commit Message:
XEEN: Fix display of combat action buttons

Changed paths:
    engines/xeen/interface.cpp
    engines/xeen/interface.h



diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp
index 611eccb..47db309 100644
--- a/engines/xeen/interface.cpp
+++ b/engines/xeen/interface.cpp
@@ -1223,7 +1223,7 @@ void Interface::bash(const Common::Point &pt, Direction direction) {
 	drawParty(true);
 }
 
-void Interface::draw3d(bool updateFlag) {
+void Interface::draw3d(bool updateFlag, bool skipDelay) {
 	Combat &combat = *_vm->_combat;
 	EventsManager &events = *_vm->_events;
 	Party &party = *_vm->_party;
@@ -1282,11 +1282,7 @@ void Interface::draw3d(bool updateFlag) {
 		// TODO: Save current scripts data?
 	}
 
-	// TODO: Check use of updateFlag here. Original doesn't have it, but I
-	// wanted to ensure in places like the AutoMapDialog, that the draw3d
-	// doesn't result in the screen updating until the dialog has had
-	// a chance to full render itself
-	if (updateFlag)
+	if (!skipDelay)
 		events.wait(2);
 }
 
@@ -1871,7 +1867,7 @@ void Interface::doCombat() {
 
 	_iconSprites.load("combat.icn");
 	for (int idx = 1; idx < 16; ++idx)
-		_mainList[idx]._sprites = nullptr;
+		_mainList[idx]._sprites = &_iconSprites;
 
 	// Set the combat buttons
 	setMainButtons(true);
diff --git a/engines/xeen/interface.h b/engines/xeen/interface.h
index 66a40c2..f5e5cc3 100644
--- a/engines/xeen/interface.h
+++ b/engines/xeen/interface.h
@@ -140,7 +140,7 @@ public:
 
 	void bash(const Common::Point &pt, Direction direction);
 
-	void draw3d(bool updateFlag);
+	void draw3d(bool updateFlag, bool skipDelay = false);
 
 	void assembleBorder();
 


Commit: b4c8c81a83eb95467def7de0e2c5d4c0d931d541
    https://github.com/scummvm/scummvm/commit/b4c8c81a83eb95467def7de0e2c5d4c0d931d541
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-02-25T21:54:03-05:00

Commit Message:
XEEN: Properly reimplement nextChar

Changed paths:
    engines/xeen/interface.cpp



diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp
index 47db309..74749d4 100644
--- a/engines/xeen/interface.cpp
+++ b/engines/xeen/interface.cpp
@@ -1885,6 +1885,13 @@ void Interface::doCombat() {
 	// Set up the combat party
 	combat.setupCombatParty();
 	combat.setSpeedTable();
+
+	// Initialize arrays for character/monster states
+	combat._charsGone.resize(combat._speedTable.size());
+	combat._charsBlocked.resize(combat._speedTable.size());
+	Common::fill(&combat._charsGone[0], &combat._charsGone[0] + combat._speedTable.size(), 0);
+	Common::fill(&combat._charsBlocked[0], &combat._charsBlocked[0] + combat._speedTable.size(), false);
+
 	combat._whosSpeed = -1;
 	combat._whosTurn = -1;
 	resetHighlight();
@@ -1893,6 +1900,7 @@ void Interface::doCombat() {
 
 	if (!party._dead) {
 		combat.setSpeedTable();
+
 		if (_tillMove) {
 			combat.moveMonsters();
 			draw3d(true);
@@ -2160,6 +2168,8 @@ void Interface::nextChar() {
 		return;
 	}
 
+	// Loop for potentially multiple monsters attacking until it's time
+	// for one of the party's turn
 	for (;;) {
 		// Check if party is dead
 		party.checkPartyDead();
@@ -2168,50 +2178,53 @@ void Interface::nextChar() {
 			break;
 		}
 
-		if (combat._whosTurn < (int)combat._combatParty.size()) {
-			if (!combat.allHaveGone())
-				highlightChar(combat._whosTurn);
-			break;
-		} else {
-			combat.attackMonster(0);
-			if (!party._dead)
-				party.checkPartyDead();
-
-			if (party._dead)
-				break;
-		}
-
-		// Check the combat participants
-		bool resetFlag = false;
-		for (uint idx = 0; idx < combat._speedTable.size(); ++idx) {
-			// Mark the given character as haven taken their turn
+		int idx;
+		for (idx = 0; idx < (int)combat._speedTable.size(); ++idx) {
 			if (combat._whosTurn != -1) {
 				combat._charsGone[combat._whosTurn] = true;
 			}
 
-			combat._whosSpeed %= combat._speedTable.size();
+			combat._whosSpeed = (combat._whosSpeed + 1) % combat._speedTable.size();
 			combat._whosTurn = combat._speedTable[combat._whosSpeed];
-
 			if (combat.allHaveGone()) {
-				if (combat.charsCantAct()) {
-					combat.setSpeedTable();
-					combat._whosTurn = -1;
-					combat._whosSpeed = -1;
-
-					combat._charsGone.resize(combat._speedTable.size());
-					Common::fill(&combat._charsGone[0], &combat._charsGone[combat._charsGone.size()], 0);
-					resetFlag = true;
-					break;
-				}
-				return;
-			} else if (combat._whosTurn >= (int)combat._combatParty.size() ||
-					!combat._combatParty[combat._whosTurn]->isDisabledOrDead()) {
+				idx = -1;
 				break;
 			}
+
+			if (combat._whosTurn < (int)combat._combatParty.size()) {
+				if (!combat._combatParty[idx]->isDisabledOrDead())
+					continue;
+			}
+
+			break;
 		}
 
-		if (party._dead)
+		if (idx == -1) {
+			if (!combat.charsCantAct())
+				return;
+
+			combat.setSpeedTable();
+			combat._whosTurn = -1;
+			combat._whosSpeed = -1;
+			Common::fill(&combat._charsGone[0], &combat._charsGone[0] + combat._charsGone.size(), 0);
+			continue;
+		}
+
+		if (combat._whosTurn < (int)combat._combatParty.size()) {
+			// It's a party character's turn now, so highlight the character
+			if (!combat.allHaveGone()) {
+				highlightChar(combat._whosTurn);
+			}
 			break;
+		} else {
+			// It's a monster's turn to attack
+			combat.attackMonster(0);
+			if (!party._dead) {
+				party.checkPartyDead();
+				if (party._dead)
+					break;
+			}
+		}
 	}
 }
 


Commit: 4191335dfabc0baff9459a61e5453dad6270582f
    https://github.com/scummvm/scummvm/commit/4191335dfabc0baff9459a61e5453dad6270582f
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-02-25T22:03:57-05:00

Commit Message:
XEEN: Method rename and compilation warning fixes

Changed paths:
    engines/xeen/combat.cpp
    engines/xeen/combat.h
    engines/xeen/interface.cpp



diff --git a/engines/xeen/combat.cpp b/engines/xeen/combat.cpp
index c3590e7..1aa41fb 100644
--- a/engines/xeen/combat.cpp
+++ b/engines/xeen/combat.cpp
@@ -621,7 +621,7 @@ void Combat::monstersAttack() {
 
 	for (int idx = 0; idx < 36; ++idx) {
 		if (_gmonHit[idx] != -1)
-			attackMonster(_gmonHit[idx]);
+			doMonsterTurn(_gmonHit[idx]);
 	}
 
 	_monstersAttacking = false;
@@ -770,7 +770,7 @@ void Combat::monsterOvercome() {
 	}
 }
 
-void Combat::attackMonster(int monsterId) {
+void Combat::doMonsterTurn(int monsterId) {
 	Interface &intf = *_vm->_interface;
 	Map &map = *_vm->_map;
 	Party &party = *_vm->_party;
@@ -808,7 +808,7 @@ void Combat::attackMonster(int monsterId) {
 	intf.draw3d(true);
 	intf.draw3d(true);
 
-	File f(monsterData._attackVoc);
+	File f(Common::String::format("%s.voc", monsterData._attackVoc.c_str()));
 	sound.playSample(&f, 0);
 	bool flag = false;
 
@@ -1073,7 +1073,7 @@ void Combat::setupCombatParty() {
 void Combat::setSpeedTable() {
 	Map &map = *_vm->_map;
 	Common::Array<int> charSpeeds;
-	bool hasSpeed = _whosSpeed != -1 && _whosSpeed < _speedTable.size();
+	bool hasSpeed = _whosSpeed != -1 && _whosSpeed < (int)_speedTable.size();
 	int oldSpeed = hasSpeed ? _speedTable[_whosSpeed] : 0;
 
 	// Set up speeds for party membres
diff --git a/engines/xeen/combat.h b/engines/xeen/combat.h
index d4cb87e..4783819 100644
--- a/engines/xeen/combat.h
+++ b/engines/xeen/combat.h
@@ -158,7 +158,7 @@ public:
 
 	void moveMonster(int monsterId, const Common::Point &moveDelta);
 
-	void attackMonster(int monsterId);
+	void doMonsterTurn(int monsterId);
 
 	void endAttack();
 
diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp
index 74749d4..c06ef79 100644
--- a/engines/xeen/interface.cpp
+++ b/engines/xeen/interface.cpp
@@ -2218,7 +2218,7 @@ void Interface::nextChar() {
 			break;
 		} else {
 			// It's a monster's turn to attack
-			combat.attackMonster(0);
+			combat.doMonsterTurn(0);
 			if (!party._dead) {
 				party.checkPartyDead();
 				if (party._dead)


Commit: 68e30b2967797537a951c5126b89fdb905138cb6
    https://github.com/scummvm/scummvm/commit/68e30b2967797537a951c5126b89fdb905138cb6
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-02-26T08:10:01-05:00

Commit Message:
XEEN: Fix monster/party taking turns in combat

Changed paths:
    engines/xeen/combat.cpp
    engines/xeen/interface.cpp



diff --git a/engines/xeen/combat.cpp b/engines/xeen/combat.cpp
index 1aa41fb..4e32d43 100644
--- a/engines/xeen/combat.cpp
+++ b/engines/xeen/combat.cpp
@@ -777,41 +777,40 @@ void Combat::doMonsterTurn(int monsterId) {
 	SoundManager &sound = *_vm->_sound;
 
 	if (_monstersAttacking) {
-		warning("TODO: Original used uninitialized variables if flag was set");
-		return;
-	}
+		int monsterIndex;
+		switch (_whosTurn - _combatParty.size()) {
+		case 0:
+			monsterIndex = _attackMonsters[0];
+			intf._indoorList[156]._scale = 0;
+			break;
+		case 1:
+			monsterIndex = _attackMonsters[1];
+			intf._indoorList[150]._scale = 0;
+			break;
+		case 2:
+		default:
+			monsterIndex = _attackMonsters[2];
+			intf._indoorList[153]._scale = 0;
+		}
 
-	int monsterIndex;
-	switch (_whosTurn - _combatParty.size()) {
-	case 0:
-		monsterIndex = _attackMonsters[0];
-		intf._indoorList[156]._scale = 0;
-		break;
-	case 1:
-		monsterIndex = _attackMonsters[1];
-		intf._indoorList[150]._scale = 0;
-		break;
-	case 2:
-	default:
-		monsterIndex = _attackMonsters[2];
-		intf._indoorList[153]._scale = 0;
-	} 
+		MazeMonster &monster = map._mobData._monsters[monsterIndex];
+		MonsterStruct &monsterData = *monster._monsterData;
+		if (monster._damageType)
+			return;
 
-	MazeMonster &monster = map._mobData._monsters[monsterIndex];
-	MonsterStruct &monsterData = *monster._monsterData;
-	if (monster._damageType)
-		return;
+		monster._frame = 8;
+		monster._fieldA = 3;
+		monster._field9 = 0;
+		intf.draw3d(true);
+		intf.draw3d(true);
 
-	monster._frame = 8;
-	monster._fieldA = 3;
-	monster._field9 = 0;
-	intf.draw3d(true);
-	intf.draw3d(true);
+		File f(Common::String::format("%s.voc", monsterData._attackVoc.c_str()));
+		sound.playSample(&f, 0);
+		monsterId = monster._spriteId;
+	}
 
-	File f(Common::String::format("%s.voc", monsterData._attackVoc.c_str()));
-	sound.playSample(&f, 0);
+	MonsterStruct &monsterData = map._monsterData[monsterId];
 	bool flag = false;
-
 	for (int attackNum = 0; attackNum < monsterData._numberOfAttacks; ++attackNum) {
 		int charNum = -1;
 		bool isHated = false;
@@ -918,14 +917,14 @@ void Combat::doMonsterTurn(int monsterId) {
 			if (true) {
 				Character &c = *_combatParty[charNum];
 				if (monsterData._attackType != DT_PHYSICAL || c._conditions[ASLEEP]) {
-					doCharDamage(c, charNum, monster._spriteId);
+					doCharDamage(c, charNum, monsterId);
 				} else {
 					int v = _vm->getRandomNumber(1, 20);
 					if (v == 1) {
 						sound.playFX(6);
 					} else {
 						if (v == 20)
-							doCharDamage(c, charNum, monster._spriteId);
+							doCharDamage(c, charNum, monsterId);
 						v += monsterData._hitChance / 4 + _vm->getRandomNumber(1,
 							monsterData._hitChance);
 
@@ -934,7 +933,7 @@ void Combat::doMonsterTurn(int monsterId) {
 						if (ac > v) {
 							sound.playFX(6);
 						} else {
-							doCharDamage(c, charNum, monster._spriteId);
+							doCharDamage(c, charNum, monsterId);
 						}
 					}
 				}
diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp
index c06ef79..6c65dd4 100644
--- a/engines/xeen/interface.cpp
+++ b/engines/xeen/interface.cpp
@@ -2192,7 +2192,9 @@ void Interface::nextChar() {
 			}
 
 			if (combat._whosTurn < (int)combat._combatParty.size()) {
-				if (!combat._combatParty[idx]->isDisabledOrDead())
+				// If it's a party member, only allow them to become active if
+				// they're still conscious
+				if (combat._combatParty[idx]->isDisabledOrDead())
 					continue;
 			}
 


Commit: 19007bac4088f4933410438c242814915b20e4ac
    https://github.com/scummvm/scummvm/commit/19007bac4088f4933410438c242814915b20e4ac
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-02-26T08:29:04-05:00

Commit Message:
XEEN: Fix hang calling checkEvents when in combat mode

Changed paths:
    engines/xeen/scripts.cpp



diff --git a/engines/xeen/scripts.cpp b/engines/xeen/scripts.cpp
index 0d701fe..ef101b9 100644
--- a/engines/xeen/scripts.cpp
+++ b/engines/xeen/scripts.cpp
@@ -167,7 +167,7 @@ int Scripts::checkEvents() {
 			if (eventIndex == map._events.size())
 				_lineNum = -1;
 		}
-	} while (!_vm->shouldQuit() && _lineNum != -1);
+	} while (!_vm->shouldQuit() && !_eventSkipped && _lineNum != -1);
 
 	intf._face1State = intf._face2State = 2;
 	if (_refreshIcons) {


Commit: c069a7f805b18428d095a0adf643753ceeaa59e3
    https://github.com/scummvm/scummvm/commit/c069a7f805b18428d095a0adf643753ceeaa59e3
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-02-26T19:58:05-05:00

Commit Message:
XEEN: Fix mode change across display of CastSpell dialog

Changed paths:
    engines/xeen/dialogs_spells.cpp
    engines/xeen/dialogs_spells.h
    engines/xeen/interface.cpp



diff --git a/engines/xeen/dialogs_spells.cpp b/engines/xeen/dialogs_spells.cpp
index ea423aa..9a19ac2 100644
--- a/engines/xeen/dialogs_spells.cpp
+++ b/engines/xeen/dialogs_spells.cpp
@@ -435,7 +435,7 @@ const char *SpellsDialog::setSpellText(Character *c, int isCasting) {
 
 /*------------------------------------------------------------------------*/
 
-int CastSpell::show(XeenEngine *vm, int mode) {
+int CastSpell::show(XeenEngine *vm) {
 	Combat &combat = *vm->_combat;
 	Interface &intf = *vm->_interface;
 	Party &party = *vm->_party;
@@ -443,7 +443,7 @@ int CastSpell::show(XeenEngine *vm, int mode) {
 	int charNum;
 
 	// Get which character is doing the casting
-	if (mode == MODE_COMBAT) {
+	if (vm->_mode == MODE_COMBAT) {
 		charNum = combat._whosTurn;
 	} else if (spells._lastCaster >= 0 && spells._lastCaster < (int)party._activeParty.size()) {
 		charNum = spells._lastCaster;
@@ -460,21 +460,21 @@ int CastSpell::show(XeenEngine *vm, int mode) {
 	intf.highlightChar(charNum);
 
 	CastSpell *dlg = new CastSpell(vm);
-	int spellId = dlg->execute(c, mode);
+	int spellId = dlg->execute(c);
 	delete dlg;
 
 	return spellId;
 }
 
-int CastSpell::show(XeenEngine *vm, Character *&c, int mode) {
+int CastSpell::show(XeenEngine *vm, Character *&c) {
 	CastSpell *dlg = new CastSpell(vm);
-	int spellId = dlg->execute(c, mode);
+	int spellId = dlg->execute(c);
 	delete dlg;
 
 	return spellId;
 }
 
-int CastSpell::execute(Character *&c, int mode) {
+int CastSpell::execute(Character *&c) {
 	EventsManager &events = *_vm->_events;
 	Interface &intf = *_vm->_interface;
 	Party &party = *_vm->_party;
@@ -482,7 +482,8 @@ int CastSpell::execute(Character *&c, int mode) {
 	Spells &spells = *_vm->_spells;
 	Window &w = screen._windows[10];
 
-	Mode oldMode = (Mode)mode;
+	Mode oldMode = _vm->_mode;
+	_vm->_mode = MODE_3;
 
 	w.open();
 	loadButtons();
@@ -503,7 +504,6 @@ int CastSpell::execute(Character *&c, int mode) {
 			drawButtons(&screen);
 			w.update();
 
-			_vm->_mode = MODE_3;
 			redrawFlag = false;
 		}
 
@@ -565,6 +565,7 @@ int CastSpell::execute(Character *&c, int mode) {
 	if (_vm->shouldQuit())
 		spellId = -1;
 
+	_vm->_mode = oldMode;
 	return spellId;
 }
 
diff --git a/engines/xeen/dialogs_spells.h b/engines/xeen/dialogs_spells.h
index 32d0790..6a9e43f 100644
--- a/engines/xeen/dialogs_spells.h
+++ b/engines/xeen/dialogs_spells.h
@@ -65,12 +65,12 @@ private:
 
 	CastSpell(XeenEngine *vm) : ButtonContainer(), _vm(vm) {}
 
-	int execute(Character *&c, int mode);
+	int execute(Character *&c);
 
 	void loadButtons();
 public:
-	static int show(XeenEngine *vm, int mode);
-	static int show(XeenEngine *vm, Character *&c, int mode);
+	static int show(XeenEngine *vm);
+	static int show(XeenEngine *vm, Character *&c);
 };
 
 } // End of namespace Xeen
diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp
index 6c65dd4..076437a 100644
--- a/engines/xeen/interface.cpp
+++ b/engines/xeen/interface.cpp
@@ -531,7 +531,7 @@ void Interface::perform() {
 			spells._lastCaster >= (int)party._activeParty.size()) ?
 			(int)party._activeParty.size() - 1 : spells._lastCaster];
 		do {
-			int spellId = CastSpell::show(_vm, c, _vm->_mode);
+			int spellId = CastSpell::show(_vm, c);
 			if (spellId == -1 || c == nullptr)
 				break;
 
@@ -1975,10 +1975,13 @@ void Interface::doCombat() {
 				
 			case Common::KEYCODE_c: {
 				// Cast spell
-				int spellId = CastSpell::show(_vm, _vm->_mode);
+				int spellId = CastSpell::show(_vm);
 				if (spellId != -1) {
 					Character *c = combat._combatParty[combat._whosTurn];
 					spells.castSpell(c, spellId);
+					nextChar();
+				} else {
+					highlightChar(combat._combatParty[combat._whosTurn]->_rosterId);
 				}
 				break;
 			}


Commit: dc7e4153d4fb7de1d8e2241fe9b836e4680cf650
    https://github.com/scummvm/scummvm/commit/dc7e4153d4fb7de1d8e2241fe9b836e4680cf650
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-02-26T20:50:49-05:00

Commit Message:
XEEN: Fixes for attacking monsters

Changed paths:
    engines/xeen/combat.cpp
    engines/xeen/combat.h
    engines/xeen/interface.cpp



diff --git a/engines/xeen/combat.cpp b/engines/xeen/combat.cpp
index 4e32d43..fca7fcb 100644
--- a/engines/xeen/combat.cpp
+++ b/engines/xeen/combat.cpp
@@ -1342,11 +1342,11 @@ void Combat::attack(Character &c, RangeType rangeType) {
 			break;
 		}
 
-		int numberOfAttacks = c.getCurrentLevel() / divisor;
+		int numberOfAttacks = c.getCurrentLevel() / divisor + 1;
 		damage = 0;
 
 		while (numberOfAttacks-- > 0) {
-			if (hitMonster(c, RT_0))
+			if (hitMonster(c, RT_CLOSE))
 				damage += getMonsterDamage(c);
 		}
 
@@ -1593,7 +1593,7 @@ void Combat::quickFight() {
 
 	switch (c->_quickOption) {
 	case QUICK_ATTACK:
-		attack(*c, RT_0);
+		attack(*c, RT_CLOSE);
 		break;
 	case QUICK_SPELL:
 		if (c->_currentSpell != -1) {
@@ -1720,7 +1720,7 @@ void Combat::getWeaponDamage(Character &c, RangeType rangeType) {
 }
 
 int Combat::getMonsterDamage(Character &c) {
-	return (c.statBonus(c.getStat(MIGHT)) + _weaponDamage) < 1;
+	return MAX(c.statBonus(c.getStat(MIGHT)) + _weaponDamage, 1);
 }
 
 int Combat::getDamageScale(int v) {
@@ -1739,7 +1739,7 @@ int Combat::getMonsterResistence(RangeType rangeType) {
 	MonsterStruct &monsterData = *monster._monsterData;
 	int resistence = 0, damage = 0;
 
-	if (rangeType != RT_0 && rangeType != RT_3) {
+	if (rangeType != RT_CLOSE && rangeType != RT_3) {
 		switch (_damageType) {
 		case DT_PHYSICAL:
 			resistence = monsterData._phsyicalResistence;
diff --git a/engines/xeen/combat.h b/engines/xeen/combat.h
index 4783819..bf35ca8 100644
--- a/engines/xeen/combat.h
+++ b/engines/xeen/combat.h
@@ -57,7 +57,7 @@ enum ElementalCategory {
 };
 
 enum RangeType {
-	RT_0 = 0, RT_1 = 1, RT_2 = 2, RT_3 = 3
+	RT_CLOSE = 0, RT_1 = 1, RT_2 = 2, RT_3 = 3
 };
 
 class XeenEngine;
diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp
index 076437a..01cd494 100644
--- a/engines/xeen/interface.cpp
+++ b/engines/xeen/interface.cpp
@@ -1963,7 +1963,7 @@ void Interface::doCombat() {
 
 			case Common::KEYCODE_a:
 				// Attack
-				combat.attack(*combat._combatParty[combat._whosTurn], RT_0);
+				combat.attack(*combat._combatParty[combat._whosTurn], RT_CLOSE);
 				nextChar();
 				break;
 


Commit: 349ad82f93f44f521c8023dd88e962d4835be98b
    https://github.com/scummvm/scummvm/commit/349ad82f93f44f521c8023dd88e962d4835be98b
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-02-26T21:35:45-05:00

Commit Message:
XEEN: Fix moving backwards

Changed paths:
    engines/xeen/interface.cpp



diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp
index 01cd494..de4137e 100644
--- a/engines/xeen/interface.cpp
+++ b/engines/xeen/interface.cpp
@@ -920,7 +920,7 @@ bool Interface::checkMoveDirection(int key) {
 			(Direction)(party._mazeDirection + 1);
 		break;
 	case Common::KEYCODE_DOWN:
-		party._mazeDirection = (party._mazeDirection == DIR_NORTH) ? DIR_SOUTH : DIR_NORTH;
+		party._mazeDirection = (Direction)((int)party._mazeDirection ^ 2);
 		break;
 	default:
 		break;


Commit: b46561ef293da3299ff4e7fb85ffd49222faab67
    https://github.com/scummvm/scummvm/commit/b46561ef293da3299ff4e7fb85ffd49222faab67
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-02-27T07:50:32-05:00

Commit Message:
XEEN: Implemented openGrate

Changed paths:
    engines/xeen/dialogs_whowill.cpp
    engines/xeen/interface.cpp
    engines/xeen/resources.cpp
    engines/xeen/scripts.cpp
    engines/xeen/scripts.h
    engines/xeen/xeen.cpp



diff --git a/engines/xeen/dialogs_whowill.cpp b/engines/xeen/dialogs_whowill.cpp
index 10bbae2..fd72154 100644
--- a/engines/xeen/dialogs_whowill.cpp
+++ b/engines/xeen/dialogs_whowill.cpp
@@ -84,8 +84,8 @@ int WhoWill::execute(int message, int action, bool type) {
 		if (_buttonValue == 27) {
 			_buttonValue = 0;
 			break;
-		} else if (_buttonValue >= 201 && _buttonValue <= 206) {
-			_buttonValue -= 201;
+		} else if (_buttonValue >= Common::KEYCODE_F1 && _buttonValue <= Common::KEYCODE_F6) {
+			_buttonValue -= Common::KEYCODE_F1 - 1;
 			if (_buttonValue > (int)party._activeParty.size())
 				continue;
 
@@ -97,7 +97,6 @@ int WhoWill::execute(int message, int action, bool type) {
 		}
 	}
 
-
 	intf._face1State = intf._face2State = 2;
 	screen._windows[36].close();
 	return _buttonValue;
diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp
index de4137e..ded3d9c 100644
--- a/engines/xeen/interface.cpp
+++ b/engines/xeen/interface.cpp
@@ -269,22 +269,24 @@ void Interface::perform() {
 	Party &party = *_vm->_party;
 	Scripts &scripts = *_vm->_scripts;
 	Spells &spells = *_vm->_spells;
-	const Common::Rect waitBounds(8, 8, 224, 140);
+	const Common::Rect WAIT_BOUNDS(8, 8, 224, 140);
 
 	events.updateGameCounter();
 	draw3d(true);
 
-	// Wait for a frame
+	// Wait for a frame or a user event
 	do {
 		events.pollEventsAndWait();
 		checkEvents(_vm);
+
+		if (events._leftButton && WAIT_BOUNDS.contains(events._mousePos))
+			_buttonValue = Common::KEYCODE_SPACE;
 	} while (!_buttonValue && events.timeElapsed() < 1 && !_vm->_party->_partyDead);
 
 	if (!_buttonValue && !_vm->_party->_partyDead)
 		return;
 
-	if (_buttonValue == Common::KEYCODE_SPACE ||
-			(events._leftButton && waitBounds.contains(events._mousePos))) {
+	if (_buttonValue == Common::KEYCODE_SPACE) {
 		int lookupId = map.mazeLookup(party._mazePosition, 
 			WALL_SHIFTS[party._mazeDirection][2]);
 
diff --git a/engines/xeen/resources.cpp b/engines/xeen/resources.cpp
index 2716f24..5c76d29 100644
--- a/engines/xeen/resources.cpp
+++ b/engines/xeen/resources.cpp
@@ -107,10 +107,10 @@ const char *const SURFACE_NAMES[16] = {
 };
 
 const char *const WHO_ACTIONS[32] = {
-	"aSearch", "aOpen", "aDrink", "aMine", "aTouch", "aRead", "aLearn", "aTake",
-	"aBang", "aSteal", "aBribe", "aPay", "aSit", "aTry", "aTurn", "aBathe",
-	"aDestroy", "aPull", "aDescend", "aTossACoin", "aPray", "aJoin", "aAct",
-	"aPlay", "aPush", "aRub", "aPick", "aEat", "aSign", "aClose", "aLook", "aTry"
+	"search", "open", "drink", "mine", "touch", "read", "learn", "take",
+	"bang", "steal", "bribe", "pay", "sit", "try", "turn", "bathe",
+	"destroy", "pull", "descend", "toss a coin", "pray", "join", "act",
+	"play", "push", "rub", "pick", "eat", "sign", "close", "look", "try"
 };
 
 const char *const WHO_WILL_ACTIONS[4] = {
diff --git a/engines/xeen/scripts.cpp b/engines/xeen/scripts.cpp
index ef101b9..f1bce04 100644
--- a/engines/xeen/scripts.cpp
+++ b/engines/xeen/scripts.cpp
@@ -207,12 +207,63 @@ int Scripts::checkEvents() {
 	return _scriptResult;
 }
 
-void Scripts::giveTreasure() {
-	// TODO
-}
+void Scripts::openGrate(int wallVal, int action) {
+	Combat &combat = *_vm->_combat;
+	Interface &intf = *_vm->_interface;
+	Map &map = *_vm->_map;
+	Party &party = *_vm->_party;
+	SoundManager &sound = *_vm->_sound;
+	bool isDarkCc = _vm->_files->_isDarkCc;
+
+	if ((wallVal != 13 || map._currentIsGrate) && (!isDarkCc || wallVal != 9 ||
+			map.mazeData()._wallKind != 2)) {
+		if (wallVal != 9 && !map._currentIsGrate) {
+			int charIndex = WhoWill::show(_vm, 13, action, false) - 1;
+			if (charIndex >= 0) {
+				// There is a 1 in 4 chance the character will receive damage
+				if (_vm->getRandomNumber(1, 4) == 1) {
+					combat.giveCharDamage(map.mazeData()._trapDamage,
+						(DamageType)_vm->getRandomNumber(0, 6), charIndex);
+				}
 
-void Scripts::openGrate(int v1, int v2) {
-	// TODO
+				// Check whether character can unlock the door
+				Character &c = party._activeParty[charIndex];
+				if ((c.getThievery() + _vm->getRandomNumber(1, 20)) <
+						map.mazeData()._difficulties._unlockDoor)
+					return;
+
+				c._experience += map.mazeData()._difficulties._unlockDoor * c.getCurrentLevel();
+			}
+
+			// Set the wall state for the wall party is facing
+			map.setCellSurfaceFlags(party._mazePosition, 0x80);
+			map.setWall(party._mazePosition, party._mazeDirection, wallVal);
+
+			// Set the wall state for the reverse wall in the next cell over
+			Common::Point pt = party._mazePosition;
+			Direction dir = (Direction)((int)party._mazeDirection ^ 2);
+			switch (party._mazeDirection) {
+			case DIR_NORTH:
+				pt.y++;
+				break;
+			case DIR_EAST:
+				pt.x++;
+				break;
+			case DIR_SOUTH:
+				pt.y--;
+				break;
+			case DIR_WEST:
+				pt.x--;
+				break;
+			}
+
+			map.setCellSurfaceFlags(pt, 0x80);
+			map.setWall(pt, dir, wallVal);
+			sound.playFX(10);
+		}
+
+		intf.draw3d(true);
+	}
 }
 
 typedef void(Scripts::*ScriptMethodPtr)(Common::Array<byte> &);
diff --git a/engines/xeen/scripts.h b/engines/xeen/scripts.h
index 1db672b..d347ec0 100644
--- a/engines/xeen/scripts.h
+++ b/engines/xeen/scripts.h
@@ -233,9 +233,7 @@ public:
 
 	int checkEvents();
 
-	void giveTreasure();
-
-	void openGrate(int v1, int v2);
+	void openGrate(int v1, int action);
 };
 
 } // End of namespace Xeen
diff --git a/engines/xeen/xeen.cpp b/engines/xeen/xeen.cpp
index 1410d65..a1604a5 100644
--- a/engines/xeen/xeen.cpp
+++ b/engines/xeen/xeen.cpp
@@ -333,7 +333,7 @@ void XeenEngine::gameLoop() {
 			if (shouldQuit() || _quitMode)
 				return;
 		}
-		_scripts->giveTreasure();
+		_party->giveTreasure();
 
 		// Main user interface handler for waiting for and processing user input
 		_interface->perform();


Commit: b9539c6cb168ecabda994353a453e050b380487f
    https://github.com/scummvm/scummvm/commit/b9539c6cb168ecabda994353a453e050b380487f
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-02-27T20:52:59-05:00

Commit Message:
XEEN: Fixes for marking grates as unlocked

Changed paths:
    engines/xeen/interface.cpp
    engines/xeen/map.cpp
    engines/xeen/map.h
    engines/xeen/scripts.cpp
    engines/xeen/scripts.h



diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp
index ded3d9c..0354732 100644
--- a/engines/xeen/interface.cpp
+++ b/engines/xeen/interface.cpp
@@ -299,12 +299,14 @@ void Interface::perform() {
 			}
 
 		case 6:
+			// Open grate being closed
 			if (!map._isOutdoors) {
 				scripts.openGrate(9, 0);
 				eventsFlag = _buttonValue != 0;
 			}
 			break;
 		case 9:
+			// Closed grate being opened
 			if (!map._isOutdoors) {
 				scripts.openGrate(6, 0);
 				eventsFlag = _buttonValue != 0;
diff --git a/engines/xeen/map.cpp b/engines/xeen/map.cpp
index 2017978..e5a5531 100644
--- a/engines/xeen/map.cpp
+++ b/engines/xeen/map.cpp
@@ -891,7 +891,7 @@ Map::Map(XeenEngine *vm) : _vm(vm), _mobData(vm) {
 	_currentSurfaceId = 0;
 	_currentWall = 0;
 	_currentTile = 0;
-	_currentIsGrate = false;
+	_currentGrateUnlocked = false;
 	_currentCantRest = false;
 	_currentIsDrain = false;
 	_currentIsEvent = false;
@@ -1383,7 +1383,7 @@ void Map::cellFlagLookup(const Common::Point &pt) {
 
 	// Get the cell flags
 	const MazeCell &cell = _mazeData[_mazeDataIndex]._cells[pos.y][pos.x];
-	_currentIsGrate = cell._flags & OUTFLAG_GRATE;
+	_currentGrateUnlocked = cell._flags & OUTFLAG_GRATE;
 	_currentCantRest = cell._flags & RESTRICTION_REST;
 	_currentIsDrain = cell._flags & OUTFLAG_DRAIN;
 	_currentIsEvent = cell._flags & FLAG_AUTOEXECUTE_EVENT;
@@ -1393,14 +1393,17 @@ void Map::cellFlagLookup(const Common::Point &pt) {
 
 void Map::setCellSurfaceFlags(const Common::Point &pt, int bits) {
 	mazeLookup(pt, 0);
-	_mazeData[0]._cells[pt.y][pt.x]._surfaceId |= bits;
+
+	Common::Point mapPos(pt.x & 15, pt.y & 15);
+	_mazeData[_mazeDataIndex]._cells[mapPos.y][mapPos.x]._surfaceId |= bits;
 }
 
 void Map::setWall(const Common::Point &pt, Direction dir, int v) {
 	const int XOR_MASKS[4] = { 0xFFF, 0xF0FF, 0xFF0F, 0xFFF0 };
 	mazeLookup(pt, 0, 0);
 	
-	MazeWallLayers &wallLayer = _mazeData[0]._wallData[pt.y][pt.x];
+	Common::Point mapPos(pt.x & 15, pt.y & 15);
+	MazeWallLayers &wallLayer = _mazeData[_mazeDataIndex]._wallData[mapPos.y][mapPos.x];
 	wallLayer._data &= XOR_MASKS[dir];
 	wallLayer._data |= v << WALL_SHIFTS[dir][2];
 }
diff --git a/engines/xeen/map.h b/engines/xeen/map.h
index bd74837..bfc09ec 100644
--- a/engines/xeen/map.h
+++ b/engines/xeen/map.h
@@ -376,7 +376,7 @@ public:
 	SpriteResource _tileSprites;
 	SpriteResource _surfaceSprites[TOTAL_SURFACES];
 	WallSprites _wallSprites;
-	bool _currentIsGrate;
+	bool _currentGrateUnlocked;
 	bool _currentCantRest;
 	bool _currentIsDrain;
 	bool _currentIsEvent;
diff --git a/engines/xeen/scripts.cpp b/engines/xeen/scripts.cpp
index f1bce04..4af7af1 100644
--- a/engines/xeen/scripts.cpp
+++ b/engines/xeen/scripts.cpp
@@ -215,53 +215,56 @@ void Scripts::openGrate(int wallVal, int action) {
 	SoundManager &sound = *_vm->_sound;
 	bool isDarkCc = _vm->_files->_isDarkCc;
 
-	if ((wallVal != 13 || map._currentIsGrate) && (!isDarkCc || wallVal != 9 ||
+	if ((wallVal != 13 || map._currentGrateUnlocked) && (!isDarkCc || wallVal != 9 ||
 			map.mazeData()._wallKind != 2)) {
-		if (wallVal != 9 && !map._currentIsGrate) {
+		if (wallVal != 9 && !map._currentGrateUnlocked) {
 			int charIndex = WhoWill::show(_vm, 13, action, false) - 1;
-			if (charIndex >= 0) {
-				// There is a 1 in 4 chance the character will receive damage
-				if (_vm->getRandomNumber(1, 4) == 1) {
-					combat.giveCharDamage(map.mazeData()._trapDamage,
-						(DamageType)_vm->getRandomNumber(0, 6), charIndex);
-				}
-
-				// Check whether character can unlock the door
-				Character &c = party._activeParty[charIndex];
-				if ((c.getThievery() + _vm->getRandomNumber(1, 20)) <
-						map.mazeData()._difficulties._unlockDoor)
-					return;
+			if (charIndex < 0) {
+				intf.draw3d(true);
+				return;
+			}
 
-				c._experience += map.mazeData()._difficulties._unlockDoor * c.getCurrentLevel();
+			// There is a 1 in 4 chance the character will receive damage
+			if (_vm->getRandomNumber(1, 4) == 1) {
+				combat.giveCharDamage(map.mazeData()._trapDamage,
+					(DamageType)_vm->getRandomNumber(0, 6), charIndex);
 			}
 
-			// Set the wall state for the wall party is facing
-			map.setCellSurfaceFlags(party._mazePosition, 0x80);
-			map.setWall(party._mazePosition, party._mazeDirection, wallVal);
+			// Check whether character can unlock the door
+			Character &c = party._activeParty[charIndex];
+			if ((c.getThievery() + _vm->getRandomNumber(1, 20)) <
+					map.mazeData()._difficulties._unlockDoor)
+				return;
 
-			// Set the wall state for the reverse wall in the next cell over
-			Common::Point pt = party._mazePosition;
-			Direction dir = (Direction)((int)party._mazeDirection ^ 2);
-			switch (party._mazeDirection) {
-			case DIR_NORTH:
-				pt.y++;
-				break;
-			case DIR_EAST:
-				pt.x++;
-				break;
-			case DIR_SOUTH:
-				pt.y--;
-				break;
-			case DIR_WEST:
-				pt.x--;
-				break;
-			}
+			c._experience += map.mazeData()._difficulties._unlockDoor * c.getCurrentLevel();
+		}
+
+		// Flag the grate as unlocked, and the wall the grate is on
+		map.setCellSurfaceFlags(party._mazePosition, 0x80);
+		map.setWall(party._mazePosition, party._mazeDirection, wallVal);
 
-			map.setCellSurfaceFlags(pt, 0x80);
-			map.setWall(pt, dir, wallVal);
-			sound.playFX(10);
+		// Set the grate as opened and the wall on the other side of the grate
+		Common::Point pt = party._mazePosition;
+		Direction dir = (Direction)((int)party._mazeDirection ^ 2);
+		switch (party._mazeDirection) {
+		case DIR_NORTH:
+			pt.y++;
+			break;
+		case DIR_EAST:
+			pt.x++;
+			break;
+		case DIR_SOUTH:
+			pt.y--;
+			break;
+		case DIR_WEST:
+			pt.x--;
+			break;
 		}
 
+		map.setCellSurfaceFlags(pt, 0x80);
+		map.setWall(pt, dir, wallVal);
+
+		sound.playFX(10);
 		intf.draw3d(true);
 	}
 }
diff --git a/engines/xeen/scripts.h b/engines/xeen/scripts.h
index d347ec0..3a835d8 100644
--- a/engines/xeen/scripts.h
+++ b/engines/xeen/scripts.h
@@ -233,7 +233,7 @@ public:
 
 	int checkEvents();
 
-	void openGrate(int v1, int action);
+	void openGrate(int wallVal, int action);
 };
 
 } // End of namespace Xeen


Commit: 302b3cdc63fe24b4c702c260935879fd7f477bd5
    https://github.com/scummvm/scummvm/commit/302b3cdc63fe24b4c702c260935879fd7f477bd5
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-02-27T21:33:07-05:00

Commit Message:
XEEN: Fix updating cell flag that grate is unlocked

Changed paths:
    engines/xeen/map.cpp



diff --git a/engines/xeen/map.cpp b/engines/xeen/map.cpp
index e5a5531..021c417 100644
--- a/engines/xeen/map.cpp
+++ b/engines/xeen/map.cpp
@@ -1395,7 +1395,8 @@ void Map::setCellSurfaceFlags(const Common::Point &pt, int bits) {
 	mazeLookup(pt, 0);
 
 	Common::Point mapPos(pt.x & 15, pt.y & 15);
-	_mazeData[_mazeDataIndex]._cells[mapPos.y][mapPos.x]._surfaceId |= bits;
+	MazeCell &cell = _mazeData[_mazeDataIndex]._cells[mapPos.y][mapPos.x];
+	cell._flags |= bits & 0xF8;
 }
 
 void Map::setWall(const Common::Point &pt, Direction dir, int v) {
@@ -1453,7 +1454,7 @@ int Map::getCell(int idx) {
 				if (_vm->_files->_isDarkCc) {
 					if ((mapId >= 53 && mapId <= 88 && mapId != 73) || (mapId >= 74 && mapId <= 120) ||
 						mapId == 125 || mapId == 126 || mapId == 128 || mapId == 129) {
-						_currentSurfaceId = SURFTYPE_DESERT;
+						_currentSurfaceId = 6;
 					} else {
 						_currentSurfaceId = 0;
 					}
@@ -1489,7 +1490,7 @@ int Map::getCell(int idx) {
 				if (_vm->_files->_isDarkCc) {
 					if ((mapId >= 53 && mapId <= 88 && mapId != 73) || (mapId >= 74 && mapId <= 120) ||
 						mapId == 125 || mapId == 126 || mapId == 128 || mapId == 129) {
-						_currentSurfaceId = SURFTYPE_DESERT;
+						_currentSurfaceId = 6;
 					} else {
 						_currentSurfaceId = 0;
 					}
@@ -1524,7 +1525,7 @@ int Map::getCell(int idx) {
 			return 0;
 
 		if (pt.x > 31 || pt.y > 31)
-			_currentSurfaceId = SURFTYPE_ROAD;
+			_currentSurfaceId = 7;
 		else
 			_currentSurfaceId = _mazeData[_mazeDataIndex]._cells[pt.y][pt.x]._surfaceId;
 


Commit: 973c5a0df5bf9f86cc589a7a138899b96684bf23
    https://github.com/scummvm/scummvm/commit/973c5a0df5bf9f86cc589a7a138899b96684bf23
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-02-28T12:45:33-05:00

Commit Message:
XEEN: Implemented multiAttack

Changed paths:
    engines/xeen/character.cpp
    engines/xeen/character.h
    engines/xeen/combat.cpp
    engines/xeen/combat.h
    engines/xeen/interface.cpp
    engines/xeen/spells.cpp



diff --git a/engines/xeen/character.cpp b/engines/xeen/character.cpp
index e005a35..d95e061 100644
--- a/engines/xeen/character.cpp
+++ b/engines/xeen/character.cpp
@@ -1848,6 +1848,16 @@ bool Character::hasSpecialItem() const {
 	return false;
 }
 
+bool Character::hasMissileWeapon() const {
+	for (uint idx = 0; idx < INV_ITEMS_TOTAL; ++idx) {
+		if (_weapons[idx]._frame == 4) {
+			return !isDisabledOrDead();
+		}
+	}
+
+	return false;
+}
+
 int Character::getClassCategory() const {
 	switch (_class) {
 	case CLASS_ARCHER:
diff --git a/engines/xeen/character.h b/engines/xeen/character.h
index 9e858da..77ab882 100644
--- a/engines/xeen/character.h
+++ b/engines/xeen/character.h
@@ -326,6 +326,8 @@ public:
 
 	bool hasSpecialItem() const;
 
+	bool hasMissileWeapon() const;
+
 	int getClassCategory() const;
 };
 
diff --git a/engines/xeen/combat.cpp b/engines/xeen/combat.cpp
index fca7fcb..763daa7 100644
--- a/engines/xeen/combat.cpp
+++ b/engines/xeen/combat.cpp
@@ -116,7 +116,7 @@ Combat::Combat(XeenEngine *vm): _vm(vm), _missVoc("miss.voc"), _pow1Voc("pow1.vo
 	_whosSpeed = 0;
 	_damageType = DT_PHYSICAL;
 	_oldCharacter = nullptr;
-	_shootType = 0;
+	_shootType = ST_0;
 	_monsterDamage = 0;
 	_weaponDamage = 0;
 	_weaponDie = _weaponDice = 0;
@@ -125,6 +125,7 @@ Combat::Combat(XeenEngine *vm): _vm(vm), _missVoc("miss.voc"), _pow1Voc("pow1.vo
 	_hitChanceBonus = 0;
 	_dangerPresent = false;
 	_moveMonsters = false;
+	_rangeType = RT_SINGLE;
 }
 
 void Combat::clear() {
@@ -1198,7 +1199,7 @@ void Combat::attack(Character &c, RangeType rangeType) {
 	MonsterStruct &monsterData = map._monsterData[monsterDataIndex];
 
 	if (rangeType) {
-		if (_shootType != 1 || _damageType == DT_MAGIC_ARROW) {
+		if (_shootType != ST_1 || _damageType == DT_MAGIC_ARROW) {
 			if (!monsterData._magicResistence || monsterData._magicResistence <=
 					_vm->getRandomNumber(1, 100 + _oldCharacter->getCurrentLevel())) {
 				if (_monsterDamage != 0) {
@@ -1216,25 +1217,25 @@ void Combat::attack(Character &c, RangeType rangeType) {
 						if ((monsterData._monsterType == MONSTER_ANIMAL || monsterData._monsterType == MONSTER_HUMANOID)
 							&& !monsterSavingThrow(monsterDataIndex)) {
 							damage = MIN(monster._hp, 50);
-							attack2(damage, RT_2);
+							attack2(damage, RT_ALL);
 							setSpeedTable();
 						}
 						break;
 					case DT_HOLYWORD:
 						if (monsterData._monsterType == MONSTER_UNDEAD) {
-							attack2(monster._hp, RT_2);
+							attack2(monster._hp, RT_ALL);
 							setSpeedTable();
 						}
 						break;
 					case DT_MASS_DISTORTION:
-						attack2(MAX(monster._hp / 2, 1), RT_2);
+						attack2(MAX(monster._hp / 2, 1), RT_ALL);
 						setSpeedTable();
 						break;
 					case DT_UNDEAD:
 						if (monsterData._monsterType == MONSTER_UNDEAD)
 							damage = 25;
 						else
-							rangeType = RT_2;
+							rangeType = RT_ALL;
 						attack2(damage, rangeType);
 						setSpeedTable();
 						break;
@@ -1346,7 +1347,7 @@ void Combat::attack(Character &c, RangeType rangeType) {
 		damage = 0;
 
 		while (numberOfAttacks-- > 0) {
-			if (hitMonster(c, RT_CLOSE))
+			if (hitMonster(c, RT_SINGLE))
 				damage += getMonsterDamage(c);
 		}
 
@@ -1593,7 +1594,7 @@ void Combat::quickFight() {
 
 	switch (c->_quickOption) {
 	case QUICK_ATTACK:
-		attack(*c, RT_CLOSE);
+		attack(*c, RT_SINGLE);
 		break;
 	case QUICK_SPELL:
 		if (c->_currentSpell != -1) {
@@ -1739,7 +1740,7 @@ int Combat::getMonsterResistence(RangeType rangeType) {
 	MonsterStruct &monsterData = *monster._monsterData;
 	int resistence = 0, damage = 0;
 
-	if (rangeType != RT_CLOSE && rangeType != RT_3) {
+	if (rangeType != RT_SINGLE && rangeType != RT_3) {
 		switch (_damageType) {
 		case DT_PHYSICAL:
 			resistence = monsterData._phsyicalResistence;
@@ -1825,4 +1826,261 @@ void Combat::giveExperience(int experience) {
 	}
 }
 
+void Combat::multiAttack(int powNum) {
+	Interface &intf = *_vm->_interface;
+	Map &map = *_vm->_map;
+	Party &party = *_vm->_party;
+	SoundManager &sound = *_vm->_sound;
+
+	if (_damageType == DT_POISON_VOLLEY) {
+		_damageType = DT_POISON;
+		_shootType = ST_1;
+		Common::fill(&_shooting[0], &_shooting[6], 1);
+	} else if (powNum == 11) {
+		_shootType = ST_1;
+		bool flag = false;
+
+		if (_damageType == DT_PHYSICAL) {
+			for (uint idx = 0; idx < party._activeParty.size(); ++idx) {
+				Character &c = party._activeParty[idx];
+				if (c.hasMissileWeapon()) {
+					_shooting[idx] = 1;
+					flag = true;
+				}
+			}
+		} else {
+			_shooting[0] = 1;
+			flag = true;
+		}
+
+		if (!flag) {
+			sound.playFX(21);
+			return;
+		}
+	} else {
+		_shooting[0] = 1;
+		_shootType = ST_0;
+	}
+
+	intf._charsShooting = true;
+	_powSprites.load(Common::String::format("pow%d.icn", powNum));
+	int monsterIndex = _monsterIndex;
+	int monster2Attack = _monster2Attack;
+	bool attackedFlag = false;
+	
+	Common::Array<int> attackMonsters;
+	for (int idx = 0; idx < 3; ++idx) {
+		if (_attackMonsters[idx] != -1)
+			attackMonsters.push_back(_attackMonsters[idx]);
+	}
+
+	_monsterIndex = -1;
+	if (_monster2Attack != -1) {
+		_monsterIndex--;
+		if (attackMonsters.empty())
+			attackMonsters.resize(1);
+		attackMonsters[0] = monster2Attack;
+	}
+
+	for (uint idx = 0; idx < party._activeParty.size(); ++idx) {
+		Character &c = party._activeParty[idx];
+		if (_shooting[idx]) {
+			if (map._isOutdoors) {
+				intf._outdoorList._attackImgs1[idx]._scale = 0;
+				intf._outdoorList._attackImgs2[idx]._scale = 4;
+				intf._outdoorList._attackImgs3[idx]._scale = 8;
+				intf._outdoorList._attackImgs4[idx]._scale = 12;
+				intf._outdoorList._attackImgs1[idx]._sprites = &_powSprites;
+				intf._outdoorList._attackImgs2[idx]._sprites = nullptr;
+				intf._outdoorList._attackImgs3[idx]._sprites = nullptr;
+				intf._outdoorList._attackImgs4[idx]._sprites = nullptr;
+			} else {
+				intf._indoorList._attackImgs1[idx]._scale = 0;
+				intf._indoorList._attackImgs2[idx]._scale = 4;
+				intf._indoorList._attackImgs3[idx]._scale = 8;
+				intf._indoorList._attackImgs4[idx]._scale = 12;
+				intf._indoorList._attackImgs1[idx]._sprites = &_powSprites;
+				intf._indoorList._attackImgs2[idx]._sprites = nullptr;
+				intf._indoorList._attackImgs3[idx]._sprites = nullptr;
+				intf._indoorList._attackImgs4[idx]._sprites = nullptr;
+			}
+		}
+	}
+
+	intf.draw3d(true);
+
+	++_monsterIndex;
+	for (uint monIdx = 0; monIdx < attackMonsters.size(); ++monIdx, ++_monsterIndex) {
+		Common::fill(&_missedShot[0], &_missedShot[8], false);
+		_monster2Attack = attackMonsters[monIdx];
+		attack(*_oldCharacter, RT_GROUP);
+		attackedFlag = true;
+
+		if (_rangeType == RT_SINGLE)
+			// Only single shot, so exit now that the attack is done
+			goto finished;
+	}
+
+	if (attackedFlag && _rangeType == RT_GROUP)
+		// Finished group attack, so exit
+		goto finished;
+
+	if (map._isOutdoors) {
+		map.getCell(7);
+		switch (map._currentWall) {
+		case 1:
+		case 3:
+		case 6:
+		case 7:
+		case 9:
+		case 10:
+		case 12:
+			sound.playFX(46);
+			goto finished;
+		default:
+			break;
+		}
+	} else {
+		int cell = map.getCell(2);
+		if (cell < map.mazeData()._difficulties._wallNoPass) {
+			sound.playFX(46);
+			goto finished;
+		}
+	}
+	if (!intf._isAttacking)
+		goto finished;
+
+	intf.draw3d(true);
+
+	// Start handling second teir of monsters in the back
+	attackMonsters.clear();
+	for (uint idx = 3; idx < 6; ++idx) {
+		if (_attackMonsters[idx] != -1)
+			attackMonsters.push_back(_attackMonsters[idx]);
+	}
+
+	++_monsterIndex;
+	for (uint monIdx = 0; monIdx < attackMonsters.size(); ++monIdx, ++_monsterIndex) {
+		Common::fill(&_missedShot[0], &_missedShot[8], false);
+		_monster2Attack = attackMonsters[monIdx];
+		attack(*_oldCharacter, RT_GROUP);
+		attackedFlag = true;
+
+		if (_rangeType == RT_SINGLE)
+			// Only single shot, so exit now that the attack is done
+			goto finished;
+	}
+
+	if (attackedFlag && _rangeType == RT_GROUP)
+		// Finished group attack, so exit
+		goto finished;
+
+	if (map._isOutdoors) {
+		map.getCell(14);
+		switch (map._currentWall) {
+		case 1:
+		case 3:
+		case 6:
+		case 7:
+		case 9:
+		case 10:
+		case 12:
+			sound.playFX(46);
+			goto finished;
+		default:
+			break;
+		}
+	} else {
+		int cell = map.getCell(7);
+		if (cell < map.mazeData()._difficulties._wallNoPass) {
+			sound.playFX(46);
+			goto finished;
+		}
+	}
+	if (!intf._isAttacking)
+		goto finished;
+
+	intf.draw3d(true);
+
+	// Start handling third teir of monsters in the back
+	attackMonsters.clear();
+	for (uint idx = 6; idx < 9; ++idx) {
+		if (_attackMonsters[idx] != -1)
+			attackMonsters.push_back(_attackMonsters[idx]);
+	}
+
+	++_monsterIndex;
+	for (uint monIdx = 0; monIdx < attackMonsters.size(); ++monIdx, ++_monsterIndex) {
+		Common::fill(&_missedShot[0], &_missedShot[8], false);
+		_monster2Attack = attackMonsters[monIdx];
+		attack(*_oldCharacter, RT_GROUP);
+		attackedFlag = true;
+
+		if (_rangeType == RT_SINGLE)
+			// Only single shot, so exit now that the attack is done
+			goto finished;
+	}
+
+	if (attackedFlag && _rangeType == RT_GROUP)
+		// Finished group attack, so exit
+		goto finished;
+
+	if (map._isOutdoors) {
+		map.getCell(27);
+		switch (map._currentWall) {
+		case 1:
+		case 3:
+		case 6:
+		case 7:
+		case 9:
+		case 10:
+		case 12:
+			sound.playFX(46);
+			goto finished;
+		default:
+			break;
+		}
+	} else {
+		int cell = map.getCell(14);
+		if (cell < map.mazeData()._difficulties._wallNoPass) {
+			sound.playFX(46);
+			goto finished;
+		}
+	}
+	if (!intf._isAttacking)
+		goto finished;
+
+	intf.draw3d(true);
+
+	// Fourth tier
+	attackMonsters.clear();
+	for (uint idx = 9; idx < 12; ++idx) {
+		if (_attackMonsters[idx] != -1)
+			attackMonsters.push_back(_attackMonsters[idx]);
+	}
+
+	++_monsterIndex;
+	for (uint monIdx = 0; monIdx < attackMonsters.size(); ++monIdx, ++_monsterIndex) {
+		Common::fill(&_missedShot[0], &_missedShot[8], false);
+		_monster2Attack = attackMonsters[monIdx];
+		attack(*_oldCharacter, RT_GROUP);
+		attackedFlag = true;
+
+		if (_rangeType == RT_SINGLE)
+			// Only single shot, so exit now that the attack is done
+			goto finished;
+	}
+
+	if (!(attackedFlag && _rangeType == RT_GROUP))
+		goto done;
+
+finished:
+	endAttack();
+done:
+	Common::fill(&_shooting[0], &_shooting[MAX_PARTY_COUNT], 0);
+	_monster2Attack = monster2Attack;
+	_monsterIndex = monsterIndex;
+	party.giveTreasure();
+}
+
 } // End of namespace Xeen
diff --git a/engines/xeen/combat.h b/engines/xeen/combat.h
index bf35ca8..9831f90 100644
--- a/engines/xeen/combat.h
+++ b/engines/xeen/combat.h
@@ -39,7 +39,7 @@ enum DamageType {
 	DT_FINGEROFDEATH = 8, DT_HOLYWORD = 9, DT_MASS_DISTORTION = 10,
 	DT_UNDEAD = 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
+	DT_POISON_VOLLEY = 17, DT_MAGIC_ARROW = 18
 };
 
 enum SpecialAttack {
@@ -57,7 +57,11 @@ enum ElementalCategory {
 };
 
 enum RangeType {
-	RT_CLOSE = 0, RT_1 = 1, RT_2 = 2, RT_3 = 3
+	RT_SINGLE = 0, RT_GROUP = 1, RT_ALL = 2, RT_3 = 3
+};
+
+enum ShootType {
+	ST_0 = 0, ST_1 = 1
 };
 
 class XeenEngine;
@@ -110,7 +114,6 @@ public:
 	int _whosSpeed;
 	DamageType _damageType;
 	Character *_oldCharacter;
-	int _shootType;
 	int _monsterDamage;
 	int _weaponDamage;
 	int _weaponDie, _weaponDice;
@@ -120,6 +123,8 @@ public:
 	int _hitChanceBonus;
 	bool _dangerPresent;
 	bool _moveMonsters;
+	RangeType _rangeType;
+	ShootType _shootType;
 public:
 	Combat(XeenEngine *vm);
 
@@ -165,6 +170,8 @@ public:
 	void monsterOvercome();
 
 	int stopAttack(const Common::Point &diffPt);
+
+	void multiAttack(int powNum);
 };
 
 } // End of namespace Xeen
diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp
index 0354732..7339e10 100644
--- a/engines/xeen/interface.cpp
+++ b/engines/xeen/interface.cpp
@@ -1967,7 +1967,7 @@ void Interface::doCombat() {
 
 			case Common::KEYCODE_a:
 				// Attack
-				combat.attack(*combat._combatParty[combat._whosTurn], RT_CLOSE);
+				combat.attack(*combat._combatParty[combat._whosTurn], RT_SINGLE);
 				nextChar();
 				break;
 
diff --git a/engines/xeen/spells.cpp b/engines/xeen/spells.cpp
index 25aae11..53c43b5 100644
--- a/engines/xeen/spells.cpp
+++ b/engines/xeen/spells.cpp
@@ -198,10 +198,41 @@ void Spells::addSpellCost(Character &c, int spellId) {
 	party._gems += gemCost;
 }
 
+void Spells::light() { 
+	Interface &intf = *_vm->_interface;
+	Party &party = *_vm->_party;
+	SoundManager &sound = *_vm->_sound;
+
+	++party._lightCount;
+	if (intf._intrIndex1)
+		party._stepped = true;
+	sound.playFX(39);
+}
+
+void Spells::awaken() { 
+	Interface &intf = *_vm->_interface;
+	Party &party = *_vm->_party;
+	SoundManager &sound = *_vm->_sound;
+
+	for (uint idx = 0; idx < party._activeParty.size(); ++idx) {
+		Character &c = party._activeParty[idx];
+		c._conditions[ASLEEP] = 0;
+		if (c._currentHp > 0)
+			c._conditions[UNCONSCIOUS] = 0;
+	}
+
+	intf.drawParty(true);
+	sound.playFX(30);
+}
+
+void Spells::magicArrow() { 
+	Combat &combat = *_vm->_combat;
+	combat._monsterDamage = 0;
+	combat._damageType = DT_MAGIC_ARROW;
+	combat._rangeType = RT_SINGLE;
+	combat.multiAttack(11);
+}
 
-void Spells::light() { error("TODO: spell"); }
-void Spells::awaken() { error("TODO: spell"); }
-void Spells::magicArrow() { error("TODO: spell"); }
 void Spells::firstAid() { error("TODO: spell"); }
 void Spells::flyingFist() { error("TODO: spell"); }
 void Spells::energyBlast() { error("TODO: spell"); }


Commit: b378709478fc689de8a1a0b455deb12e6aee5fb2
    https://github.com/scummvm/scummvm/commit/b378709478fc689de8a1a0b455deb12e6aee5fb2
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-02-28T13:00:35-05:00

Commit Message:
XEEN: Implement shoot action

Changed paths:
    engines/xeen/combat.cpp
    engines/xeen/combat.h
    engines/xeen/interface.cpp
    engines/xeen/party.cpp
    engines/xeen/party.h



diff --git a/engines/xeen/combat.cpp b/engines/xeen/combat.cpp
index 763daa7..74e098c 100644
--- a/engines/xeen/combat.cpp
+++ b/engines/xeen/combat.cpp
@@ -2083,4 +2083,13 @@ done:
 	party.giveTreasure();
 }
 
+/**
+ * Fires off a ranged attack at all oncoming monsters
+ */
+void Combat::shootRangedWeapon() {
+	_rangeType = RT_ALL;
+	_damageType = DT_PHYSICAL;
+	multiAttack(11);
+}
+
 } // End of namespace Xeen
diff --git a/engines/xeen/combat.h b/engines/xeen/combat.h
index 9831f90..cff9261 100644
--- a/engines/xeen/combat.h
+++ b/engines/xeen/combat.h
@@ -172,6 +172,8 @@ public:
 	int stopAttack(const Common::Point &diffPt);
 
 	void multiAttack(int powNum);
+
+	void shootRangedWeapon();
 };
 
 } // End of namespace Xeen
diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp
index 7339e10..cc027b8 100644
--- a/engines/xeen/interface.cpp
+++ b/engines/xeen/interface.cpp
@@ -268,6 +268,7 @@ void Interface::perform() {
 	Map &map = *_vm->_map;
 	Party &party = *_vm->_party;
 	Scripts &scripts = *_vm->_scripts;
+	SoundManager &sound = *_vm->_sound;
 	Spells &spells = *_vm->_spells;
 	const Common::Rect WAIT_BOUNDS(8, 8, 224, 140);
 
@@ -571,6 +572,30 @@ void Interface::perform() {
 		rest();
 		break;
 
+	case Common::KEYCODE_s:
+		// Shoot
+		if (!party.canShoot()) {
+			sound.playFX(21);
+		} else {
+			if (_tillMove) {
+				combat.moveMonsters();
+				draw3d(true);
+			}
+
+			if (combat._attackMonsters[0] != -1 || combat._attackMonsters[1] != -1
+					|| combat._attackMonsters[2] != -1) {
+				if ((_vm->_mode == MODE_1 || _vm->_mode == MODE_SLEEPING)
+						&& !combat._monstersAttacking && !_charsShooting) {
+					doCombat();
+				}
+			}
+
+			combat.shootRangedWeapon();
+			chargeStep();
+			doStepCode();
+		}
+		break;
+
 	case Common::KEYCODE_v:
 		// Show the quests dialog
 		Quests::show(_vm);
diff --git a/engines/xeen/party.cpp b/engines/xeen/party.cpp
index 268dfcc..5e111e6 100644
--- a/engines/xeen/party.cpp
+++ b/engines/xeen/party.cpp
@@ -735,4 +735,13 @@ void Party::giveTreasureToCharacter(Character &c, ItemCategory category, int ite
 	events.ipause(5);
 }
 
+bool Party::canShoot() const {
+	for (uint idx = 0; idx < _activeParty.size(); ++idx) {
+		if (_activeParty[idx].hasMissileWeapon())
+			return true;
+	}
+
+	return false;
+}
+
 } // End of namespace Xeen
diff --git a/engines/xeen/party.h b/engines/xeen/party.h
index b5e31f9..483c3f4 100644
--- a/engines/xeen/party.h
+++ b/engines/xeen/party.h
@@ -173,6 +173,8 @@ public:
 	void giveTreasure();
 
 	bool arePacksFull() const;
+
+	bool canShoot() const;
 };
 
 } // End of namespace Xeen


Commit: 99aa64bda4695ca704a2902d3c6b6bd705204043
    https://github.com/scummvm/scummvm/commit/99aa64bda4695ca704a2902d3c6b6bd705204043
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-02-28T14:59:43-05:00

Commit Message:
XEEN: Fix crash on shooting

Changed paths:
    engines/xeen/interface_map.cpp



diff --git a/engines/xeen/interface_map.cpp b/engines/xeen/interface_map.cpp
index de19a99..a9e71d4 100644
--- a/engines/xeen/interface_map.cpp
+++ b/engines/xeen/interface_map.cpp
@@ -572,18 +572,15 @@ void InterfaceMap::drawMap() {
 				}
 			}
 		} else if (_charsShooting) {
-			for (int idx = 0; idx < 96; ++idx) {
-				if (_indoorList[162 + idx]._sprites != nullptr) {
-					_indoorList[162 + idx]._frame = 0;
-				}
-				else if (_indoorList[135 + idx]._sprites != nullptr) {
-					_indoorList[135 + idx]._frame = 1;
-				}
-				else if (_indoorList[111 + idx]._sprites != nullptr) {
-					_indoorList[111 + idx]._frame = 2;
-				}
-				else if (_indoorList[79 + idx]._sprites != nullptr) {
-					_indoorList[79 + idx]._frame = 0;
+			for (int idx = 0; idx < 8; ++idx) {
+				if (_indoorList._attackImgs1[idx]._sprites != nullptr) {
+					_indoorList._attackImgs1[idx]._frame = 0;
+				} else if (_indoorList._attackImgs2[idx]._sprites != nullptr) {
+					_indoorList._attackImgs2[idx]._frame = 1;
+				} else if (_indoorList._attackImgs3[idx]._sprites != nullptr) {
+					_indoorList._attackImgs3[idx]._frame = 2;
+				} else if (_indoorList._attackImgs4[idx]._sprites != nullptr) {
+					_indoorList._attackImgs4[idx]._frame = 0;
 				}
 			}
 		}


Commit: 93cc299eafab9e385af9b812f45809cc4645a14e
    https://github.com/scummvm/scummvm/commit/93cc299eafab9e385af9b812f45809cc4645a14e
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-02-28T18:43:04-05:00

Commit Message:
XEEN: Implement addHitPoints and spellFX methods

Changed paths:
    engines/xeen/character.cpp
    engines/xeen/character.h
    engines/xeen/combat.cpp
    engines/xeen/combat.h
    engines/xeen/dialogs_spells.cpp
    engines/xeen/dialogs_spells.h
    engines/xeen/interface.cpp
    engines/xeen/interface.h
    engines/xeen/resources.cpp
    engines/xeen/resources.h
    engines/xeen/scripts.cpp
    engines/xeen/scripts.h
    engines/xeen/spells.cpp
    engines/xeen/spells.h



diff --git a/engines/xeen/character.cpp b/engines/xeen/character.cpp
index d95e061..ea0f9f5 100644
--- a/engines/xeen/character.cpp
+++ b/engines/xeen/character.cpp
@@ -876,6 +876,15 @@ bool Character::isDisabledOrDead() const {
 }
 
 /**
+ * Returns whether the given character has a dead condition
+ */
+bool Character::isDead() const {
+	Condition condition = worstCondition();
+
+	return condition >= DEAD && condition <= ERADICATED;
+}
+
+/**
  * Get the character's age
  */
 int Character::getAge(bool ignoreTemp) const {
@@ -1810,6 +1819,32 @@ int Character::makeItem(int p1, int itemIndex, int p3) {
 	return category;
 }
 
+/**
+ * Add hit points to a character
+ */
+void Character::addHitPoints(int amount) {
+	Interface &intf = *Party::_vm->_interface;
+	Common::fill(&intf._charFX[0], &intf._charFX[MAX_ACTIVE_PARTY], 0);
+	
+	if (!isDead()) {
+		int maxHp = getMaxHP();
+		if (_currentHp <= maxHp) {
+			_currentHp = MIN(_currentHp + amount, maxHp);
+			intf.spellFX(this);
+		}
+
+		if (_currentHp > 0)
+			_conditions[UNCONSCIOUS] = 0;
+
+		intf.drawParty(true);
+	}
+
+	Common::fill(&intf._charFX[0], &intf._charFX[MAX_ACTIVE_PARTY], 0);
+}
+
+/**
+ * Remove hit points fromo the character
+ */
 void Character::subtractHitPoints(int amount) {
 	SoundManager &sound = *Party::_vm->_sound;
 	_currentHp -= amount;
diff --git a/engines/xeen/character.h b/engines/xeen/character.h
index 77ab882..f1243f1 100644
--- a/engines/xeen/character.h
+++ b/engines/xeen/character.h
@@ -278,6 +278,8 @@ public:
 
 	bool isDisabledOrDead() const;
 
+	bool isDead() const;
+
 	int getAge(bool ignoreTemp = false) const;
 
 	int getMaxHP() const;
@@ -322,6 +324,8 @@ public:
 
 	int makeItem(int p1, int itemIndex, int p3);
 
+	void addHitPoints(int amount);
+
 	void subtractHitPoints(int amount);
 
 	bool hasSpecialItem() const;
diff --git a/engines/xeen/combat.cpp b/engines/xeen/combat.cpp
index 74e098c..7cc2ab6 100644
--- a/engines/xeen/combat.cpp
+++ b/engines/xeen/combat.cpp
@@ -109,7 +109,7 @@ Combat::Combat(XeenEngine *vm): _vm(vm), _missVoc("miss.voc"), _pow1Voc("pow1.vo
 	_whosTurn = -1;
 	_itemFlag = false;
 	_monstersAttacking = false;
-	_combatMode = 0;
+	_combatMode = COMBATMODE_0;
 	_monsterIndex = 0;
 	_partyRan = false;
 	_monster2Attack = -1;
@@ -1883,7 +1883,6 @@ void Combat::multiAttack(int powNum) {
 	}
 
 	for (uint idx = 0; idx < party._activeParty.size(); ++idx) {
-		Character &c = party._activeParty[idx];
 		if (_shooting[idx]) {
 			if (map._isOutdoors) {
 				intf._outdoorList._attackImgs1[idx]._scale = 0;
diff --git a/engines/xeen/combat.h b/engines/xeen/combat.h
index cff9261..33309b2 100644
--- a/engines/xeen/combat.h
+++ b/engines/xeen/combat.h
@@ -64,6 +64,10 @@ enum ShootType {
 	ST_0 = 0, ST_1 = 1
 };
 
+enum CombatMode {
+	COMBATMODE_0 = 0, COMBATMODE_1 = 1, COMBATMODE_2 = 2
+};
+
 class XeenEngine;
 class Character;
 class XeenItem;
@@ -108,7 +112,7 @@ public:
 	bool _rangeAttacking[MAX_NUM_MONSTERS];
 	int _gmonHit[36];
 	bool _monstersAttacking;
-	int _combatMode;
+	CombatMode _combatMode;
 	int _monsterIndex;
 	bool _partyRan;
 	int _whosSpeed;
diff --git a/engines/xeen/dialogs_spells.cpp b/engines/xeen/dialogs_spells.cpp
index 9a19ac2..08828a0 100644
--- a/engines/xeen/dialogs_spells.cpp
+++ b/engines/xeen/dialogs_spells.cpp
@@ -577,4 +577,71 @@ void CastSpell::loadButtons() {
 	addPartyButtons(_vm);
 }
 
+/*------------------------------------------------------------------------*/
+
+int SpellOnWho::show(XeenEngine *vm, int spellId) {
+	SpellOnWho *dlg = new SpellOnWho(vm);
+	int result = dlg->execute(spellId);
+	delete dlg;
+
+	return result;
+}
+
+int SpellOnWho::execute(int spellId) {
+	Combat &combat = *_vm->_combat;
+	EventsManager &events = *_vm->_events;
+	Interface &intf = *_vm->_interface;
+	Party &party = *_vm->_party;
+	Screen &screen = *_vm->_screen;
+	Spells &spells = *_vm->_spells;
+	Window &w = screen._windows[16];
+	Mode oldMode = _vm->_mode;
+	_vm->_mode = MODE_3;
+	int result = 999;
+
+	w.open();
+	w.writeString(ON_WHO);
+	w.update();
+	addPartyButtons(_vm);
+
+	while (result == 999) {
+		do {
+			events.updateGameCounter();
+			intf.draw3d(true);
+
+			do {
+				events.pollEventsAndWait();
+				if (_vm->shouldQuit())
+					return -1;
+
+				checkEvents(_vm);
+			} while (!_buttonValue && events.timeElapsed() < 1);
+		} while (!_buttonValue);
+
+		switch (_buttonValue) {
+		case Common::KEYCODE_ESCAPE:
+			result = -1;
+			spells.addSpellCost(*combat._oldCharacter, spellId);
+			break;
+
+		case Common::KEYCODE_F1:
+		case Common::KEYCODE_F2:
+		case Common::KEYCODE_F3:
+		case Common::KEYCODE_F4:
+		case Common::KEYCODE_F5:
+		case Common::KEYCODE_F6:
+			_buttonValue -= Common::KEYCODE_F1;
+			if (_buttonValue < (int)(combat._combatMode == 2 ? combat._combatParty.size() :
+					party._activeParty.size())) {
+				result = _buttonValue;
+			}
+			break;
+		}
+	}
+
+	w.close();
+	_vm->_mode = oldMode;
+	return result;
+}
+
 } // End of namespace Xeen
diff --git a/engines/xeen/dialogs_spells.h b/engines/xeen/dialogs_spells.h
index 6a9e43f..660f2ef 100644
--- a/engines/xeen/dialogs_spells.h
+++ b/engines/xeen/dialogs_spells.h
@@ -73,6 +73,17 @@ public:
 	static int show(XeenEngine *vm, Character *&c);
 };
 
+class SpellOnWho : public ButtonContainer {
+private:
+	XeenEngine *_vm;
+
+	SpellOnWho(XeenEngine *vm) : ButtonContainer(), _vm(vm) {}
+
+	int execute(int spellId);
+public:
+	static int show(XeenEngine *vm, int spellId);
+};
+
 } // End of namespace Xeen
 
 #endif /* XEEN_DIALOGS_SPELLS_H */
diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp
index cc027b8..923eaea 100644
--- a/engines/xeen/interface.cpp
+++ b/engines/xeen/interface.cpp
@@ -149,6 +149,7 @@ Interface::Interface(XeenEngine *vm) : ButtonContainer(), InterfaceMap(vm),
 	_face1State = _face2State = 0;
 	_upDoorText = false;
 	_tillMove = 0;
+	Common::fill(&_charFX[0], &_charFX[MAX_ACTIVE_PARTY], 0);
 
 	initDrawStructs();
 }
@@ -1891,7 +1892,7 @@ void Interface::doCombat() {
 	bool reloadMap = false;
 	
 	_upDoorText = false;
-	combat._combatMode = 2;
+	combat._combatMode = COMBATMODE_2;
 	_vm->_mode = MODE_COMBAT;
 
 	_iconSprites.load("combat.icn");
@@ -2182,7 +2183,7 @@ void Interface::doCombat() {
 			DIR_EAST : DIR_SOUTH;
 	}
 
-	combat._combatMode = 1;
+	combat._combatMode = COMBATMODE_1;
 }
 
 /**
@@ -2262,4 +2263,53 @@ void Interface::nextChar() {
 	}
 }
 
+void Interface::spellFX(Character *c) {
+	Combat &combat = *_vm->_combat;
+	EventsManager &events = *_vm->_events;
+	Party &party = *_vm->_party;
+	Screen &screen = *_vm->_screen;
+	SoundManager &sound = *_vm->_sound;
+
+	// Ensure there's no alraedy running effect for the given character
+	uint charIndex;
+	for (charIndex = 0; charIndex < party._activeParty.size(); ++charIndex) {
+		if (&party._activeParty[charIndex] == c)
+			break;
+	}
+	if (charIndex == party._activeParty.size() || _charFX[charIndex])
+		return;
+
+	if (screen._windows[12]._enabled)
+		screen._windows[12].close();
+
+	if (combat._combatMode == COMBATMODE_2) {
+		for (uint idx = 0; idx < combat._combatParty.size(); ++idx) {
+			if (combat._combatParty[idx]->_rosterId == c->_rosterId) {
+				charIndex = idx;
+				break;
+			}
+		}
+	}
+
+	int tillMove = _tillMove;
+	_tillMove = 0;
+	sound.playFX(20);
+
+	for (int frameNum = 0; frameNum < 4; ++frameNum) {
+		events.updateGameCounter();
+		_spellFxSprites.draw(screen, frameNum, Common::Point(
+			CHAR_FACES_X[charIndex], 150));
+
+		if (!screen._windows[11]._enabled)
+			draw3d(false);
+
+		screen._windows[0].update();
+		events.wait(screen._windows[11]._enabled ? 2 : 1);
+	}
+
+	drawParty(true);
+	_tillMove = tillMove;
+}
+
+
 } // End of namespace Xeen
diff --git a/engines/xeen/interface.h b/engines/xeen/interface.h
index f5e5cc3..24edf9d 100644
--- a/engines/xeen/interface.h
+++ b/engines/xeen/interface.h
@@ -119,6 +119,7 @@ public:
 	bool _upDoorText;
 	Common::String _screenText;
 	byte _tillMove;
+	int _charFX[6];
 public:
 	Interface(XeenEngine *vm);
 
@@ -145,6 +146,8 @@ public:
 	void assembleBorder();
 
 	void doCombat();
+
+	void spellFX(Character *c);
 };
 
 } // End of namespace Xeen
diff --git a/engines/xeen/resources.cpp b/engines/xeen/resources.cpp
index 5c76d29..5893403 100644
--- a/engines/xeen/resources.cpp
+++ b/engines/xeen/resources.cpp
@@ -1528,4 +1528,6 @@ const char *const GIVE_TREASURE_FORMATTING =
 
 const char *const X_FOUND_Y = "\v060\t000\x03c%s found: %s";
 
+const char *const ON_WHO = "\x3""c\v009On Who?";
+
 } // End of namespace Xeen
diff --git a/engines/xeen/resources.h b/engines/xeen/resources.h
index c98db7f..b908d91 100644
--- a/engines/xeen/resources.h
+++ b/engines/xeen/resources.h
@@ -539,6 +539,8 @@ extern const char *const GIVE_TREASURE_FORMATTING;
 
 extern const char *const X_FOUND_Y;
 
+extern const char *const ON_WHO;
+
 } // End of namespace Xeen
 
 #endif	/* XEEN_RESOURCES_H */
diff --git a/engines/xeen/scripts.cpp b/engines/xeen/scripts.cpp
index 4af7af1..ec00327 100644
--- a/engines/xeen/scripts.cpp
+++ b/engines/xeen/scripts.cpp
@@ -88,7 +88,6 @@ bool MirrorEntry::synchronize(Common::SeekableReadStream &s) {
 /*------------------------------------------------------------------------*/
 
 Scripts::Scripts(XeenEngine *vm) : _vm(vm) {
-	Common::fill(&_charFX[0], &_charFX[MAX_ACTIVE_PARTY], 0);
 	_whoWill = 0;
 	_itemType = 0;
 	_treasureItems = 0;
@@ -120,7 +119,7 @@ int Scripts::checkEvents() {
 	_var50 = false;
 	_whoWill = 0;
 	Mode oldMode = _vm->_mode;
-	Common::fill(&_charFX[0], &_charFX[MAX_ACTIVE_PARTY], 0);
+	Common::fill(&intf._charFX[0], &intf._charFX[MAX_ACTIVE_PARTY], 0);
 	//int items = _treasureItems;
 	
 	if (party._treasure._gold & party._treasure._gems) {
@@ -202,7 +201,7 @@ int Scripts::checkEvents() {
 	}
 
 	_v2 = 1;
-	Common::fill(&_charFX[0], &_charFX[6], 0);
+	Common::fill(&intf._charFX[0], &intf._charFX[6], 0);
 
 	return _scriptResult;
 }
diff --git a/engines/xeen/scripts.h b/engines/xeen/scripts.h
index 3a835d8..29de5b8 100644
--- a/engines/xeen/scripts.h
+++ b/engines/xeen/scripts.h
@@ -139,7 +139,6 @@ struct MirrorEntry {
 class Scripts {
 private:
 	XeenEngine *_vm;
-	int _charFX[6];
 	int _treasureItems;
 	int _lineNum;
 	int _charIndex;
diff --git a/engines/xeen/spells.cpp b/engines/xeen/spells.cpp
index 53c43b5..d446b3c 100644
--- a/engines/xeen/spells.cpp
+++ b/engines/xeen/spells.cpp
@@ -21,6 +21,7 @@
  */
 
 #include "xeen/spells.h"
+#include "xeen/dialogs_spells.h"
 #include "xeen/files.h"
 #include "xeen/resources.h"
 #include "xeen/xeen.h"
@@ -95,6 +96,16 @@ void Spells::executeSpell(int spellId) {
 	(this->*SPELL_LIST[spellId])();
 }
 
+/**
+ * Spell being cast failed
+ */
+void Spells::spellFailed() {
+	ErrorScroll::show(_vm, SPELL_FAILED, WT_NONFREEZED_WAIT);
+}
+
+/**
+ * Cast a spell associated with an item
+ */
 void Spells::castItemSpell(int spellId) {
 	if (_vm->_mode == MODE_COMBAT) {
 		if (spellId == 15 || spellId == 20 || spellId == 27 || spellId == 41
@@ -233,7 +244,26 @@ void Spells::magicArrow() {
 	combat.multiAttack(11);
 }
 
-void Spells::firstAid() { error("TODO: spell"); }
+void Spells::firstAid() {
+	Combat &combat = *_vm->_combat;
+	Party &party = *_vm->_party;
+	SoundManager &sound = *_vm->_sound;
+
+	int charIndex = SpellOnWho::show(_vm, MS_FirstAid);
+	if (charIndex == -1)
+		return;
+
+	Character &c = combat._combatMode == 2 ? *combat._combatParty[charIndex] :
+		party._activeParty[charIndex];
+
+	if (c.isDead()) {
+		spellFailed();
+	} else {
+		sound.playFX(30);
+		c.addHitPoints(6);
+	}
+}
+
 void Spells::flyingFist() { error("TODO: spell"); }
 void Spells::energyBlast() { error("TODO: spell"); }
 void Spells::sleep() { error("TODO: spell"); }
diff --git a/engines/xeen/spells.h b/engines/xeen/spells.h
index af52511..2f79670 100644
--- a/engines/xeen/spells.h
+++ b/engines/xeen/spells.h
@@ -69,6 +69,8 @@ private:
 
 	void executeSpell(int spellId);
 
+	void spellFailed();
+
 	// Spell list
 	void light();
 	void awaken();


Commit: 810619072a7760339379ca3802d956c976fc22dd
    https://github.com/scummvm/scummvm/commit/810619072a7760339379ca3802d956c976fc22dd
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-02-28T18:50:18-05:00

Commit Message:
XEEN: gcc compilation fixes

Changed paths:
    engines/xeen/character.cpp
    engines/xeen/dialogs_items.cpp
    engines/xeen/dialogs_spells.cpp
    engines/xeen/module.mk
    engines/xeen/spells.cpp



diff --git a/engines/xeen/character.cpp b/engines/xeen/character.cpp
index ea0f9f5..ca224ab 100644
--- a/engines/xeen/character.cpp
+++ b/engines/xeen/character.cpp
@@ -300,7 +300,7 @@ Common::String WeaponItems::getFullDescription(int itemIndex, int displayNum) {
 	Resources &res = *vm()->_resources;
 
 	return Common::String::format("\f%02u%s%s%s\f%02u%s%s%s", displayNum,
-		!i._bonusFlags ? res._maeNames[i._material] : "",
+		!i._bonusFlags ? res._maeNames[i._material].c_str() : "",
 		(i._bonusFlags & ITEMFLAG_BROKEN) ? ITEM_BROKEN : "",
 		(i._bonusFlags & ITEMFLAG_CURSED) ? ITEM_CURSED : "",
 		WEAPON_NAMES[i._id],
@@ -466,7 +466,7 @@ Common::String ArmorItems::getFullDescription(int itemIndex, int displayNum) {
 	Resources &res = *vm()->_resources;
 
 	return Common::String::format("\f%02u%s%s%s\f%02u%s%s", displayNum,
-		!i._bonusFlags ? "" : res._maeNames[i._material],
+		!i._bonusFlags ? "" : res._maeNames[i._material].c_str(),
 		(i._bonusFlags & ITEMFLAG_BROKEN) ? ITEM_BROKEN : "",
 		(i._bonusFlags & ITEMFLAG_CURSED) ? ITEM_CURSED : "",
 		ARMOR_NAMES[i._id],
@@ -589,7 +589,7 @@ Common::String AccessoryItems::getFullDescription(int itemIndex, int displayNum)
 	Resources &res = *vm()->_resources;
 
 	return Common::String::format("\f%02u%s%s%s\f%02u%s%s", displayNum,
-		!i._bonusFlags ? "" : res._maeNames[i._material],
+		!i._bonusFlags ? "" : res._maeNames[i._material].c_str(),
 		(i._bonusFlags & ITEMFLAG_BROKEN) ? ITEM_BROKEN : "",
 		(i._bonusFlags & ITEMFLAG_CURSED) ? ITEM_CURSED : "",
 		ARMOR_NAMES[i._id],
@@ -638,7 +638,7 @@ Common::String MiscItems::getFullDescription(int itemIndex, int displayNum) {
 	Resources &res = *vm()->_resources;
 
 	return Common::String::format("\f%02u%s%s%s\f%02u%s%s", displayNum,
-		!i._bonusFlags ? "" : res._maeNames[i._material],
+		!i._bonusFlags ? "" : res._maeNames[i._material].c_str(),
 		(i._bonusFlags & ITEMFLAG_BROKEN) ? ITEM_BROKEN : "",
 		(i._bonusFlags & ITEMFLAG_CURSED) ? ITEM_CURSED : "",
 		ARMOR_NAMES[i._id],
diff --git a/engines/xeen/dialogs_items.cpp b/engines/xeen/dialogs_items.cpp
index 21a8856..bdcdffa 100644
--- a/engines/xeen/dialogs_items.cpp
+++ b/engines/xeen/dialogs_items.cpp
@@ -149,11 +149,11 @@ Character *ItemsDialog::execute(Character *c, ItemsMode mode) {
 								|| mode == ITEMMODE_ENCHANT || mode == ITEMMODE_RECHARGE) {
 							lines.push_back(Common::String::format(ITEMS_DIALOG_LINE1, 
 								arr[idx], idx + 1,
-								c->_items[category].getFullDescription(idx, arr[idx])));
+								c->_items[category].getFullDescription(idx, arr[idx]).c_str()));
 						} else {
 							lines.push_back(Common::String::format(ITEMS_DIALOG_LINE2,
 								arr[idx], idx + 1,
-								c->_items[category].getFullDescription(idx, arr[idx]),
+								c->_items[category].getFullDescription(idx, arr[idx]).c_str(),
 								calcItemCost(c, idx, mode,
 									mode == ITEMMODE_TO_GOLD ? 1 : startingChar->_skills[MERCHANT],
 									category)
@@ -194,7 +194,7 @@ Character *ItemsDialog::execute(Character *c, ItemsMode mode) {
 
 						lines.push_back(Common::String::format(ITEMS_DIALOG_LINE2,
 							arr[idx], idx + 1,
-							c->_items[category].getFullDescription(idx, arr[idx]),
+							c->_items[category].getFullDescription(idx, arr[idx]).c_str(),
 							calcItemCost(c, idx, tempMode, skill, category)
 						));
 					}
@@ -1002,7 +1002,7 @@ int ItemsDialog::doItemOptions(Character &c, int actionIndex, int itemIndex, Ite
 				int cost = calcItemCost(&c, itemIndex, mode, actionIndex, category);
 				Common::String msg = Common::String::format(FIX_IDENTIFY_GOLD,
 					FIX_IDENTIFY[0],
-					c._items[category].getFullDescription(itemIndex),
+					c._items[category].getFullDescription(itemIndex).c_str(),
 					cost);
 
 				if (Confirm::show(_vm, msg) && party.subtract(0, cost, 0)) {
@@ -1015,7 +1015,7 @@ int ItemsDialog::doItemOptions(Character &c, int actionIndex, int itemIndex, Ite
 			int cost = calcItemCost(&c, itemIndex, mode, actionIndex, category);
 			Common::String msg = Common::String::format(FIX_IDENTIFY_GOLD,
 				FIX_IDENTIFY[1],
-				c._items[category].getFullDescription(itemIndex),
+				c._items[category].getFullDescription(itemIndex).c_str(),
 				cost);
 
 			if (Confirm::show(_vm, msg) && party.subtract(0, cost, 0)) {
diff --git a/engines/xeen/dialogs_spells.cpp b/engines/xeen/dialogs_spells.cpp
index 08828a0..70668e2 100644
--- a/engines/xeen/dialogs_spells.cpp
+++ b/engines/xeen/dialogs_spells.cpp
@@ -67,7 +67,7 @@ Character *SpellsDialog::execute(ButtonContainer *priorDialog, Character *c, int
 
 			Common::String title = Common::String::format(BUY_SPELLS, c->_name.c_str());
 			Common::String msg = Common::String::format(GUILD_OPTIONS,
-				title.c_str(), XeenEngine::printMil(party._gold));
+				title.c_str(), XeenEngine::printMil(party._gold).c_str());
 			screen._windows[10].writeString(msg);
 
 			warning("TODO: Sprite draw using previously used button sprites");
@@ -353,7 +353,7 @@ const char *SpellsDialog::setSpellText(Character *c, int isCasting) {
 						if (!c->_spells[idx] || (isCasting & 0x80)) {
 							int cost = spells.calcSpellCost(SPELLS_ALLOWED[category][idx], expenseFactor);
 							_spells.push_back(SpellEntry(Common::String::format("\x3l%s\x3r\x9""000%u",
-								spells._spellNames[SPELLS_ALLOWED[category][idx]], cost), 
+								spells._spellNames[SPELLS_ALLOWED[category][idx]].c_str(), cost), 
 								idx, spellId));
 						}
 					}
@@ -370,7 +370,7 @@ const char *SpellsDialog::setSpellText(Character *c, int isCasting) {
 						if (!c->_spells[idx] || (isCasting & 0x80)) {
 							int cost = spells.calcSpellCost(SPELLS_ALLOWED[category][idx], expenseFactor);
 							_spells.push_back(SpellEntry(Common::String::format("\x3l%s\x3r\x9""000%u",
-								spells._spellNames[SPELLS_ALLOWED[category][idx]], cost), 
+								spells._spellNames[SPELLS_ALLOWED[category][idx]].c_str(), cost), 
 								idx, spellId));
 						}
 					}
@@ -385,7 +385,7 @@ const char *SpellsDialog::setSpellText(Character *c, int isCasting) {
 						if (!c->_spells[idx] || (isCasting & 0x80)) {
 							int cost = spells.calcSpellCost(SPELLS_ALLOWED[category][idx], expenseFactor);
 							_spells.push_back(SpellEntry(Common::String::format("\x3l%s\x3r\x9""000%u",
-								spells._spellNames[SPELLS_ALLOWED[category][idx]], cost), 
+								spells._spellNames[SPELLS_ALLOWED[category][idx]].c_str(), cost), 
 								idx, spellId));
 						}
 					}
diff --git a/engines/xeen/module.mk b/engines/xeen/module.mk
index 1fe29c6..4e64b8e 100644
--- a/engines/xeen/module.mk
+++ b/engines/xeen/module.mk
@@ -1,9 +1,9 @@
 MODULE := engines/xeen
 
 MODULE_OBJS := \
-	clouds\clouds_game.o \
-	darkside\darkside_game.o \
-	worldofxeen\worldofxeen_game.o \
+	clouds/clouds_game.o \
+	darkside/darkside_game.o \
+	worldofxeen/worldofxeen_game.o \
 	character.o \
 	combat.o \
 	debugger.o \
diff --git a/engines/xeen/spells.cpp b/engines/xeen/spells.cpp
index d446b3c..8166a1b 100644
--- a/engines/xeen/spells.cpp
+++ b/engines/xeen/spells.cpp
@@ -151,7 +151,7 @@ int Spells::castSpell(Character *c, int spellId) {
 				// Return the spell costs and flag that another spell can be selected
 				addSpellCost(*c, spellId);
 				ErrorDialog::show(_vm, Common::String::format(CANT_CAST_WHILE_ENGAGED,
-					_spellNames[spellId]));
+					_spellNames[spellId].c_str()));
 				result = -1;
 			}
 			break;


Commit: b414ff26f2319e4d88c60f1b0fb58880926da5f0
    https://github.com/scummvm/scummvm/commit/b414ff26f2319e4d88c60f1b0fb58880926da5f0
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-02-28T19:22:42-05:00

Commit Message:
XEEN: Implement some of the spells

Changed paths:
    engines/xeen/spells.cpp
    engines/xeen/spells.h



diff --git a/engines/xeen/spells.cpp b/engines/xeen/spells.cpp
index 8166a1b..1e883e7 100644
--- a/engines/xeen/spells.cpp
+++ b/engines/xeen/spells.cpp
@@ -75,7 +75,7 @@ void Spells::executeSpell(int spellId) {
 		&Spells::curePoison, &Spells::acidSpray, &Spells::timeDistortion,
 		&Spells::dragonSleep,
 
-		&Spells::cureDisease, &Spells::teleport, &Spells::fingerOfDeath,
+		&Spells::suppressPoison, &Spells::teleport, &Spells::fingerOfDeath,
 		&Spells::cureParalysis, &Spells::golemStopper, &Spells::poisonVolley,
 		&Spells::deadlySwarm, &Spells::superShelter, &Spells::dayOfProtection,
 		&Spells::dayOfSorcery,
@@ -264,18 +264,144 @@ void Spells::firstAid() {
 	}
 }
 
-void Spells::flyingFist() { error("TODO: spell"); }
-void Spells::energyBlast() { error("TODO: spell"); }
-void Spells::sleep() { error("TODO: spell"); }
-void Spells::revitalize() { error("TODO: spell"); }
-void Spells::cureWounds() { error("TODO: spell"); }
-void Spells::sparks() { error("TODO: spell"); }
+void Spells::flyingFist() {
+	Combat &combat = *_vm->_combat;
+	SoundManager &sound = *_vm->_sound;
+
+	combat._monsterDamage = 6;
+	combat._damageType = DT_PHYSICAL;
+	combat._rangeType = RT_SINGLE;
+	sound.playFX(18);
+	combat.multiAttack(14);
+}
+
+void Spells::energyBlast() {
+	Combat &combat = *_vm->_combat;
+	SoundManager &sound = *_vm->_sound;
+
+	combat._monsterDamage = combat._oldCharacter->getCurrentLevel() * 2;
+	combat._damageType = DT_ENERGY;
+	combat._rangeType = RT_SINGLE;
+	sound.playFX(16);
+	combat.multiAttack(13);
+}
+
+void Spells::sleep() {
+	Combat &combat = *_vm->_combat;
+	SoundManager &sound = *_vm->_sound;
+
+	combat._monsterDamage = 0;
+	combat._damageType = DT_SLEEP;
+	combat._rangeType = RT_GROUP;
+	sound.playFX(18);
+	combat.multiAttack(7);
+}
+
+void Spells::revitalize() {
+	Combat &combat = *_vm->_combat;
+	Interface &intf = *_vm->_interface;
+	Party &party = *_vm->_party;
+	SoundManager &sound = *_vm->_sound;
+
+	int charIndex = SpellOnWho::show(_vm, MS_Revitalize);
+	if (charIndex == -1)
+		return;
+
+	Character &c = combat._combatMode == 2 ? *combat._combatParty[charIndex] :
+		party._activeParty[charIndex];
+
+	sound.playFX(30);
+	c.addHitPoints(0);
+	c._conditions[WEAK] = 0;
+	intf.drawParty(true);
+}
+
+void Spells::cureWounds() {
+	Combat &combat = *_vm->_combat;
+	Party &party = *_vm->_party;
+	SoundManager &sound = *_vm->_sound;
+
+	int charIndex = SpellOnWho::show(_vm, MS_Revitalize);
+	if (charIndex == -1)
+		return;
+
+	Character &c = combat._combatMode == 2 ? *combat._combatParty[charIndex] :
+		party._activeParty[charIndex];
+
+	if (c.isDead()) {
+		spellFailed();
+	} else {
+		sound.playFX(30);
+		c.addHitPoints(15);
+	}
+}
+
+void Spells::sparks() {
+	Combat &combat = *_vm->_combat;
+	SoundManager &sound = *_vm->_sound;
+
+	combat._monsterDamage = combat._oldCharacter->getCurrentLevel() * 2;
+	combat._damageType = DT_ELECTRICAL;
+	combat._rangeType = RT_GROUP;
+	sound.playFX(14);
+	combat.multiAttack(5);
+}
 
 void Spells::shrapMetal() { error("TODO: spell"); }
 void Spells::insectSpray() { error("TODO: spell"); }
-void Spells::toxicCloud() { error("TODO: spell"); }
-void Spells::protectionFromElements() { error("TODO: spell"); }
-void Spells::pain() { error("TODO: spell"); }
+
+void Spells::toxicCloud() {
+	Combat &combat = *_vm->_combat;
+	SoundManager &sound = *_vm->_sound;
+
+	combat._monsterDamage = 10;
+	combat._damageType = DT_POISON;
+	combat._rangeType = RT_GROUP;
+	sound.playFX(17);
+	combat.multiAttack(10);
+}
+
+void Spells::suppressPoison() {
+	Combat &combat = *_vm->_combat;
+	Interface &intf = *_vm->_interface;
+	Party &party = *_vm->_party;
+	SoundManager &sound = *_vm->_sound;
+
+	int charIndex = SpellOnWho::show(_vm, MS_FirstAid);
+	if (charIndex == -1)
+		return;
+
+	Character &c = combat._combatMode == 2 ? *combat._combatParty[charIndex] :
+		party._activeParty[charIndex];
+
+	if (c._conditions[POISONED]) {
+		if (c._conditions[POISONED] >= 4) {
+			c._conditions[POISONED] -= 2;
+		} else {
+			c._conditions[POISONED] = 1;
+		}
+	}
+
+	sound.playFX(20);
+	c.addHitPoints(0);
+	intf.drawParty(1);
+}
+
+void Spells::protectionFromElements() {
+	error("TODO: spell");
+}
+
+void Spells::pain() {
+	Combat &combat = *_vm->_combat;
+	SoundManager &sound = *_vm->_sound;
+
+	combat._monsterDamage = 0;
+	combat._damageType = DT_PHYSICAL;
+	combat._rangeType = RT_GROUP;
+	sound.playFX(18);
+	combat.multiAttack(14);
+}
+
 void Spells::jump() { error("TODO: spell"); }			// Not while engaged
 void Spells::beastMaster() { error("TODO: spell"); }
 void Spells::clairvoyance() { error("TODO: spell"); }
@@ -304,7 +430,6 @@ void Spells::acidSpray() { error("TODO: spell"); }
 void Spells::timeDistortion() { error("TODO: spell"); }
 void Spells::dragonSleep() { error("TODO: spell"); }
 
-void Spells::cureDisease() { error("TODO: spell"); }
 void Spells::teleport() { error("TODO: spell"); }		// Not while engaged
 void Spells:: fingerOfDeath() { error("TODO: spell"); }
 void Spells::cureParalysis() { error("TODO: spell"); }
diff --git a/engines/xeen/spells.h b/engines/xeen/spells.h
index 2f79670..f71f1fd 100644
--- a/engines/xeen/spells.h
+++ b/engines/xeen/spells.h
@@ -116,7 +116,7 @@ private:
 	void timeDistortion();
 	void dragonSleep();
 
-	void cureDisease();
+	void suppressPoison();
 	void teleport();		// Not while engaged
 	void  fingerOfDeath();
 	void cureParalysis();


Commit: 9789962605a30e8a993370d3de3c1a30582f3964
    https://github.com/scummvm/scummvm/commit/9789962605a30e8a993370d3de3c1a30582f3964
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-02-28T20:43:07-05:00

Commit Message:
XEEN: Implemented protection from elements spell

Changed paths:
    engines/xeen/dialogs_spells.cpp
    engines/xeen/dialogs_spells.h
    engines/xeen/resources.cpp
    engines/xeen/resources.h
    engines/xeen/spells.cpp



diff --git a/engines/xeen/dialogs_spells.cpp b/engines/xeen/dialogs_spells.cpp
index 70668e2..3aa0cfa 100644
--- a/engines/xeen/dialogs_spells.cpp
+++ b/engines/xeen/dialogs_spells.cpp
@@ -644,4 +644,87 @@ int SpellOnWho::execute(int spellId) {
 	return result;
 }
 
+/*------------------------------------------------------------------------*/
+
+int SelectElement::show(XeenEngine *vm, int spellId) {
+	SelectElement *dlg = new SelectElement(vm);
+	int result = dlg->execute(spellId);
+	delete dlg;
+
+	return result;
+}
+
+int SelectElement::execute(int spellId) {
+	Combat &combat = *_vm->_combat;
+	EventsManager &events = *_vm->_events;
+	Interface &intf = *_vm->_interface;
+	Party &party = *_vm->_party;
+	Screen &screen = *_vm->_screen;
+	Spells &spells = *_vm->_spells;
+	Window &w = screen._windows[15];
+	Mode oldMode = _vm->_mode;
+	_vm->_mode = MODE_3;
+	int result = 999;
+
+	loadButtons();
+
+	w.open();
+	w.writeString(WHICH_ELEMENT1);
+	drawButtons(&screen);
+	w.update();
+
+	while (result == 999) {
+		do {
+			events.updateGameCounter();
+			intf.draw3d(true);
+			w.frame();
+			w.writeString(WHICH_ELEMENT2);
+			drawButtons(&screen);
+			w.update();
+
+			do {
+				events.pollEventsAndWait();
+				if (_vm->shouldQuit())
+					return -1;
+
+				checkEvents(_vm);
+			} while (!_buttonValue && events.timeElapsed() < 1);
+		} while (!_buttonValue);
+
+		switch (_buttonValue) {
+		case Common::KEYCODE_ESCAPE:
+			result = -1;
+			spells.addSpellCost(*combat._oldCharacter, spellId);
+			break;
+
+		case Common::KEYCODE_a:
+			result = DT_POISON;
+			break;
+		case Common::KEYCODE_c:
+			result = DT_COLD;
+			break;
+		case Common::KEYCODE_e:
+			result = DT_ELECTRICAL;
+			break;
+		case Common::KEYCODE_f:
+			result = DT_FIRE;
+			break;
+		default:
+			break;
+		}
+	}
+
+	w.close();
+	_vm->_mode = oldMode;
+	return result;
+}
+
+void SelectElement::loadButtons() {
+	_iconSprites.load("element.icn");
+	addButton(Common::Rect(60, 92, 84, 112), Common::KEYCODE_f, &_iconSprites);
+	addButton(Common::Rect(90, 92, 114, 112), Common::KEYCODE_e, &_iconSprites);
+	addButton(Common::Rect(120, 92, 144, 112), Common::KEYCODE_c, &_iconSprites);
+	addButton(Common::Rect(150, 92, 174, 112), Common::KEYCODE_a, &_iconSprites);
+}
+
 } // End of namespace Xeen
diff --git a/engines/xeen/dialogs_spells.h b/engines/xeen/dialogs_spells.h
index 660f2ef..6bbdb3c 100644
--- a/engines/xeen/dialogs_spells.h
+++ b/engines/xeen/dialogs_spells.h
@@ -84,6 +84,20 @@ public:
 	static int show(XeenEngine *vm, int spellId);
 };
 
+class SelectElement : public ButtonContainer {
+private:
+	XeenEngine *_vm;
+	SpriteResource _iconSprites;
+
+	SelectElement(XeenEngine *vm) : ButtonContainer(), _vm(vm) {}
+
+	int execute(int spellId);
+
+	void loadButtons();
+public:
+	static int show(XeenEngine *vm, int spellId);
+};
+
 } // End of namespace Xeen
 
 #endif /* XEEN_DIALOGS_SPELLS_H */
diff --git a/engines/xeen/resources.cpp b/engines/xeen/resources.cpp
index 5893403..3a751b7 100644
--- a/engines/xeen/resources.cpp
+++ b/engines/xeen/resources.cpp
@@ -1530,4 +1530,14 @@ const char *const X_FOUND_Y = "\v060\t000\x03c%s found: %s";
 
 const char *const ON_WHO = "\x3""c\v009On Who?";
 
+const char *const WHICH_ELEMENT = "";
+
+const char *const WHICH_ELEMENT1 =
+	"\r\x3""c\x1Which Element?\x2\v034\t014\f15F\fdire\t044"
+	"\f15E\fdlec\t074\f15C\fdold\t104\f15A\fdcid\x1";
+
+const char *const WHICH_ELEMENT2 =
+	"\r\x3""cWhich Element?', 2, 0Bh, '034\t014\f15F\fdire\t044"
+	"\f15E\fdlec\t074\f15C\fdold\t104\f15A\fdcid\x1";
+
 } // End of namespace Xeen
diff --git a/engines/xeen/resources.h b/engines/xeen/resources.h
index b908d91..fed2491 100644
--- a/engines/xeen/resources.h
+++ b/engines/xeen/resources.h
@@ -541,6 +541,9 @@ extern const char *const X_FOUND_Y;
 
 extern const char *const ON_WHO;
 
+extern const char *const WHICH_ELEMENT1;
+extern const char *const WHICH_ELEMENT2;
+
 } // End of namespace Xeen
 
 #endif	/* XEEN_RESOURCES_H */
diff --git a/engines/xeen/spells.cpp b/engines/xeen/spells.cpp
index 1e883e7..b2b477e 100644
--- a/engines/xeen/spells.cpp
+++ b/engines/xeen/spells.cpp
@@ -388,7 +388,35 @@ void Spells::suppressPoison() {
 }
 
 void Spells::protectionFromElements() {
-	error("TODO: spell");
+	Combat &combat = *_vm->_combat;
+	Interface &intf = *_vm->_interface;
+	Party &party = *_vm->_party;
+	SoundManager &sound = *_vm->_sound;
+	Character &c = *combat._oldCharacter;
+	int resist = MIN(c.getCurrentLevel() * 2 + 5, (uint)200);
+	
+	int elementType = SelectElement::show(_vm, MS_ProtFromElements);
+	if (elementType != -1) {
+		switch (elementType) {
+		case DT_FIRE:
+			party._fireResistence = resist;
+			break;
+		case DT_ELECTRICAL:
+			party._fireResistence = resist;
+			break;
+		case DT_COLD:
+			party._coldResistence = resist;
+			break;
+		case DT_POISON:
+			party._poisonResistence = resist;
+			break;
+		default:
+			break;
+		}
+
+		sound.playFX(20);
+		intf.drawParty(true);
+	}
 }
 
 void Spells::pain() {


Commit: 07f504fe160d051c458e1f0035d4784ac74e2530
    https://github.com/scummvm/scummvm/commit/07f504fe160d051c458e1f0035d4784ac74e2530
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-02-28T22:53:17-05:00

Commit Message:
XEEN: Fix ordering of spell list and methods

Changed paths:
    engines/xeen/combat.cpp
    engines/xeen/dialogs_spells.cpp
    engines/xeen/dialogs_spells.h
    engines/xeen/interface.cpp
    engines/xeen/resources.cpp
    engines/xeen/resources.h
    engines/xeen/spells.cpp
    engines/xeen/spells.h



diff --git a/engines/xeen/combat.cpp b/engines/xeen/combat.cpp
index 7cc2ab6..1d03a51 100644
--- a/engines/xeen/combat.cpp
+++ b/engines/xeen/combat.cpp
@@ -64,10 +64,6 @@ static const int MONSTER_GRID_BITINDEX2[48] = {
 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
 };
 
-static const int MONSTER_GRID_BITMASK[12] = {
-	0xC, 8, 4, 0, 0xF, 0xF000, 0xF00, 0xF0, 0xF00, 0xF0, 0x0F, 0xF000
-};
-
 static const int ATTACK_TYPE_FX[23] = {
 	49, 18, 13, 14, 15, 17, 16, 0, 6, 1, 2, 3,
 	4, 5, 4, 9, 27, 29, 44, 51, 53, 61, 71
@@ -1598,7 +1594,7 @@ void Combat::quickFight() {
 		break;
 	case QUICK_SPELL:
 		if (c->_currentSpell != -1) {
-			spells.castSpell(c, SPELLS_ALLOWED[c->getClassCategory()][c->_currentSpell]);
+			spells.castSpell(c, (MagicSpell)SPELLS_ALLOWED[c->getClassCategory()][c->_currentSpell]);
 		}
 		break;
 	case QUICK_BLOCK:
diff --git a/engines/xeen/dialogs_spells.cpp b/engines/xeen/dialogs_spells.cpp
index 3aa0cfa..dfc72aa 100644
--- a/engines/xeen/dialogs_spells.cpp
+++ b/engines/xeen/dialogs_spells.cpp
@@ -658,7 +658,6 @@ int SelectElement::execute(int spellId) {
 	Combat &combat = *_vm->_combat;
 	EventsManager &events = *_vm->_events;
 	Interface &intf = *_vm->_interface;
-	Party &party = *_vm->_party;
 	Screen &screen = *_vm->_screen;
 	Spells &spells = *_vm->_spells;
 	Window &w = screen._windows[15];
@@ -727,4 +726,34 @@ void SelectElement::loadButtons() {
 	addButton(Common::Rect(150, 92, 174, 112), Common::KEYCODE_a, &_iconSprites);
 }
 
+/*------------------------------------------------------------------------*/
+
+void NotWhileEngaged::show(XeenEngine *vm, int spellId) {
+	NotWhileEngaged *dlg = new NotWhileEngaged(vm);
+	dlg->execute(spellId);
+	delete dlg;
+}
+
+void NotWhileEngaged::execute(int spellId) {
+	EventsManager &events = *_vm->_events;
+	Screen &screen = *_vm->_screen;
+	Spells &spells = *_vm->_spells;
+	Window &w = screen._windows[6];
+	Mode oldMode = _vm->_mode;
+	_vm->_mode = MODE_3;
+
+	w.open();
+	w.writeString(Common::String::format(CANT_CAST_WHILE_ENGAGED,
+		spells._spellNames[spellId].c_str()));
+	w.update();
+
+	while (!_vm->shouldQuit() && !events.isKeyMousePressed())
+		events.pollEventsAndWait();
+	events.clearEvents();
+
+	w.close();
+	_vm->_mode = oldMode;
+}
+
+
 } // End of namespace Xeen
diff --git a/engines/xeen/dialogs_spells.h b/engines/xeen/dialogs_spells.h
index 6bbdb3c..b23f62b 100644
--- a/engines/xeen/dialogs_spells.h
+++ b/engines/xeen/dialogs_spells.h
@@ -98,6 +98,18 @@ public:
 	static int show(XeenEngine *vm, int spellId);
 };
 
+class NotWhileEngaged : public ButtonContainer {
+private:
+	XeenEngine *_vm;
+
+	NotWhileEngaged(XeenEngine *vm) : ButtonContainer(), _vm(vm) {}
+
+	void execute(int spellId);
+public:
+	static void show(XeenEngine *vm, int spellId);
+};
+
+
 } // End of namespace Xeen
 
 #endif /* XEEN_DIALOGS_SPELLS_H */
diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp
index 923eaea..d1a1478 100644
--- a/engines/xeen/interface.cpp
+++ b/engines/xeen/interface.cpp
@@ -541,7 +541,7 @@ void Interface::perform() {
 			if (spellId == -1 || c == nullptr)
 				break;
 
-			result = spells.castSpell(c, spellId);
+			result = spells.castSpell(c, (MagicSpell)spellId);
 		} while (result != -1);
 
 		if (result == 1) {
@@ -2008,7 +2008,7 @@ void Interface::doCombat() {
 				int spellId = CastSpell::show(_vm);
 				if (spellId != -1) {
 					Character *c = combat._combatParty[combat._whosTurn];
-					spells.castSpell(c, spellId);
+					spells.castSpell(c, (MagicSpell)spellId);
 					nextChar();
 				} else {
 					highlightChar(combat._combatParty[combat._whosTurn]->_rosterId);
diff --git a/engines/xeen/resources.cpp b/engines/xeen/resources.cpp
index 3a751b7..228c5f6 100644
--- a/engines/xeen/resources.cpp
+++ b/engines/xeen/resources.cpp
@@ -438,6 +438,10 @@ const int8 SCREEN_POSITIONING_Y[4][48] = {
 	}
 };
 
+const int MONSTER_GRID_BITMASK[12] = {
+	0xC, 8, 4, 0, 0xF, 0xF000, 0xF00, 0xF0, 0xF00, 0xF0, 0x0F, 0xF000
+};
+
 const int INDOOR_OBJECT_X[2][12] = {
 	{ 5, -7, -112, 98, -8, -65, 49, -9, -34, 16, -58, 40 },
 	{ -35, -35, -142, 68, -35, -95, 19, -35, -62, -14, -98, 16 }
@@ -827,7 +831,7 @@ const int MISC_SPELL_INDEX[74] = {
 	MS_Levitate, MS_WizardEye, MS_Bless, MS_IdentifyMonster,
 	MS_LightningBolt, MS_HolyBonus, MS_PowerCure, MS_NaturesCure,
 	MS_LloydsBeacon, MS_PowerShield, MS_Heroism, MS_Hynotize,
-	MS_WalkOnWater, MS_FrostBite, MS_DetectMonster, MS_FireBall,
+	MS_WalkOnWater, MS_FrostBite, MS_DetectMonster, MS_Fireball,
 	MS_ColdRay, MS_CurePoison, MS_AcidSpray, MS_TimeDistortion,
 	MS_DragonSleep, MS_CureDisease, MS_Teleport, MS_FingerOfDeath,
 	MS_CureParalysis, MS_GolemStopper, MS_PoisonVolley, MS_DeadlySwarm,
diff --git a/engines/xeen/resources.h b/engines/xeen/resources.h
index fed2491..84a4648 100644
--- a/engines/xeen/resources.h
+++ b/engines/xeen/resources.h
@@ -127,6 +127,8 @@ extern const int8 SCREEN_POSITIONING_X[4][48];
 
 extern const int8 SCREEN_POSITIONING_Y[4][48];
 
+extern const int MONSTER_GRID_BITMASK[12];
+
 extern const int INDOOR_OBJECT_X[2][12];
 
 extern const int MAP_OBJECT_Y[2][12];
diff --git a/engines/xeen/spells.cpp b/engines/xeen/spells.cpp
index b2b477e..f5f6428 100644
--- a/engines/xeen/spells.cpp
+++ b/engines/xeen/spells.cpp
@@ -54,43 +54,34 @@ int Spells::calcSpellPoints(int spellId, int expenseFactor) const {
 
 typedef void(Spells::*SpellMethodPtr)();
 
-void Spells::executeSpell(int spellId) {
-	static const SpellMethodPtr SPELL_LIST[73] = {
-		&Spells::light, &Spells::awaken, &Spells::magicArrow, &Spells::firstAid,
-		&Spells::flyingFist, &Spells::energyBlast, &Spells::sleep,
-		&Spells::revitalize, &Spells::cureWounds, &Spells::sparks,
-
-		&Spells::shrapMetal, &Spells::insectSpray, &Spells::toxicCloud,
-		&Spells::protectionFromElements, &Spells::pain, &Spells::jump,
-		&Spells::beastMaster, &Spells::clairvoyance, &Spells::turnUndead,
-		&Spells::levitate,
-
-		&Spells::wizardEye, &Spells::bless, &Spells::identifyMonster,
-		&Spells::lightningBolt, &Spells::holyBonus, &Spells::powerCure,
-		&Spells::naturesCure, &Spells::lloydsBeacon, &Spells::powerShield,
-		&Spells::heroism,
-
-		&Spells::hypnotize, &Spells::walkOnWater, &Spells::frostByte,
-		&Spells::detectMonster, &Spells::fireball, &Spells::coldRay,
-		&Spells::curePoison, &Spells::acidSpray, &Spells::timeDistortion,
-		&Spells::dragonSleep,
-
-		&Spells::suppressPoison, &Spells::teleport, &Spells::fingerOfDeath,
-		&Spells::cureParalysis, &Spells::golemStopper, &Spells::poisonVolley,
-		&Spells::deadlySwarm, &Spells::superShelter, &Spells::dayOfProtection,
-		&Spells::dayOfSorcery,
-
-		&Spells::createFood, &Spells::fieryFlail, &Spells::rechargeItem,
-		&Spells::fantasticFreeze, &Spells::townPortal, &Spells::stoneToFlesh,
-		&Spells::raiseDead, &Spells::etherialize, &Spells::dancingSword,
-		&Spells::moonRay,
-
-		&Spells::massDistortion, &Spells::prismaticLight, &Spells::enchantItem,
-		&Spells::incinerate, &Spells::holyWord, &Spells::resurrection,
-		&Spells::elementalStorm, &Spells::megaVolts, &Spells::inferno,
-		&Spells::sunRay,
-
-		&Spells::implosion, &Spells::starBurst, &Spells::divineIntervention
+void Spells::executeSpell(MagicSpell spellId) {
+	static const SpellMethodPtr SPELL_LIST[76] = {
+		&Spells::acidSpray, &Spells::awaken, &Spells::beastMaster,
+		&Spells::bless, &Spells::clairvoyance, &Spells::coldRay,
+		&Spells::createFood, &Spells::cureDisease, &Spells::cureParalysis,
+		&Spells::curePoison, &Spells::cureWounds, &Spells::dancingSword,
+		&Spells::dayOfProtection, &Spells::dayOfSorcery, &Spells::deadlySwarm,
+		&Spells::detectMonster, &Spells::divineIntervention, &Spells::dragonSleep,
+		&Spells::elementalStorm, &Spells::enchantItem, &Spells::energyBlast,
+		&Spells::etherialize, &Spells::fantasticFreeze, &Spells::fieryFlail,
+		&Spells::fingerOfDeath, &Spells::fireball, &Spells::firstAid,
+		&Spells::flyingFist, &Spells::frostbite, &Spells::golemStopper,
+		&Spells::heroism, &Spells::holyBonus, &Spells::holyWord,
+		&Spells::hypnotize, &Spells::identifyMonster, &Spells::implosion,
+		&Spells::incinerate, &Spells::inferno, &Spells::insectSpray,
+		&Spells::itemToGold, &Spells::jump, &Spells::levitate,
+		&Spells::light, &Spells::lightningBolt, &Spells::lloydsBeacon,
+		&Spells::magicArrow, &Spells::massDistortion, &Spells::megaVolts,
+		&Spells::moonRay, &Spells::naturesCure, &Spells::pain,
+		&Spells::poisonVolley, &Spells::powerCure, &Spells::powerShield,
+		&Spells::prismaticLight, &Spells::protectionFromElements, &Spells::raiseDead,
+		&Spells::rechargeItem, &Spells::resurrection, &Spells::revitalize,
+		&Spells::shrapMetal, &Spells::sleep, &Spells::sparks,
+		&Spells::starBurst, &Spells::stoneToFlesh, &Spells::sunRay,
+		&Spells::superShelter, &Spells::suppressDisease, &Spells::suppressPoison,
+		&Spells::teleport, &Spells::timeDistortion, &Spells::townPortal,
+		&Spells::toxicCloud, &Spells::turnUndead, &Spells::walkOnWater, 
+		&Spells::wizardEye
 	};
 
 	(this->*SPELL_LIST[spellId])();
@@ -106,23 +97,82 @@ void Spells::spellFailed() {
 /**
  * Cast a spell associated with an item
  */
-void Spells::castItemSpell(int spellId) {
-	if (_vm->_mode == MODE_COMBAT) {
-		if (spellId == 15 || spellId == 20 || spellId == 27 || spellId == 41
-				|| spellId == 47 || spellId == 54 || spellId == 57) {
-			ErrorDialog::show(_vm, Common::String::format(CANT_CAST_WHILE_ENGAGED,
-				_spellNames[spellId].c_str()));
+void Spells::castItemSpell(int itemSpellId) {
+	switch (itemSpellId) {
+	case 15:
+		if (_vm->_mode == MODE_COMBAT) {
+			NotWhileEngaged::show(_vm, MS_Jump);
 			return;
 		}
+		break;
+	case 20:
+		if (_vm->_mode == MODE_COMBAT) {
+			NotWhileEngaged::show(_vm, MS_WizardEye);
+			return;
+		}
+		break;
+	case 27:
+		if (_vm->_mode == MODE_COMBAT) {
+			NotWhileEngaged::show(_vm, MS_LloydsBeacon);
+			return;
+		}
+		break;
+	case 32:
+		frostbite2();
+		break;
+	case 41:
+		if (_vm->_mode == MODE_COMBAT) {
+			NotWhileEngaged::show(_vm, MS_Teleport);
+			return;
+		}
+		break;
+	case 47:
+		if (_vm->_mode == MODE_COMBAT) {
+			NotWhileEngaged::show(_vm, MS_SuperShelter);
+			return;
+		}
+		break;
+	case 54:
+		if (_vm->_mode == MODE_COMBAT) {
+			NotWhileEngaged::show(_vm, MS_TownPortal);
+			return;
+		}
+		break;
+	case 57:
+		if (_vm->_mode == MODE_COMBAT) {
+			NotWhileEngaged::show(_vm, MS_Etheralize);
+			return;
+		}
+		break;
+	default:
+		break;
 	}
 
-	executeSpell(spellId);
+	static const MagicSpell spells[73] = {
+		MS_Light, MS_Awaken, MS_MagicArrow, MS_FirstAid, MS_FlyingFist,
+		MS_EnergyBlast, MS_Sleep, MS_Revitalize, MS_CureWounds, MS_Sparks,
+		MS_Shrapmetal, MS_InsectSpray, MS_ToxicCloud, MS_ProtFromElements, MS_Pain,
+		MS_Jump, MS_BeastMaster, MS_Clairvoyance, MS_TurnUndead, MS_Levitate,
+		MS_WizardEye, MS_Bless, MS_IdentifyMonster, MS_LightningBolt, MS_HolyBonus,
+		MS_PowerCure, MS_NaturesCure, MS_LloydsBeacon, MS_PowerShield, MS_Heroism,
+		MS_Hynotize, MS_WalkOnWater, NO_SPELL, MS_DetectMonster, MS_Fireball,
+		MS_ColdRay, MS_CurePoison, MS_AcidSpray, MS_TimeDistortion, MS_DragonSleep,
+		MS_CureDisease, MS_Teleport, MS_FingerOfDeath, MS_CureParalysis, MS_GolemStopper,
+		MS_PoisonVolley, MS_DeadlySwarm, MS_SuperShelter, MS_DayOfProtection, MS_DayOfProtection,
+		MS_CreateFood, MS_FieryFlail, MS_RechargeItem, MS_FantasticFreeze, MS_TownPortal,
+		MS_StoneToFlesh, MS_RaiseDead, MS_Etheralize, MS_DancingSword, MS_MoonRay,
+		MS_MassDistortion, MS_PrismaticLight, MS_EnchantItem, MS_Incinerate, MS_HolyWord,
+		MS_Resurrection, MS_ElementalStorm, MS_MegaVolts, MS_Inferno, MS_SunRay,
+		MS_Implosion, MS_StarBurst, MS_DivineIntervention
+	};
+
+	executeSpell(spells[itemSpellId]);
 }
 
 /**
  * Cast a given spell
  */
-int Spells::castSpell(Character *c, int spellId) {
+int Spells::castSpell(Character *c, MagicSpell spellId) {
 	Combat &combat = *_vm->_combat;
 	Interface &intf = *_vm->_interface;
 	int oldTillMove = intf._tillMove;
@@ -137,21 +187,20 @@ int Spells::castSpell(Character *c, int spellId) {
 	} else {
 		// Some spells have special handling
 		switch (spellId) {
-		case 19:	// Enchant item
-		case 21:	// Etherialize
-		case 40:	// Jump
-		case 44:	// Lloyd's Beacon
-		case 66:	// Super Shelter
-		case 69:	// Teleport
-		case 71:	// Town Portal
-		case 75:	// Wizard Eye
+		case MS_EnchantItem:
+		case MS_Etheralize:	
+		case MS_Jump:
+		case MS_LloydsBeacon:
+		case MS_SuperShelter:
+		case MS_Teleport:
+		case MS_TownPortal:
+		case MS_WizardEye:
 			if (_vm->_mode != MODE_COMBAT) {
 				executeSpell(spellId);
 			} else {
 				// Return the spell costs and flag that another spell can be selected
 				addSpellCost(*c, spellId);
-				ErrorDialog::show(_vm, Common::String::format(CANT_CAST_WHILE_ENGAGED,
-					_spellNames[spellId].c_str()));
+				NotWhileEngaged::show(_vm, spellId);
 				result = -1;
 			}
 			break;
@@ -209,18 +258,9 @@ void Spells::addSpellCost(Character &c, int spellId) {
 	party._gems += gemCost;
 }
 
-void Spells::light() { 
-	Interface &intf = *_vm->_interface;
-	Party &party = *_vm->_party;
-	SoundManager &sound = *_vm->_sound;
-
-	++party._lightCount;
-	if (intf._intrIndex1)
-		party._stepped = true;
-	sound.playFX(39);
-}
+void Spells::acidSpray() { error("TODO: spell"); }
 
-void Spells::awaken() { 
+void Spells::awaken() {
 	Interface &intf = *_vm->_interface;
 	Party &party = *_vm->_party;
 	SoundManager &sound = *_vm->_sound;
@@ -236,14 +276,82 @@ void Spells::awaken() {
 	sound.playFX(30);
 }
 
-void Spells::magicArrow() { 
+void Spells::beastMaster() { error("TODO: spell"); }
+
+void Spells::bless() { error("TODO: spell"); }
+
+void Spells::clairvoyance() { error("TODO: spell"); }
+
+void Spells::coldRay() { error("TODO: spell"); }
+
+void Spells::createFood() { error("TODO: spell"); }
+
+void Spells::cureDisease() { error("TODO: spell"); }
+
+void Spells::cureParalysis() { error("TODO: spell"); }
+
+void Spells::curePoison() { error("TODO: spell"); }
+
+void Spells::cureWounds() {
 	Combat &combat = *_vm->_combat;
-	combat._monsterDamage = 0;
-	combat._damageType = DT_MAGIC_ARROW;
+	Party &party = *_vm->_party;
+	SoundManager &sound = *_vm->_sound;
+
+	int charIndex = SpellOnWho::show(_vm, MS_Revitalize);
+	if (charIndex == -1)
+		return;
+
+	Character &c = combat._combatMode == 2 ? *combat._combatParty[charIndex] :
+		party._activeParty[charIndex];
+
+	if (c.isDead()) {
+		spellFailed();
+	}
+	else {
+		sound.playFX(30);
+		c.addHitPoints(15);
+	}
+}
+
+void Spells::dancingSword() { error("TODO: spell"); }
+
+void Spells::dayOfProtection() { error("TODO: spell"); }
+
+void Spells::dayOfSorcery() { error("TODO: spell"); }
+
+void Spells::deadlySwarm() { error("TODO: spell"); }
+
+void Spells::detectMonster() { error("TODO: spell"); }
+
+void Spells::divineIntervention() { error("TODO: spell"); }
+
+void Spells::dragonSleep() { error("TODO: spell"); }
+
+void Spells::elementalStorm() { error("TODO: spell"); }
+
+void Spells::enchantItem() { error("TODO: spell"); }
+
+void Spells::energyBlast() {
+	Combat &combat = *_vm->_combat;
+	SoundManager &sound = *_vm->_sound;
+
+	combat._monsterDamage = combat._oldCharacter->getCurrentLevel() * 2;
+	combat._damageType = DT_ENERGY;
 	combat._rangeType = RT_SINGLE;
-	combat.multiAttack(11);
+	sound.playFX(16);
+	combat.multiAttack(13);
 }
 
+void Spells::etherialize() { error("TODO: spell"); }		// Not while engaged
+
+void Spells::fantasticFreeze() { error("TODO: spell"); }
+
+void Spells::fieryFlail() { error("TODO: spell"); }
+
+void Spells::fingerOfDeath() { error("TODO: spell"); }
+
+void Spells::fireball() { error("TODO: spell"); }
+
 void Spells::firstAid() {
 	Combat &combat = *_vm->_combat;
 	Party &party = *_vm->_party;
@@ -258,7 +366,8 @@ void Spells::firstAid() {
 
 	if (c.isDead()) {
 		spellFailed();
-	} else {
+	}
+	else {
 		sound.playFX(30);
 		c.addHitPoints(6);
 	}
@@ -275,28 +384,158 @@ void Spells::flyingFist() {
 	combat.multiAttack(14);
 }
 
-void Spells::energyBlast() {
-	Combat &combat = *_vm->_combat;
+void Spells::frostbite() { error("TODO: spell"); }
+
+void Spells::golemStopper() { error("TODO: spell"); }
+
+void Spells::heroism() { error("TODO: spell"); }
+
+void Spells::holyBonus() { error("TODO: spell"); }
+
+void Spells::holyWord() { error("TODO: spell"); }
+
+void Spells::hypnotize() { error("TODO: spell"); }
+
+void Spells::identifyMonster() { error("TODO: spell"); }
+
+void Spells::implosion() { error("TODO: spell"); }
+
+void Spells::incinerate() { error("TODO: spell"); }
+
+void Spells::inferno() { error("TODO: spell"); }
+
+void Spells::insectSpray() { error("TODO: spell"); }
+
+void Spells::itemToGold() { error("TODO: spell"); }
+
+void Spells::jump() {
+	Map &map = *_vm->_map;
+	Party &party = *_vm->_party;
 	SoundManager &sound = *_vm->_sound;
 
-	combat._monsterDamage = combat._oldCharacter->getCurrentLevel() * 2;
-	combat._damageType = DT_ENERGY;
+	if (map._isOutdoors) {
+		map.getCell(7);
+		if (map._currentWall != 1) {
+			map.getCell(14);
+			if (map._currentSurfaceId != 0 && map._currentWall != 1) {
+				party._mazePosition += Common::Point(
+					SCREEN_POSITIONING_X[party._mazeDirection][14],
+					SCREEN_POSITIONING_Y[party._mazeDirection][14]
+					);
+				sound.playFX(51);
+				party._stepped = true;
+				return;
+			}
+		}
+	} else {
+		Common::Point pt = party._mazePosition + Common::Point(
+			SCREEN_POSITIONING_X[party._mazeDirection][7],
+			SCREEN_POSITIONING_Y[party._mazeDirection][7]);
+		if (!map.mazeLookup(party._mazePosition, MONSTER_GRID_BITMASK[party._mazeDirection]) &&
+			!map.mazeLookup(pt, MONSTER_GRID_BITMASK[party._mazeDirection])) {
+			party._mazePosition += Common::Point(
+				SCREEN_POSITIONING_X[party._mazeDirection][14],
+				SCREEN_POSITIONING_Y[party._mazeDirection][14]
+			);
+			sound.playFX(51);
+			party._stepped = true;
+			return;
+		}
+	}
+
+	spellFailed();
+}
+
+void Spells::levitate() { error("TODO: spell"); }
+
+void Spells::light() { 
+	Interface &intf = *_vm->_interface;
+	Party &party = *_vm->_party;
+	SoundManager &sound = *_vm->_sound;
+
+	++party._lightCount;
+	if (intf._intrIndex1)
+		party._stepped = true;
+	sound.playFX(39);
+}
+
+void Spells::lightningBolt() { error("TODO: spell"); }
+
+void Spells::lloydsBeacon() { error("TODO: spell"); }	// Not while engaged
+
+void Spells::magicArrow() { 
+	Combat &combat = *_vm->_combat;
+	combat._monsterDamage = 0;
+	combat._damageType = DT_MAGIC_ARROW;
 	combat._rangeType = RT_SINGLE;
-	sound.playFX(16);
-	combat.multiAttack(13);
+	combat.multiAttack(11);
 }
 
-void Spells::sleep() {
+void Spells::massDistortion() { error("TODO: spell"); }
+
+void Spells::megaVolts() { error("TODO: spell"); }
+
+void Spells::moonRay() { error("TODO: spell"); }
+
+void Spells::naturesCure() { error("TODO: spell"); }
+
+void Spells::pain() {
 	Combat &combat = *_vm->_combat;
 	SoundManager &sound = *_vm->_sound;
 
 	combat._monsterDamage = 0;
-	combat._damageType = DT_SLEEP;
+	combat._damageType = DT_PHYSICAL;
 	combat._rangeType = RT_GROUP;
 	sound.playFX(18);
-	combat.multiAttack(7);
+	combat.multiAttack(14);
 }
 
+void Spells::poisonVolley() { error("TODO: spell"); }
+
+void Spells::powerCure() { error("TODO: spell"); }
+
+void Spells::powerShield() { error("TODO: spell"); }
+
+void Spells::prismaticLight() { error("TODO: spell"); }
+
+void Spells::protectionFromElements() {
+	Combat &combat = *_vm->_combat;
+	Interface &intf = *_vm->_interface;
+	Party &party = *_vm->_party;
+	SoundManager &sound = *_vm->_sound;
+	Character &c = *combat._oldCharacter;
+	int resist = MIN(c.getCurrentLevel() * 2 + 5, (uint)200);
+	
+	int elementType = SelectElement::show(_vm, MS_ProtFromElements);
+	if (elementType != -1) {
+		switch (elementType) {
+		case DT_FIRE:
+			party._fireResistence = resist;
+			break;
+		case DT_ELECTRICAL:
+			party._fireResistence = resist;
+			break;
+		case DT_COLD:
+			party._coldResistence = resist;
+			break;
+		case DT_POISON:
+			party._poisonResistence = resist;
+			break;
+		default:
+			break;
+		}
+
+		sound.playFX(20);
+		intf.drawParty(true);
+	}
+}
+
+void Spells::raiseDead() { error("TODO: spell"); }
+
+void Spells::rechargeItem() { error("TODO: spell"); }
+
+void Spells::resurrection() { error("TODO: spell"); }
+
 void Spells::revitalize() {
 	Combat &combat = *_vm->_combat;
 	Interface &intf = *_vm->_interface;
@@ -316,24 +555,17 @@ void Spells::revitalize() {
 	intf.drawParty(true);
 }
 
-void Spells::cureWounds() {
+void Spells::shrapMetal() { error("TODO: spell"); }
+
+void Spells::sleep() {
 	Combat &combat = *_vm->_combat;
-	Party &party = *_vm->_party;
 	SoundManager &sound = *_vm->_sound;
 
-	int charIndex = SpellOnWho::show(_vm, MS_Revitalize);
-	if (charIndex == -1)
-		return;
-
-	Character &c = combat._combatMode == 2 ? *combat._combatParty[charIndex] :
-		party._activeParty[charIndex];
-
-	if (c.isDead()) {
-		spellFailed();
-	} else {
-		sound.playFX(30);
-		c.addHitPoints(15);
-	}
+	combat._monsterDamage = 0;
+	combat._damageType = DT_SLEEP;
+	combat._rangeType = RT_GROUP;
+	sound.playFX(18);
+	combat.multiAttack(7);
 }
 
 void Spells::sparks() {
@@ -347,19 +579,15 @@ void Spells::sparks() {
 	combat.multiAttack(5);
 }
 
-void Spells::shrapMetal() { error("TODO: spell"); }
-void Spells::insectSpray() { error("TODO: spell"); }
+void Spells::starBurst() { error("TODO: spell"); }
 
-void Spells::toxicCloud() {
-	Combat &combat = *_vm->_combat;
-	SoundManager &sound = *_vm->_sound;
+void Spells::stoneToFlesh() { error("TODO: spell"); }
 
-	combat._monsterDamage = 10;
-	combat._damageType = DT_POISON;
-	combat._rangeType = RT_GROUP;
-	sound.playFX(17);
-	combat.multiAttack(10);
-}
+void Spells::sunRay() { error("TODO: spell"); }
+
+void Spells::superShelter() { error("TODO: spell"); }
+
+void Spells::suppressDisease() { error("TODO: spell"); }
 
 void Spells::suppressPoison() {
 	Combat &combat = *_vm->_combat;
@@ -387,111 +615,47 @@ void Spells::suppressPoison() {
 	intf.drawParty(1);
 }
 
-void Spells::protectionFromElements() {
+void Spells::teleport() { error("TODO: spell"); }		// Not while engaged
+
+void Spells::timeDistortion() { error("TODO: spell"); }
+
+void Spells::townPortal() { error("TODO: spell"); }		// Not while engaged
+
+void Spells::toxicCloud() {
 	Combat &combat = *_vm->_combat;
-	Interface &intf = *_vm->_interface;
-	Party &party = *_vm->_party;
 	SoundManager &sound = *_vm->_sound;
-	Character &c = *combat._oldCharacter;
-	int resist = MIN(c.getCurrentLevel() * 2 + 5, (uint)200);
-	
-	int elementType = SelectElement::show(_vm, MS_ProtFromElements);
-	if (elementType != -1) {
-		switch (elementType) {
-		case DT_FIRE:
-			party._fireResistence = resist;
-			break;
-		case DT_ELECTRICAL:
-			party._fireResistence = resist;
-			break;
-		case DT_COLD:
-			party._coldResistence = resist;
-			break;
-		case DT_POISON:
-			party._poisonResistence = resist;
-			break;
-		default:
-			break;
-		}
 
-		sound.playFX(20);
-		intf.drawParty(true);
-	}
+	combat._monsterDamage = 10;
+	combat._damageType = DT_POISON;
+	combat._rangeType = RT_GROUP;
+	sound.playFX(17);
+	combat.multiAttack(10);
 }
 
-void Spells::pain() {
+void Spells::turnUndead() {
 	Combat &combat = *_vm->_combat;
 	SoundManager &sound = *_vm->_sound;
 
 	combat._monsterDamage = 0;
-	combat._damageType = DT_PHYSICAL;
+	combat._damageType = DT_UNDEAD;
 	combat._rangeType = RT_GROUP;
 	sound.playFX(18);
-	combat.multiAttack(14);
+	combat.multiAttack(13);
 }
 
-void Spells::jump() { error("TODO: spell"); }			// Not while engaged
-void Spells::beastMaster() { error("TODO: spell"); }
-void Spells::clairvoyance() { error("TODO: spell"); }
-void Spells::turnUndead() { error("TODO: spell"); }
-void Spells::levitate() { error("TODO: spell"); }
-
-void Spells::wizardEye() { error("TODO: spell"); }		// Not while engaged
-void Spells::bless() { error("TODO: spell"); }
-void Spells::identifyMonster() { error("TODO: spell"); }
-void Spells::lightningBolt() { error("TODO: spell"); }
-void Spells::holyBonus() { error("TODO: spell"); }
-void Spells::powerCure() { error("TODO: spell"); }
-void Spells::naturesCure() { error("TODO: spell"); }
-void Spells::lloydsBeacon() { error("TODO: spell"); }	// Not while engaged
-void Spells::powerShield() { error("TODO: spell"); }
-void Spells::heroism() { error("TODO: spell"); }
-
-void Spells::hypnotize() { error("TODO: spell"); }
 void Spells::walkOnWater() { error("TODO: spell"); }
-void Spells::frostByte() { error("TODO: spell"); }
-void Spells::detectMonster() { error("TODO: spell"); }
-void Spells::fireball() { error("TODO: spell"); }
-void Spells::coldRay() { error("TODO: spell"); }
-void Spells::curePoison() { error("TODO: spell"); }
-void Spells::acidSpray() { error("TODO: spell"); }
-void Spells::timeDistortion() { error("TODO: spell"); }
-void Spells::dragonSleep() { error("TODO: spell"); }
 
-void Spells::teleport() { error("TODO: spell"); }		// Not while engaged
-void Spells:: fingerOfDeath() { error("TODO: spell"); }
-void Spells::cureParalysis() { error("TODO: spell"); }
-void Spells::golemStopper() { error("TODO: spell"); }
-void Spells::poisonVolley() { error("TODO: spell"); }
-void Spells::deadlySwarm() { error("TODO: spell"); }
-void Spells::superShelter() { error("TODO: spell"); }	// Not while engaged
-void Spells::dayOfProtection() { error("TODO: spell"); }
-void Spells::dayOfSorcery() { error("TODO: spell"); }
-
-void Spells::createFood() { error("TODO: spell"); }
-void Spells::fieryFlail() { error("TODO: spell"); }
-void Spells::rechargeItem() { error("TODO: spell"); }
-void Spells::fantasticFreeze() { error("TODO: spell"); }
-void Spells::townPortal() { error("TODO: spell"); }		// Not while engaged
-void Spells::stoneToFlesh() { error("TODO: spell"); }
-void Spells::raiseDead() { error("TODO: spell"); }
-void Spells::etherialize() { error("TODO: spell"); }		// Not while engaged
-void Spells::dancingSword() { error("TODO: spell"); }
-void Spells::moonRay() { error("TODO: spell"); }
-
-void Spells::massDistortion() { error("TODO: spell"); }
-void Spells::prismaticLight() { error("TODO: spell"); }
-void Spells::enchantItem() { error("TODO: spell"); }
-void Spells::incinerate() { error("TODO: spell"); }
-void Spells::holyWord() { error("TODO: spell"); }
-void Spells::resurrection() { error("TODO: spell"); }
-void Spells::elementalStorm() { error("TODO: spell"); }
-void Spells::megaVolts() { error("TODO: spell"); }
-void Spells::inferno() { error("TODO: spell"); }
-void Spells::sunRay() { error("TODO: spell"); }
+void Spells::wizardEye() { error("TODO: spell"); }		// Not while engaged
 
-void Spells::implosion() { error("TODO: spell"); }
-void Spells::starBurst() { error("TODO: spell"); }
-void Spells::divineIntervention() { error("TODO: spell"); }
+void Spells::frostbite2() {
+	Combat &combat = *_vm->_combat;
+	SoundManager &sound = *_vm->_sound;
+	
+	combat._monsterDamage = 35;
+	combat._damageType = DT_COLD;
+	combat._rangeType = RT_SINGLE;
+	sound.playFX(15);
+	combat.multiAttack(9);
+}
 
 } // End of namespace Xeen
diff --git a/engines/xeen/spells.h b/engines/xeen/spells.h
index f71f1fd..1af4fb2 100644
--- a/engines/xeen/spells.h
+++ b/engines/xeen/spells.h
@@ -42,7 +42,7 @@ enum MagicSpell {
 	MS_DivineIntervention = 16, MS_DragonSleep = 17, MS_ElementalStorm = 18,
 	MS_EnchantItem = 19, MS_EnergyBlast = 20, MS_Etheralize = 21,
 	MS_FantasticFreeze = 22, MS_FieryFlail = 23, MS_FingerOfDeath = 24,
-	MS_FireBall = 25, MS_FirstAid = 26, MS_FlyingFist = 27,
+	MS_Fireball = 25, MS_FirstAid = 26, MS_FlyingFist = 27,
 	MS_FrostBite = 28, MS_GolemStopper = 29, MS_Heroism = 30,
 	MS_HolyBonus = 31, MS_HolyWord = 32, MS_Hynotize = 33,
 	MS_IdentifyMonster = 34, MS_Implosion = 35, MS_Incinerate = 36,
@@ -67,91 +67,89 @@ private:
 
 	void load();
 
-	void executeSpell(int spellId);
+	void executeSpell(MagicSpell spellId);
 
 	void spellFailed();
 
 	// Spell list
-	void light();
+	void acidSpray();
 	void awaken();
-	void magicArrow();
-	void firstAid();
-	void flyingFist();
-	void energyBlast();
-	void sleep();
-	void revitalize();
-	void cureWounds();
-	void sparks();
-
-	void shrapMetal();
-	void insectSpray();
-	void toxicCloud();
-	void protectionFromElements();
-	void pain();
-	void jump();			// Not while engaged
 	void beastMaster();
-	void clairvoyance();
-	void turnUndead();
-	void levitate();
-
-	void wizardEye();		// Not while engaged
 	void bless();
-	void identifyMonster();
-	void lightningBolt();
-	void holyBonus();
-	void powerCure();
-	void naturesCure();
-	void lloydsBeacon();	// Not while engaged
-	void powerShield();
-	void heroism();
-
-	void hypnotize();
-	void walkOnWater();
-	void frostByte();
-	void detectMonster();
-	void fireball();
+	void clairvoyance();
 	void coldRay();
-	void curePoison();
-	void acidSpray();
-	void timeDistortion();
-	void dragonSleep();
-
-	void suppressPoison();
-	void teleport();		// Not while engaged
-	void  fingerOfDeath();
+	void createFood();
+	void cureDisease();
 	void cureParalysis();
-	void golemStopper();
-	void poisonVolley();
-	void deadlySwarm();
-	void superShelter();	// Not while engaged
+	void curePoison();
+	void cureWounds();
+	void dancingSword();
 	void dayOfProtection();
 	void dayOfSorcery();
-
-	void createFood();
-	void fieryFlail();
-	void rechargeItem();
+	void deadlySwarm();
+	void detectMonster();
+	void divineIntervention();
+	void dragonSleep();
+	void elementalStorm();
+	void enchantItem();
+	void energyBlast();
+	void etherialize();
 	void fantasticFreeze();
-	void townPortal();		// Not while engaged
-	void stoneToFlesh();
-	void raiseDead();
-	void etherialize();		// Not while engaged
-	void dancingSword();
-	void moonRay();
-
+	void fieryFlail();
+	void fingerOfDeath();
+	void fireball();
+	void firstAid();
+	void flyingFist();
+	void frostbite();
+	void golemStopper();
+	void heroism();
+	void holyBonus();
+	void holyWord();
+	void hypnotize();
+	void identifyMonster();
+	void implosion();
+	void incinerate();
+	void inferno();
+	void insectSpray();
+	void itemToGold();
+	void jump();
+	void levitate();
+	void light();
+	void lightningBolt();
+	void lloydsBeacon();
+	void magicArrow();
 	void massDistortion();
+	void megaVolts();
+	void moonRay();
+	void naturesCure();
+	void pain();
+	void poisonVolley();
+	void powerCure();
+	void powerShield();
 	void prismaticLight();
-	void enchantItem();
-	void incinerate();
-	void holyWord();
+	void protectionFromElements();
+	void raiseDead();
+	void rechargeItem();
 	void resurrection();
-	void elementalStorm();
-	void megaVolts();
-	void inferno();
+	void revitalize();
+	void shrapMetal();
+	void sleep();
+	void sparks();
+	void starBurst();
+	void stoneToFlesh();
 	void sunRay();
+	void superShelter();
+	void suppressDisease();
+	void suppressPoison();
+	void teleport();
+	void timeDistortion();
+	void townPortal();
+	void toxicCloud();
+	void turnUndead();
+	void walkOnWater();
+	void wizardEye();
 
-	void implosion();
-	void starBurst();
-	void divineIntervention();
+	void frostbite2();
 public:
 	Common::StringArray _spellNames;
 	int _lastCaster;
@@ -162,9 +160,9 @@ public:
 
 	int calcSpellPoints(int spellId, int expenseFactor) const;
 
-	void castItemSpell(int spellId);
+	void castItemSpell(int itemSpellId);
 
-	int castSpell(Character *c, int spellId);
+	int castSpell(Character *c, MagicSpell spellId);
 
 	int subSpellCost(Character &c, int spellId);
 


Commit: b243768887c3aabbc6fe57e83971562bf2eba0f5
    https://github.com/scummvm/scummvm/commit/b243768887c3aabbc6fe57e83971562bf2eba0f5
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-03-01T08:31:03-05:00

Commit Message:
XEEN: Implementing spells

Changed paths:
    engines/xeen/dialogs_spells.cpp
    engines/xeen/dialogs_spells.h
    engines/xeen/resources.cpp
    engines/xeen/resources.h
    engines/xeen/spells.cpp



diff --git a/engines/xeen/dialogs_spells.cpp b/engines/xeen/dialogs_spells.cpp
index dfc72aa..f535776 100644
--- a/engines/xeen/dialogs_spells.cpp
+++ b/engines/xeen/dialogs_spells.cpp
@@ -755,5 +755,112 @@ void NotWhileEngaged::execute(int spellId) {
 	_vm->_mode = oldMode;
 }
 
+/*------------------------------------------------------------------------*/
+
+bool LloydsBeacon::show(XeenEngine *vm) {
+	LloydsBeacon *dlg = new LloydsBeacon(vm);
+	bool result = dlg->execute();
+	delete dlg;
+
+	return result;
+}
+
+bool LloydsBeacon::execute() {
+	Combat &combat = *_vm->_combat;
+	EventsManager &events = *_vm->_events;
+	Interface &intf = *_vm->_interface;
+	Map &map = *_vm->_map;
+	Party &party = *_vm->_party;
+	Screen &screen = *_vm->_screen;
+	SoundManager &sound = *_vm->_sound;
+	Spells &spells = *_vm->_spells;
+	Window &w = screen._windows[10];
+	bool isDarkCc = _vm->_files->_isDarkCc;
+	Character &c = *combat._oldCharacter;
+
+	loadButtons();
+
+	if (!c._lloydMap) {
+		// No destination previously set, so have a default ready
+		if (isDarkCc) {
+			c._lloydSide = 1;
+			c._lloydPosition = Common::Point(25, 21);
+			c._lloydMap = 29;
+		} else {
+			c._lloydSide = 0;
+			c._lloydPosition = Common::Point(18, 4);
+			c._lloydMap = 28;
+		}
+	}
+
+	// Open up the text file for the destination map and read in it's name
+	File textFile(Common::String::format("%s%c%03d.txt",
+		c._lloydSide == 0 ? "xeen" : "dark",
+		c._lloydMap >= 100 ? 'x' : '0',
+		c._lloydMap));
+	Common::String mapName = textFile.readString();
+	textFile.close();
+
+	// Display the dialog
+	w.open();
+	w.writeString(Common::String::format(LLOYDS_BEACON,
+		mapName.c_str(), c._lloydPosition.x, c._lloydPosition.y));
+	drawButtons(&screen);
+	w.update();
+
+	bool result = true;
+	do {
+		do {
+			events.updateGameCounter();
+			intf.draw3d(true);
+
+			do {
+				events.pollEventsAndWait();
+				if (_vm->shouldQuit())
+					return true;
+
+				checkEvents(_vm);
+			} while (!_buttonValue && events.timeElapsed() < 1);
+		} while (!_buttonValue);
+
+		switch (_buttonValue) {
+		case Common::KEYCODE_r:
+			if (!isDarkCc && c._lloydMap >= 75 && c._lloydMap <= 78 && !party._cloudsEnd) {
+				result = false;
+			} else {
+				sound.playFX(51);
+				map._loadDarkSide = isDarkCc;
+				if (c._lloydMap != party._mazeId || c._lloydSide != (isDarkCc ? 1 : 0)) {
+					map.load(c._lloydMap);
+				}
+
+				party._mazePosition = c._lloydPosition;
+			}
+
+			_buttonValue = Common::KEYCODE_ESCAPE;
+			break;
+
+		case Common::KEYCODE_s:
+		case Common::KEYCODE_t:
+			sound.playFX(20);
+			c._lloydMap = party._mazeId;
+			c._lloydPosition = party._mazePosition;
+			c._lloydSide = isDarkCc ? 1 : 0;
+			
+			_buttonValue = Common::KEYCODE_ESCAPE;
+			break;
+		}
+	} while (_buttonValue != Common::KEYCODE_ESCAPE);
+
+	w.close();
+	return result;
+}
+
+void LloydsBeacon::loadButtons() {
+	_iconSprites.load("lloyds.icn");
+
+	addButton(Common::Rect(281, 108, 305, 128), Common::KEYCODE_r, &_iconSprites);
+	addButton(Common::Rect(242, 108, 266, 128), Common::KEYCODE_t, &_iconSprites);
+}
 
 } // End of namespace Xeen
diff --git a/engines/xeen/dialogs_spells.h b/engines/xeen/dialogs_spells.h
index b23f62b..ca7bb17 100644
--- a/engines/xeen/dialogs_spells.h
+++ b/engines/xeen/dialogs_spells.h
@@ -109,6 +109,19 @@ public:
 	static void show(XeenEngine *vm, int spellId);
 };
 
+class LloydsBeacon : public ButtonContainer {
+private:
+	XeenEngine *_vm;
+	SpriteResource _iconSprites;
+
+	LloydsBeacon(XeenEngine *vm) : ButtonContainer(), _vm(vm) {}
+
+	bool execute();
+
+	void loadButtons();
+public:
+	static bool show(XeenEngine *vm);
+};
 
 } // End of namespace Xeen
 
diff --git a/engines/xeen/resources.cpp b/engines/xeen/resources.cpp
index 228c5f6..a75f77b 100644
--- a/engines/xeen/resources.cpp
+++ b/engines/xeen/resources.cpp
@@ -1544,4 +1544,14 @@ const char *const WHICH_ELEMENT2 =
 	"\r\x3""cWhich Element?', 2, 0Bh, '034\t014\f15F\fdire\t044"
 	"\f15E\fdlec\t074\f15C\fdold\t104\f15A\fdcid\x1";
 
+const char *const DETECT_MONSTERS = "\x3""cDetect Monsters";
+
+const char *const LLOYDS_BEACON =
+	"\r\x3""c\v000\t000\x1Lloyd's Beacon\n"
+	"\n"
+	"Last Location\n"
+	"\n"
+	"%s\x3l\n"
+	"x = %d\x3r\t000y = %d\x3""c\x2\v122\t021\f15S\fdet\t060\f15R\fdeturn\x1";
+
 } // End of namespace Xeen
diff --git a/engines/xeen/resources.h b/engines/xeen/resources.h
index 84a4648..89dc74a 100644
--- a/engines/xeen/resources.h
+++ b/engines/xeen/resources.h
@@ -546,6 +546,10 @@ extern const char *const ON_WHO;
 extern const char *const WHICH_ELEMENT1;
 extern const char *const WHICH_ELEMENT2;
 
+extern const char *const DETECT_MONSTERS;
+
+extern const char *const LLOYDS_BEACON;
+
 } // End of namespace Xeen
 
 #endif	/* XEEN_RESOURCES_H */
diff --git a/engines/xeen/spells.cpp b/engines/xeen/spells.cpp
index f5f6428..e3978ae 100644
--- a/engines/xeen/spells.cpp
+++ b/engines/xeen/spells.cpp
@@ -21,6 +21,7 @@
  */
 
 #include "xeen/spells.h"
+#include "xeen/dialogs_items.h"
 #include "xeen/dialogs_spells.h"
 #include "xeen/files.h"
 #include "xeen/resources.h"
@@ -258,7 +259,16 @@ void Spells::addSpellCost(Character &c, int spellId) {
 	party._gems += gemCost;
 }
 
-void Spells::acidSpray() { error("TODO: spell"); }
+void Spells::acidSpray() {
+	Combat &combat = *_vm->_combat;
+	SoundManager &sound = *_vm->_sound;
+
+	combat._monsterDamage = 15;
+	combat._damageType = DT_POISON;
+	combat._rangeType = RT_ALL;
+	sound.playFX(17);
+	combat.multiAttack(10);
+}
 
 void Spells::awaken() {
 	Interface &intf = *_vm->_interface;
@@ -276,21 +286,106 @@ void Spells::awaken() {
 	sound.playFX(30);
 }
 
-void Spells::beastMaster() { error("TODO: spell"); }
+void Spells::beastMaster() {
+	Combat &combat = *_vm->_combat;
+	SoundManager &sound = *_vm->_sound;
 
-void Spells::bless() { error("TODO: spell"); }
+	combat._monsterDamage = 0;
+	combat._damageType = DT_BEASTMASTER;
+	combat._rangeType = RT_GROUP;
+	sound.playFX(18);
+	combat.multiAttack(7);
+}
 
-void Spells::clairvoyance() { error("TODO: spell"); }
+void Spells::bless() {
+	Combat &combat = *_vm->_combat;
+	Party &party = *_vm->_party;
+	SoundManager &sound = *_vm->_sound;
 
-void Spells::coldRay() { error("TODO: spell"); }
+	sound.playFX(30);
+	party._blessed = combat._oldCharacter->getCurrentLevel();
+}
 
-void Spells::createFood() { error("TODO: spell"); }
+void Spells::clairvoyance() {
+	_vm->_party->_clairvoyanceActive = true;
+	_vm->_sound->playFX(20);
+}
 
-void Spells::cureDisease() { error("TODO: spell"); }
+void Spells::coldRay() {
+	Combat &combat = *_vm->_combat;
+	SoundManager &sound = *_vm->_sound;
 
-void Spells::cureParalysis() { error("TODO: spell"); }
+	combat._monsterDamage = _vm->getRandomNumber(2, 4) * combat._oldCharacter->getCurrentLevel();
+	combat._damageType = DT_COLD;
+	combat._rangeType = RT_ALL;
+	sound.playFX(15);
+	combat.multiAttack(8);
+}
 
-void Spells::curePoison() { error("TODO: spell"); }
+void Spells::createFood() { 
+	Party &party = *_vm->_party;
+	SoundManager &sound = *_vm->_sound;
+
+	party._food += party._activeParty.size();
+	sound.playFX(20);
+}
+
+void Spells::cureDisease() {
+	Combat &combat = *_vm->_combat;
+	Interface &intf = *_vm->_interface;
+	Party &party = *_vm->_party;
+	SoundManager &sound = *_vm->_sound;
+
+	int charIndex = SpellOnWho::show(_vm, MS_Revitalize);
+	if (charIndex == -1)
+		return;
+
+	Character &c = combat._combatMode == 2 ? *combat._combatParty[charIndex] :
+		party._activeParty[charIndex];
+
+	sound.playFX(30);
+	c.addHitPoints(0);
+	c._conditions[DISEASED] = 0;
+	intf.drawParty(true);
+}
+
+void Spells::cureParalysis() {
+	Combat &combat = *_vm->_combat;
+	Interface &intf = *_vm->_interface;
+	Party &party = *_vm->_party;
+	SoundManager &sound = *_vm->_sound;
+
+	int charIndex = SpellOnWho::show(_vm, MS_Revitalize);
+	if (charIndex == -1)
+		return;
+
+	Character &c = combat._combatMode == 2 ? *combat._combatParty[charIndex] :
+		party._activeParty[charIndex];
+
+	sound.playFX(30);
+	c.addHitPoints(0);
+	c._conditions[PARALYZED] = 0;
+	intf.drawParty(true);
+}
+
+void Spells::curePoison() {
+	Combat &combat = *_vm->_combat;
+	Interface &intf = *_vm->_interface;
+	Party &party = *_vm->_party;
+	SoundManager &sound = *_vm->_sound;
+
+	int charIndex = SpellOnWho::show(_vm, MS_Revitalize);
+	if (charIndex == -1)
+		return;
+
+	Character &c = combat._combatMode == 2 ? *combat._combatParty[charIndex] :
+		party._activeParty[charIndex];
+
+	sound.playFX(30);
+	c.addHitPoints(0);
+	c._conditions[POISONED] = 0;
+	intf.drawParty(true);
+}
 
 void Spells::cureWounds() {
 	Combat &combat = *_vm->_combat;
@@ -306,30 +401,178 @@ void Spells::cureWounds() {
 
 	if (c.isDead()) {
 		spellFailed();
-	}
-	else {
+	} else {
 		sound.playFX(30);
 		c.addHitPoints(15);
 	}
 }
 
-void Spells::dancingSword() { error("TODO: spell"); }
+void Spells::dancingSword() {
+	Combat &combat = *_vm->_combat;
+	SoundManager &sound = *_vm->_sound;
+
+	combat._monsterDamage = _vm->getRandomNumber(6, 14) * combat._oldCharacter->getCurrentLevel();
+	combat._damageType = DT_PHYSICAL;
+	combat._rangeType = RT_GROUP;
+	sound.playFX(18);
+	combat.multiAttack(14);
+}
+
+void Spells::dayOfProtection() {
+	Combat &combat = *_vm->_combat;
+	Party &party = *_vm->_party;
+	SoundManager &sound = *_vm->_sound;
+
+	int lvl = combat._oldCharacter->getCurrentLevel();
+	party._walkOnWaterActive = true;
+	party._heroism = lvl;
+	party._holyBonus = lvl;
+	party._blessed = lvl;
+	party._poisonResistence = lvl;
+	party._coldResistence = lvl;
+	party._electricityResistence = lvl;
+	party._fireResistence = lvl;
+	party._lightCount = lvl;
+	sound.playFX(20);
+}
+
+void Spells::dayOfSorcery() {
+	Combat &combat = *_vm->_combat;
+	Party &party = *_vm->_party;
+	SoundManager &sound = *_vm->_sound;
+
+	int lvl = combat._oldCharacter->getCurrentLevel();
+	party._powerShield = lvl;
+	party._clairvoyanceActive = true;
+	party._wizardEyeActive = true;
+	party._levitateActive = true;
+	party._lightCount = lvl;
+	party._automapOn = false;
+	sound.playFX(20);
+}
+
+void Spells::deadlySwarm() {
+	Combat &combat = *_vm->_combat;
+	SoundManager &sound = *_vm->_sound;
+
+	combat._monsterDamage = 40;
+	combat._damageType = DT_PHYSICAL;
+	combat._rangeType = RT_GROUP;
+	sound.playFX(13);
+	combat.multiAttack(15);
+}
+
+void Spells::detectMonster() {
+	EventsManager &events = *_vm->_events;
+	Interface &intf = *_vm->_interface;
+	Map &map = *_vm->_map;
+	Party &party = *_vm->_party;
+	Screen &screen = *_vm->_screen;
+	SoundManager &sound = *_vm->_sound;
+	Window &w = screen._windows[19];
+	bool isDarkCc = _vm->_files->_isDarkCc;
+	int grid[7][7];
+
+	SpriteResource sprites(isDarkCc ? "detectmn.icn" : "detctmon.icn");
+	Common::fill(&grid[0][0], &grid[7][7], 0);
+
+	w.open();
+	w.writeString(DETECT_MONSTERS);
+	sprites.draw(w, 0, Common::Point(243, 80));
+
+	for (int yDiff = 3; yDiff >= -3; --yDiff) {
+		for (int xDiff = -3; xDiff <= 3; ++xDiff) {
+			for (uint monIndex = 0; monIndex < map._mobData._monsters.size(); ++monIndex) {
+				MazeMonster &monster = map._mobData._monsters[monIndex];
+				Common::Point pt = party._mazePosition + Common::Point(xDiff, yDiff);
+				if (monster._position == pt) {
+					if (++grid[yDiff][xDiff] > 3)
+						grid[yDiff][xDiff] = 3;
+				
+					sprites.draw(w, grid[yDiff][xDiff], Common::Point(xDiff * 9 + 244,
+						yDiff * 7 + 81));
+				}
+			}
+		}
+	}
+
+	sprites.draw(w, party._mazeDirection + 1, Common::Point(270, 101));
+	sound.playFX(20);
+	w.update();
+
+	do {
+		events.updateGameCounter();
+		intf.draw3d(true);
+
+		events.wait(1);
+	} while (!events.isKeyMousePressed());
+
+	w.close();
+}
+
+void Spells::divineIntervention() {
+	Combat &combat = *_vm->_combat;
+	Interface &intf = *_vm->_interface;
+	Party &party = *_vm->_party;
+	SoundManager &sound = *_vm->_sound;
+	Character &castChar = *combat._oldCharacter;
 
-void Spells::dayOfProtection() { error("TODO: spell"); }
+	if ((castChar._tempAge + 5) > 250) {
+		castChar._tempAge = 250;
+	} else {
+		castChar._tempAge += 5;
+	}
 
-void Spells::dayOfSorcery() { error("TODO: spell"); }
+	for (uint idx = 0; idx < party._activeParty.size(); ++idx) {
+		Character &c = party._activeParty[idx];
+		Common::fill(&c._conditions[CURSED], &c._conditions[ERADICATED], 0);
+		if (!c._conditions[ERADICATED])
+			c._currentHp = c.getMaxHP();
+	}
 
-void Spells::deadlySwarm() { error("TODO: spell"); }
+	sound.playFX(20);
+	intf.drawParty(true);
+}
+
+void Spells::dragonSleep() {
+	Combat &combat = *_vm->_combat;
+	SoundManager &sound = *_vm->_sound;
+
+	combat._monsterDamage = 0;
+	combat._damageType = DT_DRAGONSLEEP;
+	combat._rangeType = RT_SINGLE;
+	sound.playFX(18);
+	combat.multiAttack(7);
+}
 
-void Spells::detectMonster() { error("TODO: spell"); }
+void Spells::elementalStorm() {
+	Combat &combat = *_vm->_combat;
+	SoundManager &sound = *_vm->_sound;
+	static const int STORM_FX_LIST[4] = { 13, 14, 15, 17 };
+	static const int STORM_MA_LIST[4] = { 0, 5, 9, 10 };
+
+	combat._monsterDamage = 150;
+	combat._damageType = (DamageType)_vm->getRandomNumber(DT_FIRE, DT_POISON);
+	combat._rangeType = RT_ALL;
+	sound.playFX(STORM_FX_LIST[combat._damageType]);
+	combat.multiAttack(STORM_MA_LIST[combat._damageType]);
+}
 
-void Spells::divineIntervention() { error("TODO: spell"); }
+void Spells::enchantItem() {
+	Combat &combat = *_vm->_combat;
+	Party &party = *_vm->_party;
+	Mode oldMode = _vm->_mode;
 
-void Spells::dragonSleep() { error("TODO: spell"); }
+	int charIndex = SpellOnWho::show(_vm, MS_FirstAid);
+	if (charIndex == -1)
+		return;
 
-void Spells::elementalStorm() { error("TODO: spell"); }
+	Character &c = combat._combatMode == 2 ? *combat._combatParty[charIndex] :
+		party._activeParty[charIndex];
+	ItemsDialog::show(_vm, &c, ITEMMODE_ENCHANT);
 
-void Spells::enchantItem() { error("TODO: spell"); }
+	_vm->_mode = oldMode;
+}
 
 void Spells::energyBlast() {
 	Combat &combat = *_vm->_combat;
@@ -342,15 +585,67 @@ void Spells::energyBlast() {
 	combat.multiAttack(13);
 }
 
-void Spells::etherialize() { error("TODO: spell"); }		// Not while engaged
+void Spells::etherialize() {
+	Map &map = *_vm->_map;
+	Party &party = *_vm->_party;
+	SoundManager &sound = *_vm->_sound;
+	Common::Point pt = party._mazePosition + Common::Point(
+		SCREEN_POSITIONING_X[party._mazeDirection][7],
+		SCREEN_POSITIONING_Y[party._mazeDirection][7]
+	);
 
-void Spells::fantasticFreeze() { error("TODO: spell"); }
+	if ((map.mazeData()._mazeFlags & RESTRICTION_ETHERIALIZE) ||
+			map.mazeLookup(pt, 0, 0xffff) == INVALID_CELL) {
+		spellFailed();
+	} else {
+		party._mazePosition = pt;
+		sound.playFX(51);
+	}
+}
 
-void Spells::fieryFlail() { error("TODO: spell"); }
+void Spells::fantasticFreeze() {
+	Combat &combat = *_vm->_combat;
+	SoundManager &sound = *_vm->_sound;
 
-void Spells::fingerOfDeath() { error("TODO: spell"); }
+	combat._monsterDamage = 40;
+	combat._damageType = DT_COLD;
+	combat._rangeType = RT_GROUP;
+	sound.playFX(15);
+	combat.multiAttack(8);
+}
+
+void Spells::fieryFlail() {
+	Combat &combat = *_vm->_combat;
+	SoundManager &sound = *_vm->_sound;
+
+	combat._monsterDamage = 100;
+	combat._damageType = DT_FIRE;
+	combat._rangeType = RT_SINGLE;
+	sound.playFX(13);
+	combat.multiAttack(2);
+}
+
+void Spells::fingerOfDeath() {
+	Combat &combat = *_vm->_combat;
+	SoundManager &sound = *_vm->_sound;
 
-void Spells::fireball() { error("TODO: spell"); }
+	combat._monsterDamage = 0;
+	combat._damageType = DT_FINGEROFDEATH;
+	combat._rangeType = RT_GROUP;
+	sound.playFX(18);
+	combat.multiAttack(14);
+}
+
+void Spells::fireball() {
+	Combat &combat = *_vm->_combat;
+	SoundManager &sound = *_vm->_sound;
+
+	combat._monsterDamage = _vm->getRandomNumber(3, 7) * combat._oldCharacter->getCurrentLevel();
+	combat._damageType = DT_FIRE;
+	combat._rangeType = RT_GROUP;
+	sound.playFX(13);
+	combat.multiAttack(0);
+}
 
 void Spells::firstAid() {
 	Combat &combat = *_vm->_combat;
@@ -384,29 +679,132 @@ void Spells::flyingFist() {
 	combat.multiAttack(14);
 }
 
-void Spells::frostbite() { error("TODO: spell"); }
+void Spells::frostbite() {
+	Combat &combat = *_vm->_combat;
+	SoundManager &sound = *_vm->_sound;
 
-void Spells::golemStopper() { error("TODO: spell"); }
+	combat._monsterDamage = 35;
+	combat._damageType = DT_COLD;
+	combat._rangeType = RT_SINGLE;
+	sound.playFX(8);
+	combat.multiAttack(8);
+}
 
-void Spells::heroism() { error("TODO: spell"); }
+void Spells::golemStopper() {
+	Combat &combat = *_vm->_combat;
+	SoundManager &sound = *_vm->_sound;
 
-void Spells::holyBonus() { error("TODO: spell"); }
+	combat._monsterDamage = 0;
+	combat._damageType = DT_GOLEMSTOPPER;
+	combat._rangeType = RT_SINGLE;
+	sound.playFX(16);
+	combat.multiAttack(6);
+}
 
-void Spells::holyWord() { error("TODO: spell"); }
+void Spells::heroism() {
+	Combat &combat = *_vm->_combat;
+	Party &party = *_vm->_party;
+	SoundManager &sound = *_vm->_sound;
 
-void Spells::hypnotize() { error("TODO: spell"); }
+	sound.playFX(30);
+	party._heroism = combat._oldCharacter->getCurrentLevel();
+}
+
+void Spells::holyBonus() {
+	Combat &combat = *_vm->_combat;
+	Party &party = *_vm->_party;
+	SoundManager &sound = *_vm->_sound;
+
+	sound.playFX(30);
+	party._holyBonus = combat._oldCharacter->getCurrentLevel();
+}
+
+void Spells::holyWord() {
+	Combat &combat = *_vm->_combat;
+	SoundManager &sound = *_vm->_sound;
+
+	combat._monsterDamage = 0;
+	combat._damageType = DT_HOLYWORD;
+	combat._rangeType = RT_GROUP;
+	sound.playFX(18);
+	combat.multiAttack(13);
+}
+
+void Spells::hypnotize() {
+	Combat &combat = *_vm->_combat;
+	SoundManager &sound = *_vm->_sound;
+
+	combat._monsterDamage = 0;
+	combat._damageType = DT_HYPNOTIZE;
+	combat._rangeType = RT_GROUP;
+	sound.playFX(18);
+	combat.multiAttack(7);
+}
 
 void Spells::identifyMonster() { error("TODO: spell"); }
 
-void Spells::implosion() { error("TODO: spell"); }
+void Spells::implosion() {
+	Combat &combat = *_vm->_combat;
+	SoundManager &sound = *_vm->_sound;
 
-void Spells::incinerate() { error("TODO: spell"); }
+	combat._monsterDamage = 1000;
+	combat._damageType = DT_ENERGY;
+	combat._rangeType = RT_SINGLE;
+	sound.playFX(18);
+	combat.multiAttack(6);
+}
 
-void Spells::inferno() { error("TODO: spell"); }
+void Spells::incinerate() {
+	Combat &combat = *_vm->_combat;
+	SoundManager &sound = *_vm->_sound;
 
-void Spells::insectSpray() { error("TODO: spell"); }
+	combat._monsterDamage = 250;
+	combat._damageType = DT_FIRE;
+	combat._rangeType = RT_SINGLE;
+	sound.playFX(22);
+	combat.multiAttack(1);
+}
 
-void Spells::itemToGold() { error("TODO: spell"); }
+void Spells::inferno() {
+	Combat &combat = *_vm->_combat;
+	SoundManager &sound = *_vm->_sound;
+
+	combat._monsterDamage = 250;
+	combat._damageType = DT_FIRE;
+	combat._rangeType = RT_GROUP;
+	sound.playFX(13);
+	combat.multiAttack(1);
+}
+
+void Spells::insectSpray() {
+	Combat &combat = *_vm->_combat;
+	SoundManager &sound = *_vm->_sound;
+
+	combat._monsterDamage = 0;
+	combat._damageType = DT_INSECT_SPRAY;
+	combat._rangeType = RT_GROUP;
+	sound.playFX(17);
+	combat.multiAttack(10);
+}
+
+void Spells::itemToGold() {
+	Combat &combat = *_vm->_combat;
+	Party &party = *_vm->_party;
+
+	int charIndex = SpellOnWho::show(_vm, MS_Revitalize);
+	if (charIndex == -1)
+		return;
+
+	Character &c = combat._combatMode == 2 ? *combat._combatParty[charIndex] :
+		party._activeParty[charIndex];
+	Mode oldMode = _vm->_mode;
+	_vm->_mode = MODE_FF;
+
+	_vm->_screen->_windows[11].close();
+	ItemsDialog::show(_vm, &c, ITEMMODE_TO_GOLD);
+
+	_vm->_mode = oldMode;
+}
 
 void Spells::jump() {
 	Map &map = *_vm->_map;
@@ -446,7 +844,10 @@ void Spells::jump() {
 	spellFailed();
 }
 
-void Spells::levitate() { error("TODO: spell"); }
+void Spells::levitate() {
+	_vm->_party->_levitateActive = true;
+	_vm->_sound->playFX(20);
+}
 
 void Spells::light() { 
 	Interface &intf = *_vm->_interface;
@@ -459,9 +860,25 @@ void Spells::light() {
 	sound.playFX(39);
 }
 
-void Spells::lightningBolt() { error("TODO: spell"); }
+void Spells::lightningBolt() {
+	Combat &combat = *_vm->_combat;
+	SoundManager &sound = *_vm->_sound;
+
+	combat._monsterDamage = _vm->getRandomNumber(4, 6) * combat._oldCharacter->getCurrentLevel();
+	combat._damageType = DT_ELECTRICAL;
+	combat._rangeType = RT_GROUP;
+	sound.playFX(14);
+	combat.multiAttack(3);
+}
 
-void Spells::lloydsBeacon() { error("TODO: spell"); }	// Not while engaged
+void Spells::lloydsBeacon() {
+	if (_vm->_map->mazeData()._mazeFlags & RESTRICTION_LLOYDS_BEACON) {
+		spellFailed();
+	} else {
+		if (!LloydsBeacon::show(_vm))
+			spellFailed();
+	}
+}
 
 void Spells::magicArrow() { 
 	Combat &combat = *_vm->_combat;
@@ -471,13 +888,68 @@ void Spells::magicArrow() {
 	combat.multiAttack(11);
 }
 
-void Spells::massDistortion() { error("TODO: spell"); }
+void Spells::massDistortion() {
+	Combat &combat = *_vm->_combat;
+	SoundManager &sound = *_vm->_sound;
+
+	combat._monsterDamage = 0;
+	combat._damageType = DT_MASS_DISTORTION;
+	combat._rangeType = RT_GROUP;
+	sound.playFX(18);
+	combat.multiAttack(6);
+}
+
+void Spells::megaVolts() {
+	Combat &combat = *_vm->_combat;
+	SoundManager &sound = *_vm->_sound;
+
+	combat._monsterDamage = 150;
+	combat._damageType = DT_ELECTRICAL;
+	combat._rangeType = RT_GROUP;
+	sound.playFX(14);
+	combat.multiAttack(4);
+}
+
+void Spells::moonRay() {
+	Combat &combat = *_vm->_combat;
+	Interface &intf = *_vm->_interface;
+	Party &party = *_vm->_party;
+	SoundManager &sound = *_vm->_sound;
+
+	combat._monsterDamage = 30;
+	combat._damageType = DT_ENERGY;
+	combat._rangeType = RT_ALL;
+	sound.playFX(16);
+	combat.multiAttack(13);
+
+	for (uint idx = 0; idx < party._activeParty.size(); ++idx) {
+		sound.playFX(30);
+		party._activeParty[idx].addHitPoints(_vm->getRandomNumber(1, 30));
+	}
+
+	intf.drawParty(true);
+}
+
+void Spells::naturesCure() {
+	Combat &combat = *_vm->_combat;
+	Interface &intf = *_vm->_interface;
+	Party &party = *_vm->_party;
+	SoundManager &sound = *_vm->_sound;
 
-void Spells::megaVolts() { error("TODO: spell"); }
+	int charIndex = SpellOnWho::show(_vm, MS_Revitalize);
+	if (charIndex == -1)
+		return;
 
-void Spells::moonRay() { error("TODO: spell"); }
+	Character &c = combat._combatMode == 2 ? *combat._combatParty[charIndex] :
+		party._activeParty[charIndex];
 
-void Spells::naturesCure() { error("TODO: spell"); }
+	if (c.isDead()) {
+		spellFailed();
+	} else {
+		sound.playFX(30);
+		c.addHitPoints(25);
+	}
+}
 
 void Spells::pain() {
 	Combat &combat = *_vm->_combat;
@@ -490,9 +962,20 @@ void Spells::pain() {
 	combat.multiAttack(14);
 }
 
-void Spells::poisonVolley() { error("TODO: spell"); }
+void Spells::poisonVolley() {
+	Combat &combat = *_vm->_combat;
+	SoundManager &sound = *_vm->_sound;
+
+	combat._monsterDamage = 10;
+	combat._damageType = DT_POISON_VOLLEY;
+	combat._rangeType = RT_ALL;
+	sound.playFX(49);
+	combat.multiAttack(11);
+}
 
-void Spells::powerCure() { error("TODO: spell"); }
+void Spells::powerCure() {
+	
+}
 
 void Spells::powerShield() { error("TODO: spell"); }
 


Commit: c6506b567c791c6ef9a80df01f666c2c6d6d4b48
    https://github.com/scummvm/scummvm/commit/c6506b567c791c6ef9a80df01f666c2c6d6d4b48
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-03-01T10:07:03-05:00

Commit Message:
XEEN: Implemented more spells

Changed paths:
    engines/xeen/dialogs_spells.cpp
    engines/xeen/dialogs_spells.h
    engines/xeen/map.h
    engines/xeen/resources.cpp
    engines/xeen/resources.h
    engines/xeen/spells.cpp



diff --git a/engines/xeen/dialogs_spells.cpp b/engines/xeen/dialogs_spells.cpp
index f535776..eb73733 100644
--- a/engines/xeen/dialogs_spells.cpp
+++ b/engines/xeen/dialogs_spells.cpp
@@ -21,6 +21,7 @@
  */
 
 #include "xeen/dialogs_spells.h"
+#include "xeen/dialogs_input.h"
 #include "xeen/dialogs_query.h"
 #include "xeen/resources.h"
 #include "xeen/spells.h"
@@ -579,12 +580,18 @@ void CastSpell::loadButtons() {
 
 /*------------------------------------------------------------------------*/
 
-int SpellOnWho::show(XeenEngine *vm, int spellId) {
+Character *SpellOnWho::show(XeenEngine *vm, int spellId) {
 	SpellOnWho *dlg = new SpellOnWho(vm);
 	int result = dlg->execute(spellId);
 	delete dlg;
 
-	return result;
+	if (result == -1)
+		return nullptr;
+	
+	Combat &combat = *vm->_combat;
+	Party &party = *vm->_party;
+	return combat._combatMode == 2 ? combat._combatParty[result] :
+		&party._activeParty[result];
 }
 
 int SpellOnWho::execute(int spellId) {
@@ -773,7 +780,6 @@ bool LloydsBeacon::execute() {
 	Party &party = *_vm->_party;
 	Screen &screen = *_vm->_screen;
 	SoundManager &sound = *_vm->_sound;
-	Spells &spells = *_vm->_spells;
 	Window &w = screen._windows[10];
 	bool isDarkCc = _vm->_files->_isDarkCc;
 	Character &c = *combat._oldCharacter;
@@ -863,4 +869,108 @@ void LloydsBeacon::loadButtons() {
 	addButton(Common::Rect(242, 108, 266, 128), Common::KEYCODE_t, &_iconSprites);
 }
 
+/*------------------------------------------------------------------------*/
+
+int Teleport::show(XeenEngine *vm) {
+	Teleport *dlg = new Teleport(vm);
+	int result = dlg->execute();
+	delete dlg;
+
+	return result;
+}
+
+int Teleport::execute() {
+	Map &map = *_vm->_map;
+	Party &party = *_vm->_party;
+	Screen &screen = *_vm->_screen;
+	Window &w = screen._windows[6];
+	Common::String num;
+
+	w.open();
+	w.writeString(Common::String::format(HOW_MANY_SQUARES,
+		DIRECTION_TEXT[party._mazeDirection]));
+	w.update();
+	int lineSize = Input::show(_vm, &w, num, 1, 200, true);
+	w.close();
+
+	if (!lineSize)
+		return -1;
+	int numSquares = atoi(num.c_str());
+	Common::Point pt = party._mazePosition;
+	int v;
+
+	switch (party._mazeDirection) {
+	case DIR_NORTH:
+		pt.y += numSquares;
+		break;
+	case DIR_EAST:
+		pt.x += numSquares;
+		break;
+	case DIR_SOUTH:
+		pt.y -= numSquares;
+		break;
+	case DIR_WEST:
+		pt.x -= numSquares;
+		break;
+	}
+
+	v = map.mazeLookup(pt, map._isOutdoors ? 0xF : 0xFFFF, 0);
+
+	if ((v != (map._isOutdoors ? 0 : INVALID_CELL)) &&
+		(!map._isOutdoors || v == SURFTYPE_DWATER)) {
+		party._mazePosition = pt;
+		return 1;
+	} else {
+		return 0;
+	}
+}
+
+/*------------------------------------------------------------------------*/
+
+int TownPortal::show(XeenEngine *vm) {
+	TownPortal *dlg = new TownPortal(vm);
+	int townNumber = dlg->execute();
+	delete dlg;
+
+	return townNumber;
+}
+
+int TownPortal::execute() {
+	Map &map = *_vm->_map;
+	Screen &screen = *_vm->_screen;
+	Window &w = screen._windows[20];
+	Common::String townNames[5];
+	Mode oldMode = _vm->_mode;
+	_vm->_mode = MODE_FF;
+
+	// Build up a lsit of the names of the towns on the current side of Xeen
+	for (int idx = 0; idx < 5; ++idx) {
+		File f(Common::String::format("%s%04d.txt",
+			map._sideTownPortal ? "dark" : "xeen",
+			TOWN_MAP_NUMBERS[map._sideTownPortal][idx]));
+		townNames[idx] = f.readString();
+		f.close();
+	}
+
+	w.open();
+	w.writeString(Common::String::format(TOWN_PORTAL,
+		townNames[0].c_str(), townNames[1].c_str(), townNames[2].c_str(),
+		townNames[3].c_str(), townNames[4].c_str()
+	));
+	w.update();
+	
+	// Get the town number
+	int townNumber;
+	Common::String num;
+	do {
+		int result = Input::show(_vm, &w, num, 1, 160, true);
+		townNumber = !result ? 0 : atoi(num.c_str());
+	} while (townNumber > 5);
+
+	w.close();
+	_vm->_mode = oldMode;
+
+	return townNumber;
+}
+
 } // End of namespace Xeen
diff --git a/engines/xeen/dialogs_spells.h b/engines/xeen/dialogs_spells.h
index ca7bb17..9f4af15 100644
--- a/engines/xeen/dialogs_spells.h
+++ b/engines/xeen/dialogs_spells.h
@@ -81,7 +81,7 @@ private:
 
 	int execute(int spellId);
 public:
-	static int show(XeenEngine *vm, int spellId);
+	static Character *show(XeenEngine *vm, int spellId);
 };
 
 class SelectElement : public ButtonContainer {
@@ -123,6 +123,29 @@ public:
 	static bool show(XeenEngine *vm);
 };
 
+class Teleport : public ButtonContainer {
+private:
+	XeenEngine *_vm;
+	SpriteResource _iconSprites;
+
+	Teleport(XeenEngine *vm) : ButtonContainer(), _vm(vm) {}
+
+	int execute();
+public:
+	static int show(XeenEngine *vm);
+};
+
+class TownPortal : public ButtonContainer {
+private:
+	XeenEngine *_vm;
+
+	TownPortal(XeenEngine *vm) : ButtonContainer(), _vm(vm) {}
+
+	int execute();
+public:
+	static int show(XeenEngine *vm);
+};
+
 } // End of namespace Xeen
 
 #endif /* XEEN_DIALOGS_SPELLS_H */
diff --git a/engines/xeen/map.h b/engines/xeen/map.h
index bfc09ec..a7e88c1 100644
--- a/engines/xeen/map.h
+++ b/engines/xeen/map.h
@@ -356,7 +356,6 @@ private:
 	XeenEngine *_vm;
 	MazeData _mazeData[9];
 	SpriteResource _wallPicSprites;
-	int _sideTownPortal;
 	int _sidePictures;
 	int _sideObjects;
 	int _sideMonsters;
@@ -387,6 +386,7 @@ public:
 	int _currentSurfaceId;
 	bool _currentSteppedOn;
 	bool _loadDarkSide;
+	int _sideTownPortal;
 public:
 	Map(XeenEngine *vm);
 
diff --git a/engines/xeen/resources.cpp b/engines/xeen/resources.cpp
index a75f77b..085cfab 100644
--- a/engines/xeen/resources.cpp
+++ b/engines/xeen/resources.cpp
@@ -1554,4 +1554,22 @@ const char *const LLOYDS_BEACON =
 	"%s\x3l\n"
 	"x = %d\x3r\t000y = %d\x3""c\x2\v122\t021\f15S\fdet\t060\f15R\fdeturn\x1";
 
+const char *const HOW_MANY_SQUARES = "\x03cTeleport\nHow many squares %s (1-9)";
+
+const char *const TOWN_PORTAL =
+	"\x3""cTown Portal\x3l\n"
+	"\n"
+	"\t0101. %s\n"
+	"\t0102. %s\n"
+	"\t0103. %s\n"
+	"\t0104. %s\n"
+	"\t0105. %s\x3""c\n"
+	"\n"
+	"To which Town (1-5)\n"
+	"\n";
+
+const int TOWN_MAP_NUMBERS[2][5] = {
+	{ 28, 29, 30, 31, 32 }, { 29, 31, 33, 35, 37 }
+};
+
 } // End of namespace Xeen
diff --git a/engines/xeen/resources.h b/engines/xeen/resources.h
index 89dc74a..29e8611 100644
--- a/engines/xeen/resources.h
+++ b/engines/xeen/resources.h
@@ -550,6 +550,12 @@ extern const char *const DETECT_MONSTERS;
 
 extern const char *const LLOYDS_BEACON;
 
+extern const char *const HOW_MANY_SQUARES;
+
+extern const char *const TOWN_PORTAL;
+
+extern const int TOWN_MAP_NUMBERS[2][5];
+
 } // End of namespace Xeen
 
 #endif	/* XEEN_RESOURCES_H */
diff --git a/engines/xeen/spells.cpp b/engines/xeen/spells.cpp
index e3978ae..e2e8cfd 100644
--- a/engines/xeen/spells.cpp
+++ b/engines/xeen/spells.cpp
@@ -331,79 +331,59 @@ void Spells::createFood() {
 }
 
 void Spells::cureDisease() {
-	Combat &combat = *_vm->_combat;
 	Interface &intf = *_vm->_interface;
-	Party &party = *_vm->_party;
 	SoundManager &sound = *_vm->_sound;
 
-	int charIndex = SpellOnWho::show(_vm, MS_Revitalize);
-	if (charIndex == -1)
+	Character *c = SpellOnWho::show(_vm, MS_CureDisease);
+	if (!c)
 		return;
 
-	Character &c = combat._combatMode == 2 ? *combat._combatParty[charIndex] :
-		party._activeParty[charIndex];
-
 	sound.playFX(30);
-	c.addHitPoints(0);
-	c._conditions[DISEASED] = 0;
+	c->addHitPoints(0);
+	c->_conditions[DISEASED] = 0;
 	intf.drawParty(true);
 }
 
 void Spells::cureParalysis() {
-	Combat &combat = *_vm->_combat;
 	Interface &intf = *_vm->_interface;
-	Party &party = *_vm->_party;
 	SoundManager &sound = *_vm->_sound;
 
-	int charIndex = SpellOnWho::show(_vm, MS_Revitalize);
-	if (charIndex == -1)
+	Character *c = SpellOnWho::show(_vm, MS_CureParalysis);
+	if (!c)
 		return;
 
-	Character &c = combat._combatMode == 2 ? *combat._combatParty[charIndex] :
-		party._activeParty[charIndex];
-
 	sound.playFX(30);
-	c.addHitPoints(0);
-	c._conditions[PARALYZED] = 0;
+	c->addHitPoints(0);
+	c->_conditions[PARALYZED] = 0;
 	intf.drawParty(true);
 }
 
 void Spells::curePoison() {
-	Combat &combat = *_vm->_combat;
 	Interface &intf = *_vm->_interface;
-	Party &party = *_vm->_party;
 	SoundManager &sound = *_vm->_sound;
 
-	int charIndex = SpellOnWho::show(_vm, MS_Revitalize);
-	if (charIndex == -1)
+	Character *c = SpellOnWho::show(_vm, MS_CurePoison);
+	if (!c)
 		return;
 
-	Character &c = combat._combatMode == 2 ? *combat._combatParty[charIndex] :
-		party._activeParty[charIndex];
-
 	sound.playFX(30);
-	c.addHitPoints(0);
-	c._conditions[POISONED] = 0;
+	c->addHitPoints(0);
+	c->_conditions[POISONED] = 0;
 	intf.drawParty(true);
 }
 
 void Spells::cureWounds() {
-	Combat &combat = *_vm->_combat;
-	Party &party = *_vm->_party;
 	SoundManager &sound = *_vm->_sound;
 
-	int charIndex = SpellOnWho::show(_vm, MS_Revitalize);
-	if (charIndex == -1)
+	Character *c = SpellOnWho::show(_vm, MS_CureWounds);
+	if (!c)
 		return;
 
-	Character &c = combat._combatMode == 2 ? *combat._combatParty[charIndex] :
-		party._activeParty[charIndex];
-
-	if (c.isDead()) {
+	if (c->isDead()) {
 		spellFailed();
 	} else {
 		sound.playFX(30);
-		c.addHitPoints(15);
+		c->addHitPoints(15);
 	}
 }
 
@@ -559,17 +539,13 @@ void Spells::elementalStorm() {
 }
 
 void Spells::enchantItem() {
-	Combat &combat = *_vm->_combat;
-	Party &party = *_vm->_party;
 	Mode oldMode = _vm->_mode;
 
-	int charIndex = SpellOnWho::show(_vm, MS_FirstAid);
-	if (charIndex == -1)
+	Character *c = SpellOnWho::show(_vm, MS_EnchantItem);
+	if (!c)
 		return;
 
-	Character &c = combat._combatMode == 2 ? *combat._combatParty[charIndex] :
-		party._activeParty[charIndex];
-	ItemsDialog::show(_vm, &c, ITEMMODE_ENCHANT);
+	ItemsDialog::show(_vm, c, ITEMMODE_ENCHANT);
 
 	_vm->_mode = oldMode;
 }
@@ -648,23 +624,17 @@ void Spells::fireball() {
 }
 
 void Spells::firstAid() {
-	Combat &combat = *_vm->_combat;
-	Party &party = *_vm->_party;
 	SoundManager &sound = *_vm->_sound;
 
-	int charIndex = SpellOnWho::show(_vm, MS_FirstAid);
-	if (charIndex == -1)
+	Character *c = SpellOnWho::show(_vm, MS_FirstAid);
+	if (!c)
 		return;
 
-	Character &c = combat._combatMode == 2 ? *combat._combatParty[charIndex] :
-		party._activeParty[charIndex];
-
-	if (c.isDead()) {
+	if (c->isDead()) {
 		spellFailed();
-	}
-	else {
+	} else {
 		sound.playFX(30);
-		c.addHitPoints(6);
+		c->addHitPoints(6);
 	}
 }
 
@@ -788,20 +758,15 @@ void Spells::insectSpray() {
 }
 
 void Spells::itemToGold() {
-	Combat &combat = *_vm->_combat;
-	Party &party = *_vm->_party;
-
-	int charIndex = SpellOnWho::show(_vm, MS_Revitalize);
-	if (charIndex == -1)
+	Character *c = SpellOnWho::show(_vm, MS_ItemToGold);
+	if (!c)
 		return;
 
-	Character &c = combat._combatMode == 2 ? *combat._combatParty[charIndex] :
-		party._activeParty[charIndex];
 	Mode oldMode = _vm->_mode;
 	_vm->_mode = MODE_FF;
 
 	_vm->_screen->_windows[11].close();
-	ItemsDialog::show(_vm, &c, ITEMMODE_TO_GOLD);
+	ItemsDialog::show(_vm, c, ITEMMODE_TO_GOLD);
 
 	_vm->_mode = oldMode;
 }
@@ -931,23 +896,17 @@ void Spells::moonRay() {
 }
 
 void Spells::naturesCure() {
-	Combat &combat = *_vm->_combat;
-	Interface &intf = *_vm->_interface;
-	Party &party = *_vm->_party;
 	SoundManager &sound = *_vm->_sound;
 
-	int charIndex = SpellOnWho::show(_vm, MS_Revitalize);
-	if (charIndex == -1)
+	Character *c = SpellOnWho::show(_vm, MS_NaturesCure);
+	if (!c)
 		return;
 
-	Character &c = combat._combatMode == 2 ? *combat._combatParty[charIndex] :
-		party._activeParty[charIndex];
-
-	if (c.isDead()) {
+	if (c->isDead()) {
 		spellFailed();
 	} else {
 		sound.playFX(30);
-		c.addHitPoints(25);
+		c->addHitPoints(25);
 	}
 }
 
@@ -974,12 +933,39 @@ void Spells::poisonVolley() {
 }
 
 void Spells::powerCure() {
-	
+	SoundManager &sound = *_vm->_sound;
+
+	Character *c = SpellOnWho::show(_vm, MS_PowerCure);
+	if (!c)
+		return;
+
+	if (c->isDead()) {
+		spellFailed();
+	} else {
+		sound.playFX(30);
+		c->addHitPoints(_vm->getRandomNumber(2, 12) * _vm->_combat->_oldCharacter->getCurrentLevel());
+	}
+}
+
+void Spells::powerShield() {
+	Combat &combat = *_vm->_combat;
+	Party &party = *_vm->_party;
+	SoundManager &sound = *_vm->_sound;
+
+	sound.playFX(20);
+	party._powerShield = combat._oldCharacter->getCurrentLevel();
 }
 
-void Spells::powerShield() { error("TODO: spell"); }
+void Spells::prismaticLight() {
+	Combat &combat = *_vm->_combat;
+	SoundManager &sound = *_vm->_sound;
 
-void Spells::prismaticLight() { error("TODO: spell"); }
+	combat._monsterDamage = 80;
+	combat._damageType = (DamageType)_vm->getRandomNumber(DT_PHYSICAL, DT_ENERGY);
+	combat._rangeType = RT_ALL;
+	sound.playFX(18);
+	combat.multiAttack(14);
+}
 
 void Spells::protectionFromElements() {
 	Combat &combat = *_vm->_combat;
@@ -1013,32 +999,91 @@ void Spells::protectionFromElements() {
 	}
 }
 
-void Spells::raiseDead() { error("TODO: spell"); }
+void Spells::raiseDead() {
+	Interface &intf = *_vm->_interface;
+	SoundManager &sound = *_vm->_sound;
 
-void Spells::rechargeItem() { error("TODO: spell"); }
+	Character *c = SpellOnWho::show(_vm, MS_RaiseDead);
+	if (!c)
+		return;
 
-void Spells::resurrection() { error("TODO: spell"); }
+	if (!c->_conditions[DEAD]) {
+		spellFailed();
+	} else {
+		c->_conditions[DEAD] = 0;
+		c->_conditions[UNCONSCIOUS] = 0;
+		c->_currentHp = 0;
+		sound.playFX(30);
+		c->addHitPoints(1);
+		if (--c->_endurance._permanent < 1)
+			c->_endurance._permanent = 1;
 
-void Spells::revitalize() {
-	Combat &combat = *_vm->_combat;
+		intf.drawParty(true);
+	}
+}
+
+void Spells::rechargeItem() {
+	Mode oldMode = _vm->_mode;
+
+	Character *c = SpellOnWho::show(_vm, MS_RechargeItem);
+	if (!c)
+		return;
+
+	ItemsDialog::show(_vm, c, ITEMMODE_RECHARGE);
+	_vm->_mode = oldMode;
+}
+
+void Spells::resurrection() {
 	Interface &intf = *_vm->_interface;
-	Party &party = *_vm->_party;
 	SoundManager &sound = *_vm->_sound;
 
-	int charIndex = SpellOnWho::show(_vm, MS_Revitalize);
-	if (charIndex == -1)
+	Character *c = SpellOnWho::show(_vm, MS_RaiseDead);
+	if (!c)
 		return;
 
-	Character &c = combat._combatMode == 2 ? *combat._combatParty[charIndex] :
-		party._activeParty[charIndex];
+	if (!c->_conditions[ERADICATED]) {
+		spellFailed();
+		sound.playFX(30);
+	} else {
+		sound.playFX(30);
+		c->addHitPoints(0);
+		c->_conditions[ERADICATED] = 0;
+		
+		if (--c->_endurance._permanent < 1)
+			c->_endurance._permanent = 1;
+		if ((c->_tempAge + 5) >= 250)
+			c->_tempAge = 250;
+		else
+			c->_tempAge += 5;
+
+		intf.drawParty(true);
+	}
+}
+
+void Spells::revitalize() {
+	Interface &intf = *_vm->_interface;
+	SoundManager &sound = *_vm->_sound;
+
+	Character *c = SpellOnWho::show(_vm, MS_Revitalize);
+	if (!c)
+		return;
 
 	sound.playFX(30);
-	c.addHitPoints(0);
-	c._conditions[WEAK] = 0;
+	c->addHitPoints(0);
+	c->_conditions[WEAK] = 0;
 	intf.drawParty(true);
 }
 
-void Spells::shrapMetal() { error("TODO: spell"); }
+void Spells::shrapMetal() {
+	Combat &combat = *_vm->_combat;
+	SoundManager &sound = *_vm->_sound;
+
+	combat._monsterDamage = combat._oldCharacter->getCurrentLevel() * 2;
+	combat._damageType = DT_PHYSICAL;
+	combat._rangeType = RT_GROUP;
+	sound.playFX(16);
+	combat.multiAttack(15);
+}
 
 void Spells::sleep() {
 	Combat &combat = *_vm->_combat;
@@ -1062,47 +1107,182 @@ void Spells::sparks() {
 	combat.multiAttack(5);
 }
 
-void Spells::starBurst() { error("TODO: spell"); }
+void Spells::starBurst() {
+	Combat &combat = *_vm->_combat;
+	SoundManager &sound = *_vm->_sound;
 
-void Spells::stoneToFlesh() { error("TODO: spell"); }
+	combat._monsterDamage = 500;
+	combat._damageType = DT_FIRE;
+	combat._rangeType = RT_ALL;
+	sound.playFX(13);
+	combat.multiAttack(15);
+}
 
-void Spells::sunRay() { error("TODO: spell"); }
+void Spells::stoneToFlesh() {
+	Interface &intf = *_vm->_interface;
+	SoundManager &sound = *_vm->_sound;
 
-void Spells::superShelter() { error("TODO: spell"); }
+	Character *c = SpellOnWho::show(_vm, MS_StoneToFlesh);
+	if (!c)
+		return;
 
-void Spells::suppressDisease() { error("TODO: spell"); }
+	sound.playFX(30);
+	c->addHitPoints(0);
+	c->_conditions[STONED] = 0;
+	intf.drawParty(true);
+}
 
-void Spells::suppressPoison() {
+void Spells::sunRay() {
 	Combat &combat = *_vm->_combat;
+	SoundManager &sound = *_vm->_sound;
+
+	combat._monsterDamage = 200;
+	combat._damageType = DT_ENERGY;
+	combat._rangeType = RT_ALL;
+	sound.playFX(16);
+	combat.multiAttack(13);
+}
+
+void Spells::superShelter() {
 	Interface &intf = *_vm->_interface;
-	Party &party = *_vm->_party;
+	Map &map = *_vm->_map;
 	SoundManager &sound = *_vm->_sound;
 
-	int charIndex = SpellOnWho::show(_vm, MS_FirstAid);
-	if (charIndex == -1)
+	if (map.mazeData()._mazeFlags & RESTRICTION_SUPER_SHELTER) {
+		spellFailed();
+	} else {
+		Mode oldMode = _vm->_mode;
+		_vm->_mode = MODE_12;
+		sound.playFX(30);
+		intf.rest();
+		_vm->_mode = oldMode;
+	}
+}
+
+void Spells::suppressDisease() {
+	Interface &intf = *_vm->_interface;
+	SoundManager &sound = *_vm->_sound;
+
+	Character *c = SpellOnWho::show(_vm, MS_SuppressDisease);
+	if (!c)
 		return;
 
-	Character &c = combat._combatMode == 2 ? *combat._combatParty[charIndex] :
-		party._activeParty[charIndex];
+	if (c->_conditions[DISEASED]) {
+		if (c->_conditions[DISEASED] >= 4)
+			c->_conditions[DISEASED] -= 3;
+		else
+			c->_conditions[DISEASED] = 1;
+
+		sound.playFX(20);
+		c->addHitPoints(0);
+		intf.drawParty(true);
+	}
+}
+
+void Spells::suppressPoison() {
+	Interface &intf = *_vm->_interface;
+	SoundManager &sound = *_vm->_sound;
+
+	Character *c = SpellOnWho::show(_vm, MS_FirstAid);
+	if (!c)
+		return;
 
-	if (c._conditions[POISONED]) {
-		if (c._conditions[POISONED] >= 4) {
-			c._conditions[POISONED] -= 2;
+	if (c->_conditions[POISONED]) {
+		if (c->_conditions[POISONED] >= 4) {
+			c->_conditions[POISONED] -= 2;
 		} else {
-			c._conditions[POISONED] = 1;
+			c->_conditions[POISONED] = 1;
 		}
 	}
 
 	sound.playFX(20);
-	c.addHitPoints(0);
+	c->addHitPoints(0);
 	intf.drawParty(1);
 }
 
-void Spells::teleport() { error("TODO: spell"); }		// Not while engaged
+void Spells::teleport() {
+	Map &map = *_vm->_map;
+	SoundManager &sound = *_vm->_sound;
 
-void Spells::timeDistortion() { error("TODO: spell"); }
+	if (map.mazeData()._mazeFlags & RESTRICTION_TELPORT) {
+		spellFailed();
+	} else {
+		switch (Teleport::show(_vm)) {
+		case 0:
+			spellFailed();
+			break;
+		case 1:
+			sound.playFX(51);
+			break;
+		default:
+			break;
+		}
+	}
+}
+
+void Spells::timeDistortion() {
+	Interface &intf = *_vm->_interface;
+	Map &map = *_vm->_map;
+	Party &party = *_vm->_party;
+	SoundManager &sound = *_vm->_sound;
+
+	if (map.mazeData()._mazeFlags & RESTRICTION_TIME_DISTORTION) {
+		spellFailed();
+	} else {
+		party.moveToRunLocation();
+		sound.playFX(51);
+		intf.draw3d(true);
+	}
+}
+
+void Spells::townPortal() {
+	Map &map = *_vm->_map;
+	Party &party = *_vm->_party;
+	SoundManager &sound = *_vm->_sound;
+
+	if (map.mazeData()._mazeFlags & RESTRICTION_TOWN_PORTAL) {
+		spellFailed();
+		return;
+	} 
+
+	int townNumber = TownPortal::show(_vm);
+	if (!townNumber)
+		return;
+	
+	sound.playFX(51);
+	map._loadDarkSide = map._sideTownPortal;
+	_vm->_files->_isDarkCc = map._sideTownPortal > 0;
+	map.load(TOWN_MAP_NUMBERS[map._sideTownPortal][townNumber - 1]);
 
-void Spells::townPortal() { error("TODO: spell"); }		// Not while engaged
+	if (!_vm->_files->_isDarkCc) {
+		party.moveToRunLocation();
+	} else {
+		switch (townNumber) {
+		case 1:
+			party._mazePosition = Common::Point(14, 11);
+			party._mazeDirection = DIR_SOUTH;
+			break;
+		case 2:
+			party._mazePosition = Common::Point(5, 12);
+			party._mazeDirection = DIR_WEST;
+			break;
+		case 3:
+			party._mazePosition = Common::Point(2, 15);
+			party._mazeDirection = DIR_EAST;
+			break;
+		case 4:
+			party._mazePosition = Common::Point(8, 11);
+			party._mazeDirection = DIR_NORTH;
+			break;
+		case 5:
+			party._mazePosition = Common::Point(2, 6);
+			party._mazeDirection = DIR_NORTH;
+			break;
+		default:
+			break;
+		}
+	}
+}
 
 void Spells::toxicCloud() {
 	Combat &combat = *_vm->_combat;
@@ -1126,9 +1306,22 @@ void Spells::turnUndead() {
 	combat.multiAttack(13);
 }
 
-void Spells::walkOnWater() { error("TODO: spell"); }
+void Spells::walkOnWater() {
+	Party &party = *_vm->_party;
+	SoundManager &sound = *_vm->_sound;
+
+	party._walkOnWaterActive = true;
+	sound.playFX(20);
+}
+
+void Spells::wizardEye() {
+	Party &party = *_vm->_party;
+	SoundManager &sound = *_vm->_sound;
 
-void Spells::wizardEye() { error("TODO: spell"); }		// Not while engaged
+	party._wizardEyeActive = true;
+	party._automapOn = false;
+	sound.playFX(20);
+}
 
 void Spells::frostbite2() {
 	Combat &combat = *_vm->_combat;


Commit: ee5b8ed59f1aaa00767ac3805d7ab63dd5a5f5d4
    https://github.com/scummvm/scummvm/commit/ee5b8ed59f1aaa00767ac3805d7ab63dd5a5f5d4
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-03-01T10:41:11-05:00

Commit Message:
XEEN: Implement remaining spells

Changed paths:
    engines/xeen/dialogs_spells.cpp
    engines/xeen/dialogs_spells.h
    engines/xeen/resources.cpp
    engines/xeen/resources.h
    engines/xeen/spells.cpp
    engines/xeen/xeen.cpp
    engines/xeen/xeen.h



diff --git a/engines/xeen/dialogs_spells.cpp b/engines/xeen/dialogs_spells.cpp
index eb73733..f49dca6 100644
--- a/engines/xeen/dialogs_spells.cpp
+++ b/engines/xeen/dialogs_spells.cpp
@@ -973,4 +973,56 @@ int TownPortal::execute() {
 	return townNumber;
 }
 
+/*------------------------------------------------------------------------*/
+
+void IdentifyMonster::show(XeenEngine *vm) {
+	IdentifyMonster *dlg = new IdentifyMonster(vm);
+	dlg->execute();
+	delete dlg;
+}
+
+void IdentifyMonster::execute() {
+	Combat &combat = *_vm->_combat;
+	EventsManager &events = *_vm->_events;
+	Interface &intf = *_vm->_interface;
+	Map &map = *_vm->_map;
+	Screen &screen = *_vm->_screen;
+	SoundManager &sound = *_vm->_sound;
+	Spells &spells = *_vm->_spells;
+	Window &w = screen._windows[17];
+	Common::String monsterDesc[3];
+
+	for (int monIndex = 0; monIndex < 3; ++monIndex) {
+		if (combat._attackMonsters[monIndex] == -1)
+			continue;
+
+		MazeMonster &monster = map._mobData._monsters[combat._attackMonsters[monIndex]];
+		MonsterStruct &monsterData = *monster._monsterData;
+
+		monsterDesc[monIndex] = Common::String::format(MONSTER_DETAILS,
+			monsterData._name.c_str(),
+			_vm->printK2(monster._hp).c_str(),
+			monsterData._accuracy, monsterData._numberOfAttacks,
+			MONSTER_SPECIAL_ATTACKS[monsterData._specialAttack]
+		);
+	}
+
+	sound.playFX(20);
+	w.open();
+	w.writeString(Common::String::format(IDENTIFY_MONSTERS,
+		monsterDesc[0].c_str(), monsterDesc[1].c_str(), monsterDesc[2].c_str()));
+	w.update();
+
+	do {
+		events.updateGameCounter();
+		intf.draw3d(false);
+		w.frame();
+		screen._windows[3].update();
+
+		events.wait(1);
+	} while (!events.isKeyMousePressed());
+
+	w.close();
+}
+
 } // End of namespace Xeen
diff --git a/engines/xeen/dialogs_spells.h b/engines/xeen/dialogs_spells.h
index 9f4af15..35b2708 100644
--- a/engines/xeen/dialogs_spells.h
+++ b/engines/xeen/dialogs_spells.h
@@ -146,6 +146,17 @@ public:
 	static int show(XeenEngine *vm);
 };
 
+class IdentifyMonster : public ButtonContainer {
+private:
+	XeenEngine *_vm;
+
+	IdentifyMonster(XeenEngine *vm) : ButtonContainer(), _vm(vm) {}
+
+	void execute();
+public:
+	static void show(XeenEngine *vm);
+};
+
 } // End of namespace Xeen
 
 #endif /* XEEN_DIALOGS_SPELLS_H */
diff --git a/engines/xeen/resources.cpp b/engines/xeen/resources.cpp
index 085cfab..8bc99f6 100644
--- a/engines/xeen/resources.cpp
+++ b/engines/xeen/resources.cpp
@@ -1572,4 +1572,17 @@ const int TOWN_MAP_NUMBERS[2][5] = {
 	{ 28, 29, 30, 31, 32 }, { 29, 31, 33, 35, 37 }
 };
 
+const char *const MONSTER_DETAILS = 
+	"\x3l\n"
+	"%s\x3""c\t100%s\t140%u\t180%u\x3r\t000%s";
+
+const char *const MONSTER_SPECIAL_ATTACKS[23] = {
+	"None", "Magic", "Fire", "Elec", "Cold", "Poison", "Energy", "Disease",
+	"Insane", "Asleep", "CurseItm", "InLove", "DrnSPts", "Curse", "Paralys",
+	"Uncons", "Confuse", "BrkWpn", "Weak", "Erad", "Age+5", "Dead", "Stone"
+};
+
+const char *const IDENTIFY_MONSTERS =
+	"Name\x3""c\t100HP\t140AC\t177#Atks\x3r\t000Special%s%s%s";
+
 } // End of namespace Xeen
diff --git a/engines/xeen/resources.h b/engines/xeen/resources.h
index 29e8611..e15c509 100644
--- a/engines/xeen/resources.h
+++ b/engines/xeen/resources.h
@@ -556,6 +556,12 @@ extern const char *const TOWN_PORTAL;
 
 extern const int TOWN_MAP_NUMBERS[2][5];
 
+extern const char *const MONSTER_DETAILS;
+
+extern const char *const MONSTER_SPECIAL_ATTACKS[23];
+
+extern const char *const IDENTIFY_MONSTERS;
+
 } // End of namespace Xeen
 
 #endif	/* XEEN_RESOURCES_H */
diff --git a/engines/xeen/spells.cpp b/engines/xeen/spells.cpp
index e2e8cfd..ba4e78b 100644
--- a/engines/xeen/spells.cpp
+++ b/engines/xeen/spells.cpp
@@ -711,7 +711,16 @@ void Spells::hypnotize() {
 	combat.multiAttack(7);
 }
 
-void Spells::identifyMonster() { error("TODO: spell"); }
+void Spells::identifyMonster() {
+	Combat &combat = *_vm->_combat;
+
+	if (combat._attackMonsters[0] == -1 && combat._attackMonsters[1] == -1
+		&& combat._attackMonsters[2] == -1) {
+		spellFailed();
+	} else {
+		IdentifyMonster::show(_vm);
+	}
+}
 
 void Spells::implosion() {
 	Combat &combat = *_vm->_combat;
diff --git a/engines/xeen/xeen.cpp b/engines/xeen/xeen.cpp
index a1604a5..fb7edea 100644
--- a/engines/xeen/xeen.cpp
+++ b/engines/xeen/xeen.cpp
@@ -350,4 +350,9 @@ Common::String XeenEngine::printK(uint value) {
 		Common::String::format("%u", value);
 }
 
+Common::String XeenEngine::printK2(uint value) {
+	return (value > 999) ? Common::String::format("%uk", value / 1000) :
+		Common::String::format("%u", value);
+}
+
 } // End of namespace Xeen
diff --git a/engines/xeen/xeen.h b/engines/xeen/xeen.h
index 2d995a1..7185941 100644
--- a/engines/xeen/xeen.h
+++ b/engines/xeen/xeen.h
@@ -203,6 +203,8 @@ public:
 	static Common::String printMil(uint value);
 
 	static Common::String printK(uint value);
+
+	static Common::String printK2(uint value);
 };
 
 } // End of namespace Xeen


Commit: 8e6708e6008b3ac1132f84923ebc766d1b199679
    https://github.com/scummvm/scummvm/commit/8e6708e6008b3ac1132f84923ebc766d1b199679
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-03-01T21:58:58-05:00

Commit Message:
XEEN: Hook up debugger properly and implement spell command

Changed paths:
    engines/xeen/debugger.cpp
    engines/xeen/debugger.h
    engines/xeen/dialogs_error.cpp
    engines/xeen/dialogs_spells.cpp
    engines/xeen/events.cpp
    engines/xeen/resources.cpp



diff --git a/engines/xeen/debugger.cpp b/engines/xeen/debugger.cpp
index a83af9f..35cbaeb 100644
--- a/engines/xeen/debugger.cpp
+++ b/engines/xeen/debugger.cpp
@@ -25,7 +25,7 @@
 #include "xeen/debugger.h"
 
 namespace Xeen {
-/*
+
 static int strToInt(const char *s) {
 	if (!*s)
 		// No string at all
@@ -41,16 +41,43 @@ static int strToInt(const char *s) {
 		error("strToInt failed on string \"%s\"", s);
 	return (int)tmp;
 }
-*/
 
 /*------------------------------------------------------------------------*/
 
 Debugger::Debugger(XeenEngine *vm) : GUI::Debugger(), _vm(vm) {
 	registerCmd("continue", WRAP_METHOD(Debugger, cmdExit));
-	registerCmd("scene", WRAP_METHOD(Debugger, Cmd_LoadScene));
+	registerCmd("spell", WRAP_METHOD(Debugger, cmdSpell));
+
+	_spellId = -1;
 }
 
-bool Debugger::Cmd_LoadScene(int argc, const char **argv) {
+void Debugger::update() {
+	Combat &combat = *_vm->_combat;
+	Party &party = *_vm->_party;
+	Spells &spells = *_vm->_spells;
+
+	if (_spellId != -1) {
+		// Cast any specified spell
+		MagicSpell spellId = (MagicSpell)_spellId;
+		_spellId = -1;
+		spells.castSpell(&party._activeParty[0], spellId);
+	}
+
+	onFrame();
+}
+
+bool Debugger::cmdSpell(int argc, const char **argv) {
+	if (argc != 2) {
+		debugPrintf("Format: spell <spell-id>");
+		return true;
+	} else {
+		int spellId = strToInt(argv[1]);
+		if (spellId >= MS_AcidSpray && spellId <= MS_WizardEye) {
+			_spellId = spellId;
+			return false;
+		}
+	}
+
 	return true;
 }
 
diff --git a/engines/xeen/debugger.h b/engines/xeen/debugger.h
index 6a1ec12..e7f8ef6 100644
--- a/engines/xeen/debugger.h
+++ b/engines/xeen/debugger.h
@@ -31,12 +31,15 @@ namespace Xeen {
 class XeenEngine;
 
 class Debugger : public GUI::Debugger {
-protected:
+private:
 	XeenEngine *_vm;
+	int _spellId;
 
-	bool Cmd_LoadScene(int argc, const char **argv);
+	bool cmdSpell(int argc, const char **argv);
 public:
 	Debugger(XeenEngine *vm);
+
+	void update();
 };
 
 } // End of namespace Xeen
diff --git a/engines/xeen/dialogs_error.cpp b/engines/xeen/dialogs_error.cpp
index 7f649af..7204bad 100644
--- a/engines/xeen/dialogs_error.cpp
+++ b/engines/xeen/dialogs_error.cpp
@@ -93,6 +93,7 @@ void CantCast::show(XeenEngine *vm, int spellId, int componentNum) {
 void CantCast::execute(int spellId, int componentNum) {
 	EventsManager &events = *_vm->_events;
 	SoundManager &sound = *_vm->_sound;
+	Spells &spells = *_vm->_spells;
 	Window &w = _vm->_screen->_windows[6];
 	Mode oldMode = _vm->_mode;
 	_vm->_mode = MODE_FF;
@@ -100,7 +101,9 @@ void CantCast::execute(int spellId, int componentNum) {
 	sound.playFX(21);
 	w.open();
 	w.writeString(Common::String::format(NOT_ENOUGH_TO_CAST,
-		SPELL_CAST_COMPONENTS[componentNum - 1]));
+		SPELL_CAST_COMPONENTS[componentNum - 1],
+		spells._spellNames[spellId].c_str()
+	));
 	w.update();
 
 	do {
diff --git a/engines/xeen/dialogs_spells.cpp b/engines/xeen/dialogs_spells.cpp
index f49dca6..7cde5f3 100644
--- a/engines/xeen/dialogs_spells.cpp
+++ b/engines/xeen/dialogs_spells.cpp
@@ -988,7 +988,6 @@ void IdentifyMonster::execute() {
 	Map &map = *_vm->_map;
 	Screen &screen = *_vm->_screen;
 	SoundManager &sound = *_vm->_sound;
-	Spells &spells = *_vm->_spells;
 	Window &w = screen._windows[17];
 	Common::String monsterDesc[3];
 
diff --git a/engines/xeen/events.cpp b/engines/xeen/events.cpp
index 9f13861..92dc8b4 100644
--- a/engines/xeen/events.cpp
+++ b/engines/xeen/events.cpp
@@ -94,7 +94,14 @@ void EventsManager::pollEvents() {
 		case Common::EVENT_RTL:
 			return;
 		case Common::EVENT_KEYDOWN:
-			_keyCode = event.kbd.keycode;
+			// Check for debugger
+			if (event.kbd.keycode == Common::KEYCODE_d && (event.kbd.flags & Common::KBD_CTRL)) {
+				// Attach to the debugger
+				_vm->_debugger->attach();
+				_vm->_debugger->onFrame();
+			} else {
+				_keyCode = event.kbd.keycode;
+			}
 			break;
 		case Common::EVENT_MOUSEMOVE:
 			_mousePos = event.mouse;
@@ -181,6 +188,11 @@ void EventsManager::ipause(uint amount) {
  */
 void EventsManager::nextFrame() {
 	++_frameCounter;
+
+	// Allow debugger to update
+	_vm->_debugger->update();
+
+	// Update the screen
 	_vm->_screen->update();
 }
 
diff --git a/engines/xeen/resources.cpp b/engines/xeen/resources.cpp
index 8bc99f6..544db24 100644
--- a/engines/xeen/resources.cpp
+++ b/engines/xeen/resources.cpp
@@ -1315,7 +1315,7 @@ const char *const USE_ITEM_IN_COMBAT =
 
 const char *const NO_SPECIAL_ABILITIES = "\v005\x3""c%s\fdhas no special abilities!";
 
-const char *const CANT_CAST_WHILE_ENGAGED = "\x03c\v007Can't cast %s while engaged!";
+const char *const CANT_CAST_WHILE_ENGAGED = "\x3""c\v007Can't cast %s while engaged!";
 
 const char *const EQUIPPED_ALL_YOU_CAN = "\x3""c\v007You have equipped all the %ss you can!";
 const char *const REMOVE_X_TO_EQUIP_Y = "\x3""c\v007You must remove %sto equip %s\x8!";
@@ -1328,7 +1328,7 @@ const char *const CANNOT_DISCARD_CURSED_ITEM = "\3x""cYou cannot discard a curse
 
 const char *const PERMANENTLY_DISCARD = "\v000\t000\x03lPermanently discard %s\fd?";
 
-const char *const BACKPACK_IS_FULL = "\v005\x03c\fd%s's backpack is full.";
+const char *const BACKPACK_IS_FULL = "\v005\x3""c\fd%s's backpack is full.";
 
 const char *const CATEGORY_BACKPACK_IS_FULL[4] = {
 	"\v010\t000\x3""c%s's weapons backpack is full.",
@@ -1341,11 +1341,11 @@ const char *const BUY_X_FOR_Y_GOLD = "\x3l\v000\t000\fdBuy %s\fd for %lu gold?";
 
 const char *const SELL_X_FOR_Y_GOLD = "\x3l\v000\t000\fdSell %s\fd for %lu gold?";
 
-const char *const NO_NEED_OF_THIS = "\v005\x03c\fdWe have no need of this %s\f!";
+const char *const NO_NEED_OF_THIS = "\v005\x3""c\fdWe have no need of this %s\f!";
 
-const char *const NOT_RECHARGABLE = "\v012\x03c\fdNot Rechargeable.  %s";
+const char *const NOT_RECHARGABLE = "\v012\x3""c\fdNot Rechargeable.  %s";
 
-const char *const NOT_ENCHANTABLE = "\v012\t000\x03cNot Enchantable.  %s";
+const char *const NOT_ENCHANTABLE = "\v012\t000\x3""cNot Enchantable.  %s";
 
 const char *const SPELL_FAILED = "Spell Failed!";
 
@@ -1495,7 +1495,7 @@ const int NEW_CHARACTER_SPELLS[10][4] = {
 
 const char *const COMBAT_DETAILS = "\r\f00\x3""c\v000\t000\x2""Combat%s%s%s\x1";
 
-const char *NOT_ENOUGH_TO_CAST = "\x03c\v010Not enough %s to Cast %s";
+const char *NOT_ENOUGH_TO_CAST = "\x3""c\v010Not enough %s to Cast %s";
 const char *SPELL_CAST_COMPONENTS[2] = { "Spell Points", "Gems" };
 
 const char *const CAST_SPELL_DETAILS = 
@@ -1530,7 +1530,7 @@ const char *const GIVE_TREASURE_FORMATTING =
 	"\x4""077\n"
 	"\x4""077";
 
-const char *const X_FOUND_Y = "\v060\t000\x03c%s found: %s";
+const char *const X_FOUND_Y = "\v060\t000\x3""c%s found: %s";
 
 const char *const ON_WHO = "\x3""c\v009On Who?";
 
@@ -1554,7 +1554,7 @@ const char *const LLOYDS_BEACON =
 	"%s\x3l\n"
 	"x = %d\x3r\t000y = %d\x3""c\x2\v122\t021\f15S\fdet\t060\f15R\fdeturn\x1";
 
-const char *const HOW_MANY_SQUARES = "\x03cTeleport\nHow many squares %s (1-9)";
+const char *const HOW_MANY_SQUARES = "\x3""cTeleport\nHow many squares %s (1-9)";
 
 const char *const TOWN_PORTAL =
 	"\x3""cTown Portal\x3l\n"


Commit: 02c046941b76b5289d206bdc110cf55719a05dbb
    https://github.com/scummvm/scummvm/commit/02c046941b76b5289d206bdc110cf55719a05dbb
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-03-01T22:16:51-05:00

Commit Message:
XEEN: Fixes for text entry

Changed paths:
    engines/xeen/dialogs_input.cpp



diff --git a/engines/xeen/dialogs_input.cpp b/engines/xeen/dialogs_input.cpp
index 042fabf..3626441 100644
--- a/engines/xeen/dialogs_input.cpp
+++ b/engines/xeen/dialogs_input.cpp
@@ -40,26 +40,35 @@ int Input::show(XeenEngine *vm, Window *window, Common::String &line,
  */
 int Input::getString(Common::String &line, uint maxLen, int maxWidth, bool isNumeric) {
 	_vm->_noDirectionSense = true;
-	Common::String msg = Common::String::format("\x03""l\t000\x04%03d\x03""c", maxWidth);
+	Common::String msg = Common::String::format("\x3""l\t000\x4%03d\x0""c", maxWidth);
 	_window->writeString(msg);
 	_window->update();
 
 	while (!_vm->shouldQuit()) {
 		Common::KeyCode keyCode = doCursor(msg);
 
+		bool refresh = false;
 		if ((keyCode == Common::KEYCODE_BACKSPACE || keyCode == Common::KEYCODE_DELETE)
-			&& line.size() > 0)
+				&& line.size() > 0) {
 			line.deleteLastChar();
-		else if (line.size() < maxLen && (line.size() > 0 || keyCode != Common::KEYCODE_SPACE)
+			refresh = true;
+		} else if (line.size() < maxLen && (line.size() > 0 || keyCode != Common::KEYCODE_SPACE)
 				&& ((isNumeric && keyCode >= Common::KEYCODE_0 && keyCode < Common::KEYCODE_9) ||
 				   (!isNumeric && keyCode >= Common::KEYCODE_SPACE && keyCode < Common::KEYCODE_DELETE))) {
 			line += (char)keyCode;
+			refresh = true;
 		} else if (keyCode == Common::KEYCODE_RETURN || keyCode == Common::KEYCODE_KP_ENTER) {
 			break;
 		} else if (keyCode == Common::KEYCODE_ESCAPE) {
 			line = "";
 			break;
 		}
+
+		if (refresh) {
+			msg = Common::String::format("\x3""l\t000\x4%03d\x3""c%s", maxWidth, line.c_str());
+			_window->writeString(msg);
+			_window->update();
+		}
 	}
 
 	_vm->_noDirectionSense = false;


Commit: 7bbbfd2ad0b310497eacecad7e14230eed6bd80b
    https://github.com/scummvm/scummvm/commit/7bbbfd2ad0b310497eacecad7e14230eed6bd80b
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-03-02T21:39:49-05:00

Commit Message:
XEEN: Implementing more script opcodes

Changed paths:
    engines/xeen/debugger.cpp
    engines/xeen/resources.cpp
    engines/xeen/resources.h
    engines/xeen/screen.cpp
    engines/xeen/screen.h
    engines/xeen/scripts.cpp
    engines/xeen/scripts.h



diff --git a/engines/xeen/debugger.cpp b/engines/xeen/debugger.cpp
index 35cbaeb..d9b4990 100644
--- a/engines/xeen/debugger.cpp
+++ b/engines/xeen/debugger.cpp
@@ -52,7 +52,6 @@ Debugger::Debugger(XeenEngine *vm) : GUI::Debugger(), _vm(vm) {
 }
 
 void Debugger::update() {
-	Combat &combat = *_vm->_combat;
 	Party &party = *_vm->_party;
 	Spells &spells = *_vm->_spells;
 
@@ -60,7 +59,9 @@ void Debugger::update() {
 		// Cast any specified spell
 		MagicSpell spellId = (MagicSpell)_spellId;
 		_spellId = -1;
-		spells.castSpell(&party._activeParty[0], spellId);
+		Character *c = &party._activeParty[0];
+		c->_currentSp = 99;
+		spells.castSpell(c, spellId);
 	}
 
 	onFrame();
diff --git a/engines/xeen/resources.cpp b/engines/xeen/resources.cpp
index 544db24..0b30ce3 100644
--- a/engines/xeen/resources.cpp
+++ b/engines/xeen/resources.cpp
@@ -1585,4 +1585,8 @@ const char *const MONSTER_SPECIAL_ATTACKS[23] = {
 const char *const IDENTIFY_MONSTERS =
 	"Name\x3""c\t100HP\t140AC\t177#Atks\x3r\t000Special%s%s%s";
 
+const char *const EVENT_SAMPLES[6] = {
+	"ahh.voc", "whereto.voc", "gulp.voc", "null.voc", "scream.voc", "laff1.voc"
+};
+
 } // End of namespace Xeen
diff --git a/engines/xeen/resources.h b/engines/xeen/resources.h
index e15c509..6e9ce6c 100644
--- a/engines/xeen/resources.h
+++ b/engines/xeen/resources.h
@@ -562,6 +562,8 @@ extern const char *const MONSTER_SPECIAL_ATTACKS[23];
 
 extern const char *const IDENTIFY_MONSTERS;
 
+extern const char *const EVENT_SAMPLES[6];
+
 } // End of namespace Xeen
 
 #endif	/* XEEN_RESOURCES_H */
diff --git a/engines/xeen/screen.cpp b/engines/xeen/screen.cpp
index ac1f0c4..d9dcbf1 100644
--- a/engines/xeen/screen.cpp
+++ b/engines/xeen/screen.cpp
@@ -183,8 +183,8 @@ void Window::fill() {
 	fillRect(_innerBounds, _vm->_screen->_bgColor);
 }
 
-void Window::writeString(const Common::String &s) {
-	_vm->_screen->writeString(s, _innerBounds);
+Common::String Window::writeString(const Common::String &s) {
+	return _vm->_screen->writeString(s, _innerBounds);
 }
 
 void Window::drawList(DrawStruct *items, int count) {
diff --git a/engines/xeen/screen.h b/engines/xeen/screen.h
index f8f11a4..901e79b 100644
--- a/engines/xeen/screen.h
+++ b/engines/xeen/screen.h
@@ -92,7 +92,7 @@ public:
 
 	void fill();
 
-	void writeString(const Common::String &s);
+	Common::String writeString(const Common::String &s);
 
 	void drawList(DrawStruct *items, int count);
 
diff --git a/engines/xeen/scripts.cpp b/engines/xeen/scripts.cpp
index ec00327..c1743ab 100644
--- a/engines/xeen/scripts.cpp
+++ b/engines/xeen/scripts.cpp
@@ -102,6 +102,8 @@ Scripts::Scripts(XeenEngine *vm) : _vm(vm) {
 	_scriptResult = false;
 	_scriptExecuted = false;
 	_var50 = false;
+	_redrawDone = false;
+	_windowIndex = -1;
 }
 
 int Scripts::checkEvents() {
@@ -132,7 +134,7 @@ int Scripts::checkEvents() {
 		_lineNum = 0;
 		_scriptResult = false;
 		_animCounter = 0;
-//		int var4E = 0;
+		_redrawDone = false;
 		_currentPos = party._mazePosition;
 		_charIndex = 1;
 		_v2 = 1;
@@ -366,7 +368,7 @@ void Scripts::cmdSignText(Common::Array<byte> &params) {
 }
 
 void Scripts::cmdNPC(Common::Array<byte> &params) {
-	warning("TODO: cmdNPC");
+	error("TODO: cmdNPC");
 }
 
 /**
@@ -800,18 +802,123 @@ void Scripts::cmdWhoWill(Common::Array<byte> &params) {
 		cmdNoAction(params);
 }
 
-void Scripts::cmdRndDamage(Common::Array<byte> &params) { error("TODO"); }
-void Scripts::cmdMoveWallObj(Common::Array<byte> &params) { error("TODO"); }
-void Scripts::cmdAlterCellFlag(Common::Array<byte> &params) { error("TODO"); }
-void Scripts::cmdAlterHed(Common::Array<byte> &params) { error("TODO"); }
-void Scripts::cmdDisplayStat(Common::Array<byte> &params) { error("TODO"); }
-void Scripts::cmdSeatTextSml(Common::Array<byte> &params) { error("TODO"); }
-void Scripts::cmdPlayEventVoc(Common::Array<byte> &params) { error("TODO"); }
-void Scripts::cmdDisplayBottom(Common::Array<byte> &params) { error("TODO"); }
-void Scripts::cmdIfMapFlag(Common::Array<byte> &params) { error("TODO"); }
-void Scripts::cmdSelRndChar(Common::Array<byte> &params) { error("TODO"); }
-void Scripts::cmdGiveEnchanted(Common::Array<byte> &params) { error("TODO"); }
-void Scripts::cmdItemType(Common::Array<byte> &params) { error("TODO"); }
+void Scripts::cmdRndDamage(Common::Array<byte> &params) { 
+	Combat &combat = *_vm->_combat;
+	Interface &intf = *_vm->_interface;
+
+	if (!_redrawDone) {
+		intf.draw3d(true);
+		_redrawDone = true;
+	}
+
+	combat.giveCharDamage(_vm->getRandomNumber(1, params[1]), (DamageType)params[0], _charIndex);
+	cmdNoAction(params);
+}
+
+void Scripts::cmdMoveWallObj(Common::Array<byte> &params) {
+	Map &map = *_vm->_map;
+
+	map._mobData._wallItems[params[0]]._position = Common::Point(params[1], params[2]);
+	cmdNoAction(params);
+}
+
+void Scripts::cmdAlterCellFlag(Common::Array<byte> &params) {
+	Map &map = *_vm->_map;
+	Common::Point pt(params[0], params[1]);
+	map.cellFlagLookup(pt);
+
+	if (map._isOutdoors) {
+		MazeWallLayers &wallData = map.mazeDataCurrent()._wallData[pt.y][pt.x];
+		wallData._data = (wallData._data & 0xFFF0) | params[2];
+	} else {
+		pt.x &= 0xF; 
+		pt.y &= 0xF;
+		MazeCell &cell = map.mazeDataCurrent()._cells[pt.y][pt.x];
+		cell._surfaceId = params[2];
+	}
+
+	cmdNoAction(params);
+}
+
+void Scripts::cmdAlterHed(Common::Array<byte> &params) {
+	Map &map = *_vm->_map;
+	Party &party = *_vm->_party;
+
+	HeadData::HeadEntry &he = map._headData[party._mazePosition.y][party._mazePosition.x];
+	he._left = params[0];
+	he._right = params[1];
+
+	cmdNoAction(params);
+}
+
+void Scripts::cmdDisplayStat(Common::Array<byte> &params) {
+	Party &party = *_vm->_party;
+	Window &w = _vm->_screen->_windows[12];
+	Character &c = party._activeParty[_charIndex - 1];
+
+	if (!w._enabled)
+		w.open();
+	w.writeString(Common::String::format(_message.c_str(), c._name.c_str()));
+	w.update();
+
+	cmdNoAction(params);
+}
+
+void Scripts::cmdSeatTextSml(Common::Array<byte> &params) { 
+	Interface &intf = *_vm->_interface;
+
+	intf._screenText = Common::String::format("\x2\f08\x3""c\t116\v090%s\x3l\fd\x1",
+		_message);
+	intf._upDoorText = true;
+	intf.draw3d(true);
+
+	cmdNoAction(params);
+}
+
+void Scripts::cmdPlayEventVoc(Common::Array<byte> &params) {
+	SoundManager &sound = *_vm->_sound;
+	sound.playSample(nullptr, 0);
+	File f(EVENT_SAMPLES[params[0]]);
+	sound.playSample(&f, 1);
+
+	cmdNoAction(params);
+}
+
+void Scripts::cmdDisplayBottom(Common::Array<byte> &params) {
+	_windowIndex = 12;
+
+	display(false, 0);
+	cmdNoAction(params);
+}
+
+void Scripts::cmdIfMapFlag(Common::Array<byte> &params) {
+	Map &map = *_vm->_map;
+	MazeMonster &monster = map._mobData._monsters[params[0]];
+
+	if (monster._position.x >= 32 || monster._position.y >= 32) {
+		_lineNum = params[1] - 1;
+	}
+
+	cmdNoAction(params);
+}
+
+void Scripts::cmdSelRndChar(Common::Array<byte> &params) {
+	_charIndex = _vm->getRandomNumber(1, _vm->_party->_activeParty.size());
+	cmdNoAction(params);
+}
+
+void Scripts::cmdGiveEnchanted(Common::Array<byte> &params) {
+	if (params[0] < 35) {
+
+	}
+	error("TODO");
+}
+
+void Scripts::cmdItemType(Common::Array<byte> &params) {
+	_itemType = params[0];
+
+	cmdNoAction(params);
+}
 
 /**
  * Disable all the scripts at the party's current position
@@ -840,7 +947,13 @@ void Scripts::cmdCheckProtection(Common::Array<byte> &params) {
 
 void Scripts::cmdChooseNumeric(Common::Array<byte> &params) { error("TODO"); }
 void Scripts::cmdDisplayBottomTwoLines(Common::Array<byte> &params) { error("TODO"); }
-void Scripts::cmdDisplayLarge(Common::Array<byte> &params) { error("TODO"); }
+
+void Scripts::cmdDisplayLarge(Common::Array<byte> &params) {
+	error("TODO: Implement event text loading");
+
+	display(true, 0);
+	cmdNoAction(params);
+}
 
 /**
  * Exchange the positions of two objects in the maze
@@ -868,7 +981,8 @@ void Scripts::cmdFallToMap(Common::Array<byte> &params) {
 }
 
 void Scripts::cmdDisplayMain(Common::Array<byte> &params) { 
-	error("TODO"); 
+	display(false, 0);
+	cmdNoAction(params);
 }
 
 /**
@@ -1333,4 +1447,40 @@ bool Scripts::copyProtectionCheck() {
 	return true;
 }
 
+void Scripts::display(bool justifyFlag, int var46) {
+	EventsManager &events = *_vm->_events;
+	Interface &intf = *_vm->_interface;
+	Screen &screen = *_vm->_screen;
+	Window &w = screen._windows[_windowIndex];
+
+	if (!_redrawDone) {
+		intf.draw3d(true);
+		_redrawDone = true;
+	}
+	screen._windows[38].close();
+
+	if (!justifyFlag)
+		_displayMessage = Common::String::format("\r\x3""c%s", _message.c_str());
+
+	if (!w._enabled)
+		w.open();
+
+	while (!_vm->shouldQuit()) {
+		_displayMessage = w.writeString(_displayMessage);
+		w.update();
+		if (_displayMessage.empty())
+			break;
+		events.clearEvents();
+
+		do {
+			events.updateGameCounter();
+			intf.draw3d(true);
+
+			events.wait(1, true);
+		} while (!_vm->shouldQuit() && !events.isKeyMousePressed());
+
+		w.writeString(justifyFlag ? "\r" : "\r\x3""c");
+	}
+}
+
 } // End of namespace Xeen
diff --git a/engines/xeen/scripts.h b/engines/xeen/scripts.h
index 29de5b8..15550dd 100644
--- a/engines/xeen/scripts.h
+++ b/engines/xeen/scripts.h
@@ -147,9 +147,13 @@ private:
 	int _scriptResult;
 	bool _scriptExecuted;
 	bool _var50;
+	int _windowIndex;
+	bool _redrawDone;
 	MazeEvent *_event;
 	Common::Point _currentPos;
 	Common::Stack<StackEntry> _stack;
+	Common::String _message;
+	Common::String _displayMessage;
 
 	void doOpcode(MazeEvent &event);
 	void cmdDisplay1(Common::Array<byte> &params);
@@ -219,6 +223,8 @@ private:
 	bool ifProc(int action, uint32 mask, int mode, int charIndex);
 
 	bool copyProtectionCheck();
+
+	void display(bool justifyFlag, int var46);
 public:
 	int _animCounter;
 	bool _eventSkipped;


Commit: de5aedcb0c559754697dc534e559820f466afdf2
    https://github.com/scummvm/scummvm/commit/de5aedcb0c559754697dc534e559820f466afdf2
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-03-02T23:13:01-05:00

Commit Message:
XEEN: Implemented cmNPC and TownMessage dialog class

Changed paths:
    engines/xeen/font.cpp
    engines/xeen/font.h
    engines/xeen/screen.cpp
    engines/xeen/screen.h
    engines/xeen/scripts.cpp
    engines/xeen/town.cpp
    engines/xeen/town.h



diff --git a/engines/xeen/font.cpp b/engines/xeen/font.cpp
index 53308ae..bfdc4bd 100644
--- a/engines/xeen/font.cpp
+++ b/engines/xeen/font.cpp
@@ -65,7 +65,7 @@ void FontSurface::writeSymbol(int symbolId) {
  * @remarks		Note that bounds is just used for wrapping purposes. Unless
  *		justification is set, the message will be written at _writePos
  */
-Common::String FontSurface::writeString(const Common::String &s, const Common::Rect &bounds) {
+const char *FontSurface::writeString(const Common::String &s, const Common::Rect &bounds) {
 	_displayString = s.c_str();
 	assert(_fontData);
 
@@ -250,7 +250,7 @@ Common::String FontSurface::writeString(const Common::String &s, const Common::R
 			break;
 	}
 
-	return Common::String(_displayString);
+	return _displayString;
 }
 
 /**
diff --git a/engines/xeen/font.h b/engines/xeen/font.h
index db61e3e..caaa03c 100644
--- a/engines/xeen/font.h
+++ b/engines/xeen/font.h
@@ -63,7 +63,7 @@ public:
 
 	void writeSymbol(int symbolId);
 
-	Common::String writeString(const Common::String &s, const Common::Rect &clipRect);
+	const char *writeString(const Common::String &s, const Common::Rect &clipRect);
 };
 
 } // End of namespace Xeen
diff --git a/engines/xeen/screen.cpp b/engines/xeen/screen.cpp
index d9dcbf1..80f0149 100644
--- a/engines/xeen/screen.cpp
+++ b/engines/xeen/screen.cpp
@@ -183,7 +183,7 @@ void Window::fill() {
 	fillRect(_innerBounds, _vm->_screen->_bgColor);
 }
 
-Common::String Window::writeString(const Common::String &s) {
+const char *Window::writeString(const Common::String &s) {
 	return _vm->_screen->writeString(s, _innerBounds);
 }
 
diff --git a/engines/xeen/screen.h b/engines/xeen/screen.h
index 901e79b..21b7e89 100644
--- a/engines/xeen/screen.h
+++ b/engines/xeen/screen.h
@@ -92,7 +92,7 @@ public:
 
 	void fill();
 
-	Common::String writeString(const Common::String &s);
+	const char *writeString(const Common::String &s);
 
 	void drawList(DrawStruct *items, int count);
 
diff --git a/engines/xeen/scripts.cpp b/engines/xeen/scripts.cpp
index c1743ab..53eebb9 100644
--- a/engines/xeen/scripts.cpp
+++ b/engines/xeen/scripts.cpp
@@ -368,7 +368,11 @@ void Scripts::cmdSignText(Common::Array<byte> &params) {
 }
 
 void Scripts::cmdNPC(Common::Array<byte> &params) {
-	error("TODO: cmdNPC");
+	Map &map = *_vm->_map;
+
+	if (TownMessage::show(_vm, params[2], _message, map._events._text[params[1]],
+			params[3]))
+		_lineNum = params[4];
 }
 
 /**
diff --git a/engines/xeen/town.cpp b/engines/xeen/town.cpp
index 0934aef..a3033b2 100644
--- a/engines/xeen/town.cpp
+++ b/engines/xeen/town.cpp
@@ -1192,4 +1192,119 @@ bool Town::isActive() const {
 	return _townSprites.size() > 0 && !_townSprites[0].empty();
 }
 
+/*------------------------------------------------------------------------*/
+
+bool TownMessage::show(XeenEngine *vm, int portrait, const Common::String &name,
+		const Common::String &text, int confirm) {
+	TownMessage *dlg = new TownMessage(vm);
+	bool result = dlg->execute(portrait, name, text, confirm);
+	delete dlg;
+
+	return result;
+}
+
+bool TownMessage::execute(int portrait, const Common::String &name, const Common::String &text,
+		int confirm) {
+	EventsManager &events = *_vm->_events;
+	Interface &intf = *_vm->_interface;
+	Screen &screen = *_vm->_screen;
+	Town &town = *_vm->_town;
+	Window &w = screen._windows[11];
+
+	town._townMaxId = 4;
+	town._townActionId = 7;
+	town._drawFrameIndex = 0;
+	town._townPos = Common::Point(23, 22);
+
+	if (!confirm)
+		loadButtons();
+
+	if (town._townSprites[0].empty()) {
+		town._townSprites[0].load(Common::String::format("face%02d.fac", portrait));
+		town._townSprites[1].load("frame.fac");
+	}
+
+	if (!w._enabled)
+		w.open();
+
+	int result = -1;
+	Common::String msgText = text;
+	for (;;) {
+		Common::String msg = Common::String::format("\r\v014\x03c\t125%s\t000\v054%s",
+			name.c_str(), msgText.c_str());
+		const char *msgEnd = w.writeString(msg.c_str());
+		int wordCount = 0;
+
+		for (const char *msgP = msg.c_str(); msgP < msgEnd; ++msgP) {
+			if (*msgP == ' ')
+				++wordCount;
+		}
+
+		town._drawCtr2 = wordCount * 2;
+		town._townSprites[1].draw(screen, 0, Common::Point(16, 16));
+		town._townSprites[0].draw(screen, town._drawFrameIndex, Common::Point(23, 22));
+		w.update();
+
+		if (!msgEnd) {
+			// Doesn't look like the code here in original can ever be reached
+			assert(0);
+		}
+
+		if (confirm == 2) {
+			intf._face1State = intf._face2State = 2;
+			return false;
+		}
+
+		do {
+			events.clearEvents();
+			events.updateGameCounter();
+			if (msgEnd)
+				clearButtons();
+
+			do {
+				events.wait(3, true);
+				checkEvents(_vm);
+				if (_vm->shouldQuit())
+					return false;
+
+				town.drawTownAnim(false);
+				events.updateGameCounter();
+			} while (!_buttonValue);
+
+			if (msgEnd)
+				break;
+
+			if (!msgEnd) {
+				if (confirm || _buttonValue == Common::KEYCODE_ESCAPE || 
+						_buttonValue == Common::KEYCODE_n)
+					result = 0;
+				else if (_buttonValue == Common::KEYCODE_y)
+					result = 1;
+			}
+		} while (result == -1);
+
+		if (msgEnd) {
+			msgText = Common::String(msgEnd);
+			town._drawCtr2 = wordCount;
+			continue;
+		}
+	} while (result == -1);
+
+	intf._face1State = intf._face2State = 2;
+	if (!confirm)
+		intf.mainIconsPrint();
+
+	town._townSprites[0].clear();
+	town._townSprites[1].clear();
+	return result == 1;
+}
+
+void TownMessage::loadButtons() {
+	_iconSprites.load("confirm.icn");
+
+	addButton(Common::Rect(235, 75, 259, 95), Common::KEYCODE_y, &_iconSprites);
+	addButton(Common::Rect(260, 75, 284, 95), Common::KEYCODE_n, &_iconSprites);
+	addButton(Common::Rect(), Common::KEYCODE_ESCAPE);
+}
+
 } // End of namespace Xeen
diff --git a/engines/xeen/town.h b/engines/xeen/town.h
index 8f6ef15..5aa31e5 100644
--- a/engines/xeen/town.h
+++ b/engines/xeen/town.h
@@ -32,8 +32,10 @@
 namespace Xeen {
 
 class XeenEngine;
+class TownMessage;
 
 class Town: public ButtonContainer {
+	friend class TownMessage;
 private:
 	XeenEngine *_vm;
 	SpriteResource _icons1, _icons2;
@@ -105,6 +107,22 @@ public:
 	bool isActive() const;
 };
 
+class TownMessage : public ButtonContainer {
+private:
+	XeenEngine *_vm;
+	SpriteResource _iconSprites;
+
+	TownMessage(XeenEngine *vm) : ButtonContainer(), _vm(vm) {}
+
+	bool execute(int portrait, const Common::String &name, 
+		const Common::String &text, int confirm);
+
+	void loadButtons();
+public:
+	static bool show(XeenEngine *vm, int portrait, const Common::String &name,
+		const Common::String &text, int confirm);
+};
+
 } // End of namespace Xeen
 
 #endif /* XEEN_SPELLS_H */


Commit: 66dc9ac74645da3aec55edc85c59b73d5724ba43
    https://github.com/scummvm/scummvm/commit/66dc9ac74645da3aec55edc85c59b73d5724ba43
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-03-03T21:26:20-05:00

Commit Message:
XEEN: Implement give/take script opcodes

Changed paths:
    engines/xeen/party.cpp
    engines/xeen/party.h
    engines/xeen/scripts.cpp



diff --git a/engines/xeen/party.cpp b/engines/xeen/party.cpp
index 5e111e6..9f56b98 100644
--- a/engines/xeen/party.cpp
+++ b/engines/xeen/party.cpp
@@ -744,4 +744,9 @@ bool Party::canShoot() const {
 	return false;
 }
 
+bool Party::giveTake(int mode1, uint32 mask1, int mode2, int mask2, int charIdx) {
+	error("TODO");
+}
+
+
 } // End of namespace Xeen
diff --git a/engines/xeen/party.h b/engines/xeen/party.h
index 483c3f4..445380b 100644
--- a/engines/xeen/party.h
+++ b/engines/xeen/party.h
@@ -175,6 +175,8 @@ public:
 	bool arePacksFull() const;
 
 	bool canShoot() const;
+
+	bool giveTake(int mode1, uint32 mask1, int mode2, int mask2, int charIdx);
 };
 
 } // End of namespace Xeen
diff --git a/engines/xeen/scripts.cpp b/engines/xeen/scripts.cpp
index 53eebb9..7cb487c 100644
--- a/engines/xeen/scripts.cpp
+++ b/engines/xeen/scripts.cpp
@@ -372,7 +372,9 @@ void Scripts::cmdNPC(Common::Array<byte> &params) {
 
 	if (TownMessage::show(_vm, params[2], _message, map._events._text[params[1]],
 			params[3]))
-		_lineNum = params[4];
+		_lineNum = params[4] - 1;
+
+	cmdNoAction(params);
 }
 
 /**
@@ -484,7 +486,7 @@ void Scripts::cmdIf(Common::Array<byte> &params) {
 	} else {
 		result = false;
 		for (int idx = 0; idx < (int)party._activeParty.size() && !result; ++idx) {
-			if (_charIndex == 0 || (_charIndex == 8 && idx != _v2)) {
+			if (_charIndex == 0 || (_charIndex == 8 && (int)idx != _v2)) {
 				result = ifProc(params[0], mask, _event->_opcode - 8, idx);
 			}
 		}
@@ -511,7 +513,213 @@ void Scripts::cmdMoveObj(Common::Array<byte> &params) {
 	}
 }
 
-void Scripts::cmdTakeOrGive(Common::Array<byte> &params) { error("TODO"); }
+void Scripts::cmdTakeOrGive(Common::Array<byte> &params) {
+	Party &party = *_vm->_party;
+	Screen &screen = *_vm->_screen;
+	int mode1, mode2, mode3;
+	uint32 mask1, mask2, mask3;
+	byte *extraP;
+	// TODO: See if this needs to maintain values set in other opcodes
+	int param2 = 0;
+
+	mode1 = params[0];
+	switch (mode1) {
+	case 16:
+	case 34:
+	case 100:
+		mask1 = (params[4] << 24) | (params[3] << 16) | (params[2] << 8) | params[1];
+		extraP = &params[5];
+		break;
+	case 25:
+	case 35:
+	case 101:
+	case 106:
+		mask1 = (params[2] << 8) | params[1];
+		extraP = &params[3];
+		break;
+	default:
+		mask1 = params[1];
+		extraP = &params[2];
+		break;
+	}
+
+	mode2 = *extraP++;
+	switch (mode2) {
+	case 16:
+	case 34:
+	case 100:
+		mask2 = (extraP[3] << 24) | (extraP[2] << 16) | (extraP[1] << 8) | extraP[0];
+		extraP += 4;
+		break;
+	case 25:
+	case 35:
+	case 101:
+	case 106:
+		mask2 = (extraP[1] << 8) | extraP[0];
+		extraP += 2;
+		break;
+	default:
+		mask2 = extraP[0];
+		extraP++;
+		break;
+	}
+
+	mode3 = *extraP++;
+	switch (mode3) {
+	case 16:
+	case 34:
+	case 100:
+		mask3 = (extraP[3] << 24) | (extraP[2] << 16) | (extraP[1] << 8) | extraP[0];
+		break;
+	case 25:
+	case 35:
+	case 101:
+	case 106:
+		mask3 = (extraP[1] << 8) | extraP[0];
+		break;
+	default:
+		mask3 = extraP[0];
+		break;
+	}
+
+	if (mode2)
+		screen.closeWindows();
+
+	switch (_event->_opcode) {
+	case OP_TakeOrGive_2:
+		if (_charIndex == 0 || _charIndex == 8) {
+			for (uint idx = 0; idx < party._activeParty.size(); ++idx) {
+				if (_charIndex == 0 || (_charIndex == 8 && (int)idx != _v2)) {
+					if (ifProc(params[0], mask1, _event->_opcode == OP_TakeOrGive_4 ? 2 : 1, idx)) {
+						party.giveTake(0, 0, mode2, mask2, idx);
+						if (mode2 == 82)
+							break;
+					}
+				}
+			}
+		} else if (ifProc(params[0], mask1, _event->_opcode == OP_TakeOrGive_4 ? 2 : 1, _charIndex - 1)) {
+			party.giveTake(0, 0, mode2, mask2, _charIndex - 1);
+		}
+		break;
+
+	case OP_TakeOrGive_3:
+		if (_charIndex == 0 || _charIndex == 8) {
+			for (uint idx = 0; idx < party._activeParty.size(); ++idx) {
+				if (_charIndex == 0 || (_charIndex == 8 && (int)idx != _v2)) {
+					if (ifProc(params[0], mask1, 1, idx) && ifProc(mode2, mask2, 1, idx)) {
+						party.giveTake(0, 0, mode2, mask3, idx);
+						if (mode2 == 82)
+							break;
+					}
+				}
+			}
+		} else if (ifProc(params[0], mask1, 1, _charIndex - 1) &&
+				ifProc(mode2, mask2, 1, _charIndex - 1)) {
+			party.giveTake(0, 0, mode2, mask3, _charIndex - 1);
+		}
+		break;
+
+	case OP_TakeOrGive_4:
+		if (_charIndex == 0 || _charIndex == 8) {
+			for (uint idx = 0; idx < party._activeParty.size(); ++idx) {
+				if (_charIndex == 0 || (_charIndex == 8 && (int)idx != _v2)) {
+					if (ifProc(params[0], mask1, _event->_opcode == OP_TakeOrGive_4 ? 2 : 1, idx)) {
+						party.giveTake(0, 0, mode2, mask2, idx);
+						if (mode2 == 82)
+							break;
+					}
+				}
+			}
+		} else if (ifProc(params[0], mask1, 1, _charIndex - 1)) {
+			party.giveTake(0, 0, mode2, mask2, _charIndex - 1);
+		}
+		break;
+
+	default:
+		if (_charIndex == 0 || _charIndex == 8) {
+			for (uint idx = 0; idx < party._activeParty.size(); ++idx) {
+				if (_charIndex == 0 || (_charIndex == 8 && (int)idx != _v2)) {
+					party.giveTake(mode1, mask1, mode1, mask2, idx);
+					
+					switch (mode1) {
+					case 8:
+						mode1 = 0;
+						// Deliberate fall-through
+					case 21:
+					case 66:
+						if (param2) {
+							switch (mode2) {
+							case 82:
+								mode1 = 0;
+								// Deliberate fall-through
+							case 21:
+							case 34:
+							case 35:
+							case 65:
+							case 66:
+							case 100:
+							case 101:
+							case 106:
+								if (param2)
+									continue;
+								
+								// Break out of character loop
+								idx = party._activeParty.size();
+								break;
+							}
+						}
+						break;
+
+					case 34:
+					case 35:
+					case 65:
+					case 100:
+					case 101:
+					case 106:
+						if (param2) {
+							_lineNum = -1;
+							return;
+						}
+
+						// Break out of character loop
+						idx = party._activeParty.size();
+						break;
+
+					default:
+						switch (mode2) {
+						case 82:
+							mode1 = 0;
+							// Deliberate fall-through
+						case 21:
+						case 34:
+						case 35:
+						case 65:
+						case 66:
+						case 100:
+						case 101:
+						case 106:
+							if (param2)
+								continue;
+
+							// Break out of character loop
+							idx = party._activeParty.size();
+							break;
+						}
+						break;
+					}
+				}
+			}
+		} else {
+			if (!party.giveTake(mode1, mask1, mode2, mask2, _charIndex - 1)) {
+				if (mode2 == 79)
+					screen.closeWindows();
+			}
+		}
+		break;
+	}
+
+	cmdNoAction(params);
+}
 
 /**
  * Move to the next line of the script
@@ -949,7 +1157,10 @@ void Scripts::cmdCheckProtection(Common::Array<byte> &params) {
 		cmdExit(params);
 }
 
-void Scripts::cmdChooseNumeric(Common::Array<byte> &params) { error("TODO"); }
+void Scripts::cmdChooseNumeric(Common::Array<byte> &params) {
+	error("TODO");
+}
+
 void Scripts::cmdDisplayBottomTwoLines(Common::Array<byte> &params) { error("TODO"); }
 
 void Scripts::cmdDisplayLarge(Common::Array<byte> &params) {


Commit: 8101f8d03ba755dc9a71d351b10b279276a67999
    https://github.com/scummvm/scummvm/commit/8101f8d03ba755dc9a71d351b10b279276a67999
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-03-03T23:20:51-05:00

Commit Message:
XEEN: More script opcodes

Changed paths:
    engines/xeen/scripts.cpp



diff --git a/engines/xeen/scripts.cpp b/engines/xeen/scripts.cpp
index 7cb487c..1474b3e 100644
--- a/engines/xeen/scripts.cpp
+++ b/engines/xeen/scripts.cpp
@@ -1120,10 +1120,67 @@ void Scripts::cmdSelRndChar(Common::Array<byte> &params) {
 }
 
 void Scripts::cmdGiveEnchanted(Common::Array<byte> &params) {
-	if (params[0] < 35) {
+	Party &party = *_vm->_party;
+	bool isDarkCc = _vm->_files->_isDarkCc;
+
+	if (params[0] >= 35) {
+		if (params[0] < 49) {
+			for (int idx = 0; idx < MAX_TREASURE_ITEMS; ++idx) {
+				XeenItem &item = party._treasure._armor[idx];
+				if (!item.empty()) {
+					item._id = params[0] - 35;
+					item._material = params[1];
+					item._bonusFlags = params[2];
+					party._treasure._hasItems = true;
+					break;
+				}
+			}
+
+			cmdNoAction(params);
+			return;
+		} else if (params[0] < 60) {
+			for (int idx = 0; idx < MAX_TREASURE_ITEMS; ++idx) {
+				XeenItem &item = party._treasure._accessories[idx];
+				if (!item.empty()) {
+					item._id = params[0] - 49;
+					item._material = params[1];
+					item._bonusFlags = params[2];
+					party._treasure._hasItems = true;
+					break;
+				}
+			}
+
+			cmdNoAction(params);
+			return;
+		} else if (params[0] < 82) {
+			for (int idx = 0; idx < MAX_TREASURE_ITEMS; ++idx) {
+				XeenItem &item = party._treasure._misc[idx];
+				if (!item.empty()) {
+					item._id = params[0];
+					item._material = params[1];
+					item._bonusFlags = params[2];
+					party._treasure._hasItems = true;
+					break;
+				}
+			}
 
+			cmdNoAction(params);
+			return;
+		} else {
+			party._gameFlags[6 + params[0]]++;
+		}
+	}
+
+	for (int idx = 0; idx < MAX_TREASURE_ITEMS; ++idx) {
+		XeenItem &item = party._treasure._weapons[idx];
+		if (!item.empty()) {
+			item._id = params[0];
+			item._material = params[1];
+			item._bonusFlags = params[2];
+			party._treasure._hasItems = true;
+			break;
+		}
 	}
-	error("TODO");
 }
 
 void Scripts::cmdItemType(Common::Array<byte> &params) {
@@ -1161,7 +1218,21 @@ void Scripts::cmdChooseNumeric(Common::Array<byte> &params) {
 	error("TODO");
 }
 
-void Scripts::cmdDisplayBottomTwoLines(Common::Array<byte> &params) { error("TODO"); }
+void Scripts::cmdDisplayBottomTwoLines(Common::Array<byte> &params) {
+	Interface &intf = *_vm->_interface;
+	Map &map = *_vm->_map;
+	Window &w = _vm->_screen->_windows[12];
+
+	Common::String msg = Common::String::format("\r\x03c\t000\v007%s\n\n%s",
+		map._events._text[params[1]].c_str());
+	w.close();
+	w.open();
+	w.writeString(msg);
+	w.update();
+
+	YesNo::show(_vm, true);
+	_lineNum = -1;
+}
 
 void Scripts::cmdDisplayLarge(Common::Array<byte> &params) {
 	error("TODO: Implement event text loading");


Commit: 15d375bc4471788b3323875a54a81a9a754ed034
    https://github.com/scummvm/scummvm/commit/15d375bc4471788b3323875a54a81a9a754ed034
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-03-04T07:45:13-05:00

Commit Message:
XEEN: Implement remaining missing code in checkEvents

Changed paths:
    engines/xeen/party.h
    engines/xeen/scripts.cpp
    engines/xeen/town.cpp
    engines/xeen/town.h



diff --git a/engines/xeen/party.h b/engines/xeen/party.h
index 445380b..df6864d 100644
--- a/engines/xeen/party.h
+++ b/engines/xeen/party.h
@@ -141,6 +141,7 @@ public:
 	DamageType _damageType;
 	bool _dead;
 	Treasure _treasure;
+	Treasure _savedTreasure;
 public:
 	Party(XeenEngine *vm);
 
diff --git a/engines/xeen/scripts.cpp b/engines/xeen/scripts.cpp
index 1474b3e..1656acd 100644
--- a/engines/xeen/scripts.cpp
+++ b/engines/xeen/scripts.cpp
@@ -114,6 +114,8 @@ int Scripts::checkEvents() {
 	Party &party = *_vm->_party;
 	Screen &screen = *_vm->_screen;
 	SoundManager &sound = *_vm->_sound;
+	Town &town = *_vm->_town;
+	bool isDarkCc = _vm->_files->_isDarkCc;
 
 	_refreshIcons = false;
 	_itemType = 0;
@@ -125,9 +127,15 @@ int Scripts::checkEvents() {
 	//int items = _treasureItems;
 	
 	if (party._treasure._gold & party._treasure._gems) {
-		// TODO
+		// Backup any current treasure data
+		party._savedTreasure = party._treasure;
+		party._treasure._hasItems = false;
+		party._treasure._gold = 0;
+		party._treasure._gems = 0;
 	} else {
-		// TODO
+		party._savedTreasure._hasItems = false;
+		party._savedTreasure._gold = 0;
+		party._savedTreasure._gems = 0;
 	}
 
 	do {
@@ -176,7 +184,33 @@ int Scripts::checkEvents() {
 		intf.drawParty(true);
 	}
 
-	// TODO
+	party.checkPartyDead();
+	if (party._treasure._hasItems || party._treasure._gold || party._treasure._gems)
+		party.giveTreasure();
+
+	if (_animCounter > 0 && intf._objNumber) {
+		MazeObject &selectedObj = map._mobData._objects[intf._objNumber - 1];
+
+		if (selectedObj._spriteId == (isDarkCc ? 15 : 16)) {
+			for (uint idx = 0; idx < 16; ++idx) {
+				MazeObject &obj = map._mobData._objects[idx];
+				if (obj._spriteId == (isDarkCc ? 62 : 57)) {
+					selectedObj._id = idx;
+					selectedObj._spriteId = isDarkCc ? 62 : 57;
+					break;
+				}
+			}
+		} else if (selectedObj._spriteId == 73) {
+			for (uint idx = 0; idx < 16; ++idx) {
+				MazeObject &obj = map._mobData._objects[idx];
+				if (obj._spriteId == 119) {
+					selectedObj._id = idx;
+					selectedObj._spriteId = 119;
+					break;
+				}
+			}
+		}
+	}
 
 	_animCounter = 0;
 	_vm->_mode = oldMode;
@@ -202,6 +236,15 @@ int Scripts::checkEvents() {
 		w.close();
 	}
 
+	// Restore saved treasure
+	if (party._savedTreasure._hasItems || party._savedTreasure._gold ||
+			party._savedTreasure._gems) {
+		party._treasure = party._savedTreasure;
+	}
+
+	// Clear any town loaded sprites
+	town.clearSprites();
+
 	_v2 = 1;
 	Common::fill(&intf._charFX[0], &intf._charFX[6], 0);
 
diff --git a/engines/xeen/town.cpp b/engines/xeen/town.cpp
index a3033b2..9b4bfa3 100644
--- a/engines/xeen/town.cpp
+++ b/engines/xeen/town.cpp
@@ -1192,6 +1192,10 @@ bool Town::isActive() const {
 	return _townSprites.size() > 0 && !_townSprites[0].empty();
 }
 
+void Town::clearSprites() {
+	_townSprites.clear();
+}
+
 /*------------------------------------------------------------------------*/
 
 bool TownMessage::show(XeenEngine *vm, int portrait, const Common::String &name,
diff --git a/engines/xeen/town.h b/engines/xeen/town.h
index 5aa31e5..c64ef89 100644
--- a/engines/xeen/town.h
+++ b/engines/xeen/town.h
@@ -105,6 +105,8 @@ public:
 	void drawTownAnim(bool flag);
 
 	bool isActive() const;
+
+	void clearSprites();
 };
 
 class TownMessage : public ButtonContainer {


Commit: 652a6623156b6c6bba8ca49e038945fd0c2b7780
    https://github.com/scummvm/scummvm/commit/652a6623156b6c6bba8ca49e038945fd0c2b7780
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-03-04T08:49:05-05:00

Commit Message:
XEEN: Implement cmdChooseNumeric script opcode

Changed paths:
    engines/xeen/dialogs_input.cpp
    engines/xeen/dialogs_input.h
    engines/xeen/scripts.cpp
    engines/xeen/xeen.h



diff --git a/engines/xeen/dialogs_input.cpp b/engines/xeen/dialogs_input.cpp
index 3626441..8b754ab 100644
--- a/engines/xeen/dialogs_input.cpp
+++ b/engines/xeen/dialogs_input.cpp
@@ -201,5 +201,79 @@ int NumericInput::execute(int maxLength, int maxWidth) {
 		return 0;
 }
 
+/*------------------------------------------------------------------------*/
+
+int Choose123::show(XeenEngine *vm, int numOptions) {
+	assert(numOptions <= 3);
+	Choose123 *dlg = new Choose123(vm);
+	int result = dlg->execute(numOptions);
+	delete dlg;
+
+	return result;
+}
+
+int Choose123::execute(int numOptions) {
+	EventsManager &events = *_vm->_events;
+	Interface &intf = *_vm->_interface;
+	Screen &screen = *_vm->_screen;
+	Town &town = *_vm->_town;
+	
+	Mode oldMode = _vm->_mode;
+	_vm->_mode = MODE_DIALOG_123;
+
+	loadButtons(numOptions);
+	_iconSprites.draw(screen, 7, Common::Point(232, 74));
+	drawButtons(&screen);
+	screen._windows[34].update();
+
+	int result = -1;
+	while (result == -1) {
+		do {
+			events.updateGameCounter();
+			int delay;
+			if (town.isActive()) {
+				town.drawTownAnim(true);
+				delay = 3;
+			} else {
+				intf.draw3d(true);
+				delay = 1;
+			}
+
+			events.wait(delay, true);
+			if (_vm->shouldQuit())
+				return 0;
+		} while (!_buttonValue);
+
+		switch (_buttonValue) {
+		case Common::KEYCODE_ESCAPE:
+			result = 0;
+			break;
+		case Common::KEYCODE_1:
+		case Common::KEYCODE_2:
+		case Common::KEYCODE_3: {
+			int v = _buttonValue - Common::KEYCODE_1 + 1;
+			if (v <= numOptions)
+				result = v;
+			break;
+		}
+		default:
+			break;
+		}
+	}
+
+	_vm->_mode = oldMode;
+	intf.mainIconsPrint();
+}
+
+void Choose123::loadButtons(int numOptions) {
+	_iconSprites.load("choose.icn");
+
+	if (numOptions >= 1)
+		addButton(Common::Rect(235, 75, 259, 95), Common::KEYCODE_1, &_iconSprites);
+	if (numOptions >= 2)
+		addButton(Common::Rect(260, 75, 284, 95), Common::KEYCODE_2, &_iconSprites);
+	if (numOptions >= 3)
+		addButton(Common::Rect(286, 75, 311, 95), Common::KEYCODE_3, &_iconSprites);
+}
 
 } // End of namespace Xeen
diff --git a/engines/xeen/dialogs_input.h b/engines/xeen/dialogs_input.h
index 30e4cb2..2f30b73 100644
--- a/engines/xeen/dialogs_input.h
+++ b/engines/xeen/dialogs_input.h
@@ -64,6 +64,20 @@ public:
 	static int show(XeenEngine *vm, int window, int maxLength, int maxWidth);
 };
 
+class Choose123 : public ButtonContainer {
+private:
+	XeenEngine *_vm;
+	SpriteResource _iconSprites;
+
+	Choose123(XeenEngine *vm) : ButtonContainer(), _vm(vm) {}
+
+	int execute(int numOptions);
+
+	void loadButtons(int numOptions);
+public:
+	static int show(XeenEngine *vm, int numOptions);
+};
+
 } // End of namespace Xeen
 
 #endif /* XEEN_DIALOGS_STRING_INPUT_H */
diff --git a/engines/xeen/scripts.cpp b/engines/xeen/scripts.cpp
index 1656acd..790e3d7 100644
--- a/engines/xeen/scripts.cpp
+++ b/engines/xeen/scripts.cpp
@@ -954,7 +954,20 @@ void Scripts::cmdConfirmWord(Common::Array<byte> &params) {
 	cmdNoAction(params);
 }
 
-void Scripts::cmdDamage(Common::Array<byte> &params) { error("TODO"); }
+void Scripts::cmdDamage(Common::Array<byte> &params) {
+	Combat &combat = *_vm->_combat;
+	Interface &intf = *_vm->_interface;
+
+	if (!_redrawDone) {
+		intf.draw3d(true);
+		_redrawDone = true;
+	}
+
+	int damage = (params[1] << 8) | params[0];
+	combat.giveCharDamage(damage, (DamageType)params[2], _charIndex);
+
+	cmdNoAction(params);
+}
 
 /**
  * Jump if a random number matches a given value
@@ -1164,7 +1177,6 @@ void Scripts::cmdSelRndChar(Common::Array<byte> &params) {
 
 void Scripts::cmdGiveEnchanted(Common::Array<byte> &params) {
 	Party &party = *_vm->_party;
-	bool isDarkCc = _vm->_files->_isDarkCc;
 
 	if (params[0] >= 35) {
 		if (params[0] < 49) {
@@ -1257,12 +1269,20 @@ void Scripts::cmdCheckProtection(Common::Array<byte> &params) {
 		cmdExit(params);
 }
 
+/**
+ * Given a number of options, and a list of line numbers associated with
+ * those options, jumps to whichever line for the option the user selects
+ */
 void Scripts::cmdChooseNumeric(Common::Array<byte> &params) {
-	error("TODO");
+	int choice = Choose123::show(_vm, params[0]);
+	if (choice) {
+		_lineNum = params[choice] - 1;
+	}
+
+	cmdNoAction(params);
 }
 
 void Scripts::cmdDisplayBottomTwoLines(Common::Array<byte> &params) {
-	Interface &intf = *_vm->_interface;
 	Map &map = *_vm->_map;
 	Window &w = _vm->_screen->_windows[12];
 
diff --git a/engines/xeen/xeen.h b/engines/xeen/xeen.h
index 7185941..4180a17 100644
--- a/engines/xeen/xeen.h
+++ b/engines/xeen/xeen.h
@@ -88,6 +88,7 @@ enum Mode {
 	MODE_9 = 9,
 	MODE_CHARACTER_INFO = 10,
 	MODE_12 = 12,
+	MODE_DIALOG_123 = 13,
 	MODE_17 = 17,
 	MODE_86 = 86
 };


Commit: b0016071ecf3f5ffbc6f1619af610ab648bbba3a
    https://github.com/scummvm/scummvm/commit/b0016071ecf3f5ffbc6f1619af610ab648bbba3a
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-10-12T15:18:03-04:00

Commit Message:
Merge branch 'msvc_2015' into xeen

Changed paths:
  A audio/adlib.cpp
  A audio/alsa_opl.cpp
  A audio/decoders/3do.cpp
  A audio/decoders/3do.h
  A audio/miles.h
  A audio/miles_adlib.cpp
  A audio/miles_mt32.cpp
  A audio/softsynth/mt32/Analog.cpp
  A audio/softsynth/mt32/Analog.h
  A audio/softsynth/mt32/MemoryRegion.h
  A audio/softsynth/mt32/MidiEventQueue.h
  A audio/softsynth/mt32/Types.h
  A audio/softsynth/mt32/internals.h
  A backends/platform/sdl/sdl-window.cpp
  A backends/platform/sdl/sdl-window.h
  A backends/platform/sdl/win32/win32-window.cpp
  A backends/platform/sdl/win32/win32-window.h
  A backends/platform/symbian/mmp/scummvm_access.mmp.in
  A backends/platform/symbian/mmp/scummvm_prince.mmp.in
  A devtools/create_project/msvc14/create_project.sln
  A devtools/create_project/msvc14/create_project.vcxproj
  A devtools/create_project/msvc14/create_project.vcxproj.filters
  A dists/android/custom_rules.xml
  A dists/android/jni/Android.mk
  A dists/android/project.properties
  A dists/msvc14/create_msvc14.bat
  A dists/msvc14/readme.txt
  A doc/de/Spieletitel Original-Deutsch Deutsch-Original
  A engines/access/martian/martian_player.cpp
  A engines/access/martian/martian_player.h
  A engines/agos/drivers/accolade/adlib.cpp
  A engines/agos/drivers/accolade/driverfile.cpp
  A engines/agos/drivers/accolade/mididriver.h
  A engines/agos/drivers/accolade/mt32.cpp
  A engines/agos/drivers/simon1/adlib.cpp
  A engines/agos/drivers/simon1/adlib.h
  A engines/mads/phantom/globals_phantom.cpp
  A engines/mads/phantom/globals_phantom.h
  A engines/mads/phantom/phantom_scenes1.cpp
  A engines/mads/phantom/phantom_scenes1.h
  A engines/queen/midiadlib.h
  A engines/sherlock/animation.cpp
  A engines/sherlock/animation.h
  A engines/sherlock/configure.engine
  A engines/sherlock/debugger.cpp
  A engines/sherlock/debugger.h
  A engines/sherlock/decompress.cpp
  A engines/sherlock/detection.cpp
  A engines/sherlock/detection_tables.h
  A engines/sherlock/events.cpp
  A engines/sherlock/events.h
  A engines/sherlock/fixed_text.cpp
  A engines/sherlock/fixed_text.h
  A engines/sherlock/fonts.cpp
  A engines/sherlock/fonts.h
  A engines/sherlock/image_file.cpp
  A engines/sherlock/image_file.h
  A engines/sherlock/inventory.cpp
  A engines/sherlock/inventory.h
  A engines/sherlock/journal.cpp
  A engines/sherlock/journal.h
  A engines/sherlock/map.cpp
  A engines/sherlock/map.h
  A engines/sherlock/module.mk
  A engines/sherlock/music.cpp
  A engines/sherlock/music.h
  A engines/sherlock/objects.cpp
  A engines/sherlock/objects.h
  A engines/sherlock/people.cpp
  A engines/sherlock/people.h
  A engines/sherlock/resources.cpp
  A engines/sherlock/resources.h
  A engines/sherlock/saveload.cpp
  A engines/sherlock/saveload.h
  A engines/sherlock/scalpel/3do/movie_decoder.cpp
  A engines/sherlock/scalpel/3do/movie_decoder.h
  A engines/sherlock/scalpel/drivers/adlib.cpp
  A engines/sherlock/scalpel/drivers/mididriver.h
  A engines/sherlock/scalpel/drivers/mt32.cpp
  A engines/sherlock/scalpel/scalpel.cpp
  A engines/sherlock/scalpel/scalpel.h
  A engines/sherlock/scalpel/scalpel_darts.cpp
  A engines/sherlock/scalpel/scalpel_darts.h
  A engines/sherlock/scalpel/scalpel_debugger.cpp
  A engines/sherlock/scalpel/scalpel_debugger.h
  A engines/sherlock/scalpel/scalpel_fixed_text.cpp
  A engines/sherlock/scalpel/scalpel_fixed_text.h
  A engines/sherlock/scalpel/scalpel_inventory.cpp
  A engines/sherlock/scalpel/scalpel_inventory.h
  A engines/sherlock/scalpel/scalpel_journal.cpp
  A engines/sherlock/scalpel/scalpel_journal.h
  A engines/sherlock/scalpel/scalpel_map.cpp
  A engines/sherlock/scalpel/scalpel_map.h
  A engines/sherlock/scalpel/scalpel_people.cpp
  A engines/sherlock/scalpel/scalpel_people.h
  A engines/sherlock/scalpel/scalpel_saveload.cpp
  A engines/sherlock/scalpel/scalpel_saveload.h
  A engines/sherlock/scalpel/scalpel_scene.cpp
  A engines/sherlock/scalpel/scalpel_scene.h
  A engines/sherlock/scalpel/scalpel_screen.cpp
  A engines/sherlock/scalpel/scalpel_screen.h
  A engines/sherlock/scalpel/scalpel_talk.cpp
  A engines/sherlock/scalpel/scalpel_talk.h
  A engines/sherlock/scalpel/scalpel_user_interface.cpp
  A engines/sherlock/scalpel/scalpel_user_interface.h
  A engines/sherlock/scalpel/settings.cpp
  A engines/sherlock/scalpel/settings.h
  A engines/sherlock/scalpel/tsage/logo.cpp
  A engines/sherlock/scalpel/tsage/logo.h
  A engines/sherlock/scalpel/tsage/resources.cpp
  A engines/sherlock/scalpel/tsage/resources.h
  A engines/sherlock/scene.cpp
  A engines/sherlock/scene.h
  A engines/sherlock/screen.cpp
  A engines/sherlock/screen.h
  A engines/sherlock/sherlock.cpp
  A engines/sherlock/sherlock.h
  A engines/sherlock/sound.cpp
  A engines/sherlock/sound.h
  A engines/sherlock/surface.cpp
  A engines/sherlock/surface.h
  A engines/sherlock/talk.cpp
  A engines/sherlock/talk.h
  A engines/sherlock/tattoo/tattoo.cpp
  A engines/sherlock/tattoo/tattoo.h
  A engines/sherlock/tattoo/tattoo_darts.cpp
  A engines/sherlock/tattoo/tattoo_darts.h
  A engines/sherlock/tattoo/tattoo_debugger.cpp
  A engines/sherlock/tattoo/tattoo_debugger.h
  A engines/sherlock/tattoo/tattoo_fixed_text.cpp
  A engines/sherlock/tattoo/tattoo_fixed_text.h
  A engines/sherlock/tattoo/tattoo_inventory.cpp
  A engines/sherlock/tattoo/tattoo_inventory.h
  A engines/sherlock/tattoo/tattoo_journal.cpp
  A engines/sherlock/tattoo/tattoo_journal.h
  A engines/sherlock/tattoo/tattoo_map.cpp
  A engines/sherlock/tattoo/tattoo_map.h
  A engines/sherlock/tattoo/tattoo_people.cpp
  A engines/sherlock/tattoo/tattoo_people.h
  A engines/sherlock/tattoo/tattoo_resources.cpp
  A engines/sherlock/tattoo/tattoo_resources.h
  A engines/sherlock/tattoo/tattoo_scene.cpp
  A engines/sherlock/tattoo/tattoo_scene.h
  A engines/sherlock/tattoo/tattoo_talk.cpp
  A engines/sherlock/tattoo/tattoo_talk.h
  A engines/sherlock/tattoo/tattoo_user_interface.cpp
  A engines/sherlock/tattoo/tattoo_user_interface.h
  A engines/sherlock/tattoo/widget_base.cpp
  A engines/sherlock/tattoo/widget_base.h
  A engines/sherlock/tattoo/widget_credits.cpp
  A engines/sherlock/tattoo/widget_credits.h
  A engines/sherlock/tattoo/widget_files.cpp
  A engines/sherlock/tattoo/widget_files.h
  A engines/sherlock/tattoo/widget_foolscap.cpp
  A engines/sherlock/tattoo/widget_foolscap.h
  A engines/sherlock/tattoo/widget_inventory.cpp
  A engines/sherlock/tattoo/widget_inventory.h
  A engines/sherlock/tattoo/widget_lab.cpp
  A engines/sherlock/tattoo/widget_lab.h
  A engines/sherlock/tattoo/widget_options.cpp
  A engines/sherlock/tattoo/widget_options.h
  A engines/sherlock/tattoo/widget_password.cpp
  A engines/sherlock/tattoo/widget_password.h
  A engines/sherlock/tattoo/widget_quit.cpp
  A engines/sherlock/tattoo/widget_quit.h
  A engines/sherlock/tattoo/widget_talk.cpp
  A engines/sherlock/tattoo/widget_talk.h
  A engines/sherlock/tattoo/widget_text.cpp
  A engines/sherlock/tattoo/widget_text.h
  A engines/sherlock/tattoo/widget_tooltip.cpp
  A engines/sherlock/tattoo/widget_tooltip.h
  A engines/sherlock/tattoo/widget_verbs.cpp
  A engines/sherlock/tattoo/widget_verbs.h
  A engines/sherlock/user_interface.cpp
  A engines/sherlock/user_interface.h
  A engines/sword25/util/double_serialization.cpp
  A engines/sword25/util/double_serialization.h
  A engines/sword25/util/lua_persist.cpp
  A engines/sword25/util/lua_persistence.h
  A engines/sword25/util/lua_persistence_util.cpp
  A engines/sword25/util/lua_persistence_util.h
  A engines/sword25/util/lua_unpersist.cpp
  A engines/tsage/sherlock/sherlock_logo.cpp
  A engines/tsage/sherlock/sherlock_logo.h
  A engines/zvision/detection_tables.h
  A engines/zvision/file/save_manager.cpp
  A engines/zvision/file/save_manager.h
  A engines/zvision/graphics/graphics_effect.h
  A engines/zvision/scripting/effects/animation_effect.cpp
  A engines/zvision/scripting/effects/animation_effect.h
  A engines/zvision/scripting/effects/distort_effect.cpp
  A engines/zvision/scripting/effects/distort_effect.h
  A engines/zvision/scripting/effects/music_effect.cpp
  A engines/zvision/scripting/effects/music_effect.h
  A engines/zvision/scripting/effects/region_effect.cpp
  A engines/zvision/scripting/effects/region_effect.h
  A engines/zvision/scripting/effects/syncsound_effect.cpp
  A engines/zvision/scripting/effects/syncsound_effect.h
  A engines/zvision/scripting/effects/timer_effect.cpp
  A engines/zvision/scripting/effects/timer_effect.h
  A engines/zvision/scripting/effects/ttytext_effect.cpp
  A engines/zvision/scripting/effects/ttytext_effect.h
  A engines/zvision/scripting/menu.cpp
  A engines/zvision/scripting/menu.h
  A engines/zvision/scripting/scripting_effect.h
  A engines/zvision/text/subtitles.cpp
  A engines/zvision/text/subtitles.h
  A engines/zvision/text/truetype_font.cpp
  A engines/zvision/text/truetype_font.h
  A image/codecs/cinepak_tables.h
  A video/mpegps_decoder.cpp
  A video/mpegps_decoder.h
  R audio/softsynth/adlib.cpp
  R backends/platform/android/org/scummvm/scummvm/PluginProvider.java
  R backends/platform/android/org/scummvm/scummvm/ScummVMApplication.java
  R backends/platform/android/org/scummvm/scummvm/Unpacker.java
  R dists/android/mkplugin.sh
  R dists/android/plugin-manifest.xml
  R dists/android/plugin-manifest.xml.in
  R dists/android/plugin-strings.xml
  R dists/android/res/drawable/gradient.xml
  R dists/android/res/layout/splash.xml
  R dists/iphone/readme.txt
  R dists/iphone/scummvm.xcodeproj/project.pbxproj
  R engines/sword25/util/pluto/CHANGELOG
  R engines/sword25/util/pluto/FILEFORMAT
  R engines/sword25/util/pluto/README
  R engines/sword25/util/pluto/THANKS
  R engines/sword25/util/pluto/pdep.cpp
  R engines/sword25/util/pluto/pdep/README
  R engines/sword25/util/pluto/pdep/lzio.h
  R engines/sword25/util/pluto/pdep/pdep.h
  R engines/sword25/util/pluto/pluto.cpp
  R engines/sword25/util/pluto/pluto.h
  R engines/sword25/util/pluto/plzio.cpp
  R engines/zvision/core/menu.cpp
  R engines/zvision/core/menu.h
  R engines/zvision/core/save_manager.cpp
  R engines/zvision/core/save_manager.h
  R engines/zvision/detection.h
  R engines/zvision/graphics/effect.h
  R engines/zvision/graphics/subtitles.cpp
  R engines/zvision/graphics/subtitles.h
  R engines/zvision/graphics/truetype_font.cpp
  R engines/zvision/graphics/truetype_font.h
  R engines/zvision/scripting/sidefx.h
  R engines/zvision/scripting/sidefx/animation_node.cpp
  R engines/zvision/scripting/sidefx/animation_node.h
  R engines/zvision/scripting/sidefx/distort_node.cpp
  R engines/zvision/scripting/sidefx/distort_node.h
  R engines/zvision/scripting/sidefx/music_node.cpp
  R engines/zvision/scripting/sidefx/music_node.h
  R engines/zvision/scripting/sidefx/region_node.cpp
  R engines/zvision/scripting/sidefx/region_node.h
  R engines/zvision/scripting/sidefx/syncsound_node.cpp
  R engines/zvision/scripting/sidefx/syncsound_node.h
  R engines/zvision/scripting/sidefx/timer_node.cpp
  R engines/zvision/scripting/sidefx/timer_node.h
  R engines/zvision/scripting/sidefx/ttytext_node.cpp
  R engines/zvision/scripting/sidefx/ttytext_node.h
    AUTHORS
    COPYRIGHT
    Makefile
    NEWS
    README
    audio/audiostream.cpp
    audio/audiostream.h
    audio/decoders/adpcm.cpp
    audio/decoders/adpcm.h
    audio/decoders/aiff.cpp
    audio/decoders/aiff.h
    audio/decoders/codec.h
    audio/decoders/mp3.cpp
    audio/decoders/mp3.h
    audio/decoders/quicktime.cpp
    audio/decoders/raw.cpp
    audio/decoders/raw.h
    audio/decoders/wave.h
    audio/fmopl.cpp
    audio/fmopl.h
    audio/midiparser.h
    audio/midiparser_xmidi.cpp
    audio/mods/protracker.cpp
    audio/module.mk
    audio/softsynth/mt32/BReverbModel.cpp
    audio/softsynth/mt32/BReverbModel.h
    audio/softsynth/mt32/LA32FloatWaveGenerator.cpp
    audio/softsynth/mt32/LA32Ramp.cpp
    audio/softsynth/mt32/LA32WaveGenerator.cpp
    audio/softsynth/mt32/Part.cpp
    audio/softsynth/mt32/Partial.cpp
    audio/softsynth/mt32/PartialManager.cpp
    audio/softsynth/mt32/Poly.cpp
    audio/softsynth/mt32/Poly.h
    audio/softsynth/mt32/ROMInfo.cpp
    audio/softsynth/mt32/ROMInfo.h
    audio/softsynth/mt32/Structures.h
    audio/softsynth/mt32/Synth.cpp
    audio/softsynth/mt32/Synth.h
    audio/softsynth/mt32/TVA.cpp
    audio/softsynth/mt32/TVF.cpp
    audio/softsynth/mt32/TVP.cpp
    audio/softsynth/mt32/Tables.cpp
    audio/softsynth/mt32/Tables.h
    audio/softsynth/mt32/module.mk
    audio/softsynth/mt32/mt32emu.h
    audio/softsynth/opl/dosbox.cpp
    audio/softsynth/opl/dosbox.h
    audio/softsynth/opl/mame.cpp
    audio/softsynth/opl/mame.h
    audio/timestamp.cpp
    backends/audiocd/sdl/sdl-audiocd.cpp
    backends/audiocd/sdl/sdl-audiocd.h
    backends/events/sdl/sdl-events.cpp
    backends/events/sdl/sdl-events.h
    backends/events/symbiansdl/symbiansdl-events.cpp
    backends/fs/amigaos4/amigaos4-fs.cpp
    backends/graphics/dinguxsdl/dinguxsdl-graphics.cpp
    backends/graphics/dinguxsdl/dinguxsdl-graphics.h
    backends/graphics/gph/gph-graphics.cpp
    backends/graphics/gph/gph-graphics.h
    backends/graphics/linuxmotosdl/linuxmotosdl-graphics.cpp
    backends/graphics/linuxmotosdl/linuxmotosdl-graphics.h
    backends/graphics/maemosdl/maemosdl-graphics.cpp
    backends/graphics/maemosdl/maemosdl-graphics.h
    backends/graphics/opengl/opengl-graphics.cpp
    backends/graphics/opengl/opengl-graphics.h
    backends/graphics/openglsdl/openglsdl-graphics.cpp
    backends/graphics/openglsdl/openglsdl-graphics.h
    backends/graphics/openpandora/op-graphics.cpp
    backends/graphics/openpandora/op-graphics.h
    backends/graphics/samsungtvsdl/samsungtvsdl-graphics.cpp
    backends/graphics/samsungtvsdl/samsungtvsdl-graphics.h
    backends/graphics/sdl/sdl-graphics.cpp
    backends/graphics/sdl/sdl-graphics.h
    backends/graphics/surfacesdl/surfacesdl-graphics.cpp
    backends/graphics/surfacesdl/surfacesdl-graphics.h
    backends/graphics/symbiansdl/symbiansdl-graphics.cpp
    backends/graphics/symbiansdl/symbiansdl-graphics.h
    backends/graphics/wincesdl/wincesdl-graphics.cpp
    backends/graphics/wincesdl/wincesdl-graphics.h
    backends/log/log.cpp
    backends/mixer/doublebuffersdl/doublebuffersdl-mixer.cpp
    backends/mixer/sdl/sdl-mixer.cpp
    backends/module.mk
    backends/platform/android/android.cpp
    backends/platform/android/android.h
    backends/platform/android/android.mk
    backends/platform/android/jni.cpp
    backends/platform/android/jni.h
    backends/platform/android/org/scummvm/scummvm/ScummVM.java
    backends/platform/android/org/scummvm/scummvm/ScummVMActivity.java
    backends/platform/dingux/dingux.cpp
    backends/platform/gph/gph-backend.cpp
    backends/platform/linuxmoto/linuxmoto-sdl.cpp
    backends/platform/maemo/maemo.cpp
    backends/platform/maemo/maemo.h
    backends/platform/openpandora/op-backend.cpp
    backends/platform/samsungtv/samsungtv.cpp
    backends/platform/sdl/macosx/macosx.cpp
    backends/platform/sdl/macosx/macosx.h
    backends/platform/sdl/module.mk
    backends/platform/sdl/sdl-sys.h
    backends/platform/sdl/sdl.cpp
    backends/platform/sdl/sdl.h
    backends/platform/sdl/win32/win32-main.cpp
    backends/platform/sdl/win32/win32.cpp
    backends/platform/sdl/win32/win32.h
    backends/platform/symbian/AdaptAllMMPs.pl
    backends/platform/symbian/BuildPackageUpload_LocalSettings.pl
    backends/platform/symbian/README
    backends/platform/symbian/S60/ScummVM_S60.mmp.in
    backends/platform/symbian/S60/ScummVM_S60_App.mmp
    backends/platform/symbian/S60v3/ScummVM_A0000658_S60v3.mmp.in
    backends/platform/symbian/S60v3/ScummVM_S60v3.mmp.in
    backends/platform/symbian/S80/ScummVM_S80.mmp.in
    backends/platform/symbian/S80/ScummVM_S80_App.mmp
    backends/platform/symbian/S90/Scummvm_S90.mmp.in
    backends/platform/symbian/S90/Scummvm_S90_App.mmp
    backends/platform/symbian/UIQ2/ScummVM.rss
    backends/platform/symbian/UIQ3/ScummVM.rss
    backends/platform/symbian/UIQ3/ScummVM_A0000658.rss
    backends/platform/symbian/UIQ3/ScummVM_A0000658_UIQ3.mmp.in
    backends/platform/symbian/UIQ3/ScummVM_UIQ3.mmp.in
    backends/platform/symbian/UIQ3/scummvm_A0000658_loc.rss
    backends/platform/symbian/help/ScummVM.rtf
    backends/platform/symbian/mmp/config.mmh
    backends/platform/symbian/mmp/scummvm_agi.mmp.in
    backends/platform/symbian/mmp/scummvm_agos.mmp.in
    backends/platform/symbian/mmp/scummvm_avalanche.mmp.in
    backends/platform/symbian/mmp/scummvm_base.mmp.in
    backends/platform/symbian/mmp/scummvm_bbvs.mmp.in
    backends/platform/symbian/mmp/scummvm_cge.mmp.in
    backends/platform/symbian/mmp/scummvm_cge2.mmp.in
    backends/platform/symbian/mmp/scummvm_cine.mmp.in
    backends/platform/symbian/mmp/scummvm_composer.mmp.in
    backends/platform/symbian/mmp/scummvm_cruise.mmp.in
    backends/platform/symbian/mmp/scummvm_draci.mmp.in
    backends/platform/symbian/mmp/scummvm_drascula.mmp.in
    backends/platform/symbian/mmp/scummvm_dreamweb.mmp.in
    backends/platform/symbian/mmp/scummvm_fullpipe.mmp.in
    backends/platform/symbian/mmp/scummvm_gob.mmp.in
    backends/platform/symbian/mmp/scummvm_groovie.mmp.in
    backends/platform/symbian/mmp/scummvm_hopkins.mmp.in
    backends/platform/symbian/mmp/scummvm_hugo.mmp.in
    backends/platform/symbian/mmp/scummvm_kyra.mmp.in
    backends/platform/symbian/mmp/scummvm_lastexpress.mmp.in
    backends/platform/symbian/mmp/scummvm_lure.mmp.in
    backends/platform/symbian/mmp/scummvm_m4.mmp.in
    backends/platform/symbian/mmp/scummvm_made.mmp.in
    backends/platform/symbian/mmp/scummvm_mads.mmp.in
    backends/platform/symbian/mmp/scummvm_mohawk.mmp.in
    backends/platform/symbian/mmp/scummvm_mortevielle.mmp.in
    backends/platform/symbian/mmp/scummvm_neverhood.mmp.in
    backends/platform/symbian/mmp/scummvm_parallaction.mmp.in
    backends/platform/symbian/mmp/scummvm_pegasus.mmp.in
    backends/platform/symbian/mmp/scummvm_queen.mmp.in
    backends/platform/symbian/mmp/scummvm_saga.mmp.in
    backends/platform/symbian/mmp/scummvm_sci.mmp.in
    backends/platform/symbian/mmp/scummvm_scumm.mmp.in
    backends/platform/symbian/mmp/scummvm_sky.mmp.in
    backends/platform/symbian/mmp/scummvm_sword1.mmp.in
    backends/platform/symbian/mmp/scummvm_sword2.mmp.in
    backends/platform/symbian/mmp/scummvm_sword25.mmp.in
    backends/platform/symbian/mmp/scummvm_teenagent.mmp.in
    backends/platform/symbian/mmp/scummvm_testbed.mmp.in
    backends/platform/symbian/mmp/scummvm_tinsel.mmp.in
    backends/platform/symbian/mmp/scummvm_toltecs.mmp.in
    backends/platform/symbian/mmp/scummvm_tony.mmp.in
    backends/platform/symbian/mmp/scummvm_toon.mmp.in
    backends/platform/symbian/mmp/scummvm_touche.mmp.in
    backends/platform/symbian/mmp/scummvm_tsage.mmp.in
    backends/platform/symbian/mmp/scummvm_tucker.mmp.in
    backends/platform/symbian/mmp/scummvm_voyeur.mmp.in
    backends/platform/symbian/mmp/scummvm_wintermute.mmp.in
    backends/platform/symbian/mmp/scummvm_zvision.mmp.in
    backends/platform/symbian/res/ScummVmAif.rss
    backends/platform/symbian/res/scummvm.rss
    backends/platform/symbian/res/scummvm_A0000658.rss
    backends/platform/symbian/src/ScummVm.hrh
    backends/platform/symbian/src/SymbianOS.cpp
    backends/platform/symbian/src/SymbianOS.h
    backends/platform/symbian/src/portdefs.h
    backends/platform/wince/wince-sdl.cpp
    backends/saves/default/default-saves.cpp
    backends/taskbar/win32/win32-taskbar.cpp
    backends/taskbar/win32/win32-taskbar.h
    base/main.cpp
    common/dcl.cpp
    common/dcl.h
    common/endian.h
    common/fft.cpp
    common/fft.h
    common/scummsys.h
    common/stream.h
    configure
    devtools/README
    devtools/create_mortdat/create_mortdat.cpp
    devtools/create_mortdat/menudata.h
    devtools/create_project/create_project.cpp
    devtools/create_project/msbuild.cpp
    devtools/create_project/msbuild.h
    devtools/create_project/msvc.cpp
    devtools/create_project/msvc.h
    devtools/create_project/visualstudio.cpp
    devtools/create_project/xcode.cpp
    devtools/create_project/xcode.h
    devtools/credits.pl
    devtools/scumm-md5.txt
    dists/android/AndroidManifest.xml
    dists/android/AndroidManifest.xml.in
    dists/android/res/layout/main.xml
    dists/codeblocks/readme.txt
    dists/debian/copyright
    dists/engine-data/mort.dat
    dists/macosx/Info.plist
    dists/macosx/Info.plist.in
    dists/scummvm.rc
    dists/scummvm.rc.in
    dists/win32/scummvm.nsi
    dists/win32/scummvm.nsi.in
    doc/cz/PrectiMe
    doc/de/Liesmich
    doc/de/Neues
    engines/access/access.cpp
    engines/access/access.h
    engines/access/amazon/amazon_game.cpp
    engines/access/amazon/amazon_logic.cpp
    engines/access/amazon/amazon_player.cpp
    engines/access/amazon/amazon_resources.cpp
    engines/access/amazon/amazon_resources.h
    engines/access/amazon/amazon_scripts.cpp
    engines/access/amazon/amazon_scripts.h
    engines/access/animation.cpp
    engines/access/animation.h
    engines/access/asurface.cpp
    engines/access/asurface.h
    engines/access/bubble_box.cpp
    engines/access/bubble_box.h
    engines/access/char.cpp
    engines/access/char.h
    engines/access/decompress.cpp
    engines/access/decompress.h
    engines/access/detection_tables.h
    engines/access/events.cpp
    engines/access/files.cpp
    engines/access/files.h
    engines/access/inventory.cpp
    engines/access/inventory.h
    engines/access/martian/martian_game.cpp
    engines/access/martian/martian_game.h
    engines/access/martian/martian_resources.cpp
    engines/access/martian/martian_resources.h
    engines/access/martian/martian_room.cpp
    engines/access/martian/martian_room.h
    engines/access/martian/martian_scripts.cpp
    engines/access/martian/martian_scripts.h
    engines/access/module.mk
    engines/access/player.cpp
    engines/access/player.h
    engines/access/resources.cpp
    engines/access/resources.h
    engines/access/room.cpp
    engines/access/room.h
    engines/access/screen.cpp
    engines/access/screen.h
    engines/access/scripts.cpp
    engines/access/scripts.h
    engines/access/sound.cpp
    engines/access/sound.h
    engines/access/video.cpp
    engines/access/video.h
    engines/agi/agi.cpp
    engines/agi/agi.h
    engines/agi/detection.cpp
    engines/agi/detection_tables.h
    engines/agi/font.h
    engines/agi/graphics.cpp
    engines/agi/graphics.h
    engines/agi/loader_v2.cpp
    engines/agi/loader_v3.cpp
    engines/agi/preagi.cpp
    engines/agi/preagi_mickey.cpp
    engines/agi/sound_pcjr.cpp
    engines/agi/text.cpp
    engines/agos/agos.cpp
    engines/agos/detection_tables.h
    engines/agos/gfx.cpp
    engines/agos/input.cpp
    engines/agos/midi.cpp
    engines/agos/midi.h
    engines/agos/midiparser_s1d.cpp
    engines/agos/module.mk
    engines/agos/res_snd.cpp
    engines/agos/rooms.cpp
    engines/agos/saveload.cpp
    engines/agos/sound.cpp
    engines/agos/zones.cpp
    engines/bbvs/minigames/bbairguitar.cpp
    engines/bbvs/minigames/bbairguitar.h
    engines/bbvs/sound.h
    engines/cge2/detection.cpp
    engines/cine/cine.cpp
    engines/cine/detection_tables.h
    engines/cine/main_loop.cpp
    engines/cine/saveload.cpp
    engines/cine/script_fw.cpp
    engines/cine/sound.cpp
    engines/cine/sound.h
    engines/cruise/sound.cpp
    engines/drascula/actors.cpp
    engines/drascula/detection.cpp
    engines/drascula/talk.cpp
    engines/engine.cpp
    engines/engine.h
    engines/fullpipe/gameloader.cpp
    engines/fullpipe/inventory.cpp
    engines/fullpipe/mgm.cpp
    engines/fullpipe/modal.cpp
    engines/fullpipe/motion.cpp
    engines/fullpipe/scene.cpp
    engines/fullpipe/scenes/scene04.cpp
    engines/fullpipe/scenes/scene16.cpp
    engines/fullpipe/scenes/scene23.cpp
    engines/fullpipe/statics.cpp
    engines/gob/gob.cpp
    engines/gob/map_v2.cpp
    engines/gob/sound/adlib.cpp
    engines/gob/sound/adlib.h
    engines/gob/sound/adlplayer.cpp
    engines/gob/sound/adlplayer.h
    engines/gob/sound/cdrom.cpp
    engines/gob/sound/musplayer.cpp
    engines/gob/sound/musplayer.h
    engines/gob/sound/sound.cpp
    engines/gob/sound/sound.h
    engines/gob/surface.cpp
    engines/gob/surface.h
    engines/groovie/music.cpp
    engines/groovie/music.h
    engines/hopkins/computer.cpp
    engines/hopkins/lines.cpp
    engines/hugo/mouse.cpp
    engines/kyra/sound_adlib.cpp
    engines/lastexpress/data/snd.cpp
    engines/lastexpress/data/snd.h
    engines/lure/res.h
    engines/made/database.cpp
    engines/made/made.cpp
    engines/made/music.cpp
    engines/made/music.h
    engines/made/pmvplayer.cpp
    engines/made/redreader.cpp
    engines/made/resource.cpp
    engines/made/screenfx.cpp
    engines/made/screenfx.h
    engines/made/script.cpp
    engines/made/script.h
    engines/made/scriptfuncs.cpp
    engines/made/sound.cpp
    engines/made/sound.h
    engines/mads/action.cpp
    engines/mads/action.h
    engines/mads/animation.cpp
    engines/mads/animation.h
    engines/mads/assets.cpp
    engines/mads/assets.h
    engines/mads/audio.cpp
    engines/mads/audio.h
    engines/mads/compression.cpp
    engines/mads/compression.h
    engines/mads/debugger.cpp
    engines/mads/debugger.h
    engines/mads/detection.cpp
    engines/mads/detection_tables.h
    engines/mads/dialogs.cpp
    engines/mads/dialogs.h
    engines/mads/dragonsphere/dragonsphere_scenes.cpp
    engines/mads/dragonsphere/dragonsphere_scenes.h
    engines/mads/dragonsphere/game_dragonsphere.cpp
    engines/mads/dragonsphere/game_dragonsphere.h
    engines/mads/events.cpp
    engines/mads/events.h
    engines/mads/font.cpp
    engines/mads/font.h
    engines/mads/game.cpp
    engines/mads/game.h
    engines/mads/game_data.cpp
    engines/mads/game_data.h
    engines/mads/globals.cpp
    engines/mads/globals.h
    engines/mads/hotspots.cpp
    engines/mads/hotspots.h
    engines/mads/inventory.cpp
    engines/mads/inventory.h
    engines/mads/mads.cpp
    engines/mads/mads.h
    engines/mads/menu_views.cpp
    engines/mads/menu_views.h
    engines/mads/messages.cpp
    engines/mads/messages.h
    engines/mads/module.mk
    engines/mads/msurface.cpp
    engines/mads/msurface.h
    engines/mads/nebular/dialogs_nebular.cpp
    engines/mads/nebular/dialogs_nebular.h
    engines/mads/nebular/game_nebular.cpp
    engines/mads/nebular/game_nebular.h
    engines/mads/nebular/globals_nebular.cpp
    engines/mads/nebular/globals_nebular.h
    engines/mads/nebular/menu_nebular.cpp
    engines/mads/nebular/menu_nebular.h
    engines/mads/nebular/nebular_scenes.cpp
    engines/mads/nebular/nebular_scenes.h
    engines/mads/nebular/nebular_scenes1.cpp
    engines/mads/nebular/nebular_scenes1.h
    engines/mads/nebular/nebular_scenes2.cpp
    engines/mads/nebular/nebular_scenes2.h
    engines/mads/nebular/nebular_scenes3.cpp
    engines/mads/nebular/nebular_scenes3.h
    engines/mads/nebular/nebular_scenes4.cpp
    engines/mads/nebular/nebular_scenes4.h
    engines/mads/nebular/nebular_scenes5.cpp
    engines/mads/nebular/nebular_scenes5.h
    engines/mads/nebular/nebular_scenes6.cpp
    engines/mads/nebular/nebular_scenes6.h
    engines/mads/nebular/nebular_scenes7.cpp
    engines/mads/nebular/nebular_scenes7.h
    engines/mads/nebular/nebular_scenes8.cpp
    engines/mads/nebular/nebular_scenes8.h
    engines/mads/nebular/sound_nebular.cpp
    engines/mads/nebular/sound_nebular.h
    engines/mads/palette.cpp
    engines/mads/palette.h
    engines/mads/phantom/game_phantom.cpp
    engines/mads/phantom/game_phantom.h
    engines/mads/phantom/phantom_scenes.cpp
    engines/mads/phantom/phantom_scenes.h
    engines/mads/player.cpp
    engines/mads/player.h
    engines/mads/rails.cpp
    engines/mads/rails.h
    engines/mads/resources.cpp
    engines/mads/resources.h
    engines/mads/scene.cpp
    engines/mads/scene.h
    engines/mads/scene_data.cpp
    engines/mads/scene_data.h
    engines/mads/screen.cpp
    engines/mads/screen.h
    engines/mads/sequence.cpp
    engines/mads/sequence.h
    engines/mads/sound.cpp
    engines/mads/sound.h
    engines/mads/sprites.cpp
    engines/mads/sprites.h
    engines/mads/staticres.cpp
    engines/mads/staticres.h
    engines/mads/user_interface.cpp
    engines/mads/user_interface.h
    engines/mohawk/configure.engine
    engines/mohawk/console.cpp
    engines/mohawk/cursors.cpp
    engines/mohawk/detection_tables.h
    engines/mohawk/livingbooks.cpp
    engines/mohawk/livingbooks_code.cpp
    engines/mohawk/livingbooks_code.h
    engines/mohawk/myst.cpp
    engines/mohawk/myst_areas.cpp
    engines/mohawk/myst_graphics.cpp
    engines/mohawk/myst_graphics.h
    engines/mohawk/myst_stacks/channelwood.cpp
    engines/mohawk/myst_stacks/dni.cpp
    engines/mohawk/myst_stacks/intro.cpp
    engines/mohawk/myst_stacks/mechanical.cpp
    engines/mohawk/myst_stacks/myst.cpp
    engines/mohawk/myst_stacks/stoneship.cpp
    engines/mohawk/riven.cpp
    engines/mohawk/riven_external.cpp
    engines/mohawk/riven_scripts.cpp
    engines/mohawk/sound.cpp
    engines/mohawk/sound.h
    engines/mohawk/video.cpp
    engines/mohawk/video.h
    engines/mortevielle/actions.cpp
    engines/mortevielle/detection_tables.h
    engines/mortevielle/dialogs.cpp
    engines/mortevielle/graphics.cpp
    engines/mortevielle/menu.cpp
    engines/mortevielle/mortevielle.h
    engines/mortevielle/outtext.cpp
    engines/mortevielle/sound.cpp
    engines/mortevielle/utils.cpp
    engines/neverhood/menumodule.cpp
    engines/parallaction/adlib.cpp
    engines/pegasus/menu.cpp
    engines/pegasus/sound.cpp
    engines/queen/midiadlib.cpp
    engines/queen/music.cpp
    engines/queen/walk.cpp
    engines/saga/detection_tables.h
    engines/saga/introproc_ihnm.cpp
    engines/saga/introproc_ite.cpp
    engines/saga/music.cpp
    engines/saga/music.h
    engines/saga/saga.cpp
    engines/saga/saga.h
    engines/saga/scene.cpp
    engines/saga/scene.h
    engines/saga/script.cpp
    engines/saga/sndres.cpp
    engines/sci/console.cpp
    engines/sci/console.h
    engines/sci/detection.cpp
    engines/sci/detection_tables.h
    engines/sci/engine/file.cpp
    engines/sci/engine/kernel.cpp
    engines/sci/engine/kernel.h
    engines/sci/engine/kernel_tables.h
    engines/sci/engine/kevent.cpp
    engines/sci/engine/kfile.cpp
    engines/sci/engine/kgraphics.cpp
    engines/sci/engine/kmovement.cpp
    engines/sci/engine/kparse.cpp
    engines/sci/engine/kvideo.cpp
    engines/sci/engine/savegame.cpp
    engines/sci/engine/savegame.h
    engines/sci/engine/script.cpp
    engines/sci/engine/script.h
    engines/sci/engine/script_patches.cpp
    engines/sci/engine/script_patches.h
    engines/sci/engine/state.cpp
    engines/sci/engine/state.h
    engines/sci/engine/vm.cpp
    engines/sci/engine/workarounds.cpp
    engines/sci/engine/workarounds.h
    engines/sci/graphics/paint16.cpp
    engines/sci/graphics/portrait.cpp
    engines/sci/graphics/screen.cpp
    engines/sci/graphics/screen.h
    engines/sci/graphics/transitions.cpp
    engines/sci/graphics/transitions.h
    engines/sci/parser/vocabulary.cpp
    engines/sci/parser/vocabulary.h
    engines/sci/resource.h
    engines/sci/resource_audio.cpp
    engines/sci/sci.cpp
    engines/sci/sci.h
    engines/sci/sound/audio.cpp
    engines/sci/sound/drivers/adlib.cpp
    engines/sci/sound/midiparser_sci.cpp
    engines/sci/sound/music.cpp
    engines/sci/sound/music.h
    engines/sci/sound/soundcmd.cpp
    engines/sci/sound/soundcmd.h
    engines/scumm/debugger.cpp
    engines/scumm/detection_tables.h
    engines/scumm/help.cpp
    engines/scumm/imuse_digi/dimuse.cpp
    engines/scumm/imuse_digi/dimuse_track.cpp
    engines/scumm/players/player_ad.cpp
    engines/scumm/players/player_ad.h
    engines/scumm/saveload.cpp
    engines/scumm/script_v6.cpp
    engines/scumm/scumm-md5.h
    engines/scumm/scumm.cpp
    engines/scumm/scumm.h
    engines/scumm/smush/smush_player.cpp
    engines/scumm/string.cpp
    engines/sky/music/adlibchannel.cpp
    engines/sky/music/adlibchannel.h
    engines/sky/music/adlibmusic.cpp
    engines/sky/music/adlibmusic.h
    engines/sword25/fmv/movieplayer.cpp
    engines/sword25/kernel/outputpersistenceblock.cpp
    engines/sword25/kernel/outputpersistenceblock.h
    engines/sword25/module.mk
    engines/sword25/script/luascript.cpp
    engines/tinsel/music.cpp
    engines/tinsel/music.h
    engines/tinsel/tinsel.cpp
    engines/toltecs/music.cpp
    engines/toltecs/music.h
    engines/tony/mpal/mpal.cpp
    engines/tony/window.cpp
    engines/toon/anim.cpp
    engines/toon/character.cpp
    engines/toon/font.cpp
    engines/toon/toon.cpp
    engines/toon/toon.h
    engines/tsage/blue_force/blueforce_scenes8.cpp
    engines/tsage/blue_force/blueforce_scenes8.h
    engines/tsage/blue_force/blueforce_scenes9.cpp
    engines/tsage/core.cpp
    engines/tsage/detection.cpp
    engines/tsage/detection_tables.h
    engines/tsage/globals.cpp
    engines/tsage/graphics.cpp
    engines/tsage/graphics.h
    engines/tsage/module.mk
    engines/tsage/resources.h
    engines/tsage/ringworld/ringworld_scenes3.cpp
    engines/tsage/ringworld/ringworld_scenes3.h
    engines/tsage/sound.cpp
    engines/tsage/sound.h
    engines/tsage/tsage.cpp
    engines/tsage/tsage.h
    engines/voyeur/events.cpp
    engines/voyeur/files_threads.cpp
    engines/wintermute/base/base_file_manager.cpp
    engines/wintermute/base/base_keyboard_state.cpp
    engines/wintermute/base/base_keyboard_state.h
    engines/wintermute/base/base_script_holder.cpp
    engines/wintermute/debugger.cpp
    engines/zvision/POTFILES
    engines/zvision/configure.engine
    engines/zvision/core/clock.h
    engines/zvision/core/console.cpp
    engines/zvision/core/console.h
    engines/zvision/core/events.cpp
    engines/zvision/detection.cpp
    engines/zvision/file/lzss_read_stream.cpp
    engines/zvision/file/search_manager.cpp
    engines/zvision/file/search_manager.h
    engines/zvision/graphics/cursors/cursor.cpp
    engines/zvision/graphics/cursors/cursor.h
    engines/zvision/graphics/cursors/cursor_manager.cpp
    engines/zvision/graphics/cursors/cursor_manager.h
    engines/zvision/graphics/effects/fog.cpp
    engines/zvision/graphics/effects/fog.h
    engines/zvision/graphics/effects/light.cpp
    engines/zvision/graphics/effects/light.h
    engines/zvision/graphics/effects/wave.cpp
    engines/zvision/graphics/effects/wave.h
    engines/zvision/graphics/render_manager.cpp
    engines/zvision/graphics/render_manager.h
    engines/zvision/graphics/render_table.cpp
    engines/zvision/module.mk
    engines/zvision/scripting/actions.cpp
    engines/zvision/scripting/actions.h
    engines/zvision/scripting/control.cpp
    engines/zvision/scripting/control.h
    engines/zvision/scripting/controls/fist_control.cpp
    engines/zvision/scripting/controls/fist_control.h
    engines/zvision/scripting/controls/hotmov_control.cpp
    engines/zvision/scripting/controls/hotmov_control.h
    engines/zvision/scripting/controls/input_control.cpp
    engines/zvision/scripting/controls/input_control.h
    engines/zvision/scripting/controls/lever_control.cpp
    engines/zvision/scripting/controls/lever_control.h
    engines/zvision/scripting/controls/paint_control.cpp
    engines/zvision/scripting/controls/paint_control.h
    engines/zvision/scripting/controls/safe_control.cpp
    engines/zvision/scripting/controls/safe_control.h
    engines/zvision/scripting/controls/save_control.cpp
    engines/zvision/scripting/controls/titler_control.cpp
    engines/zvision/scripting/controls/titler_control.h
    engines/zvision/scripting/scr_file_handling.cpp
    engines/zvision/scripting/script_manager.cpp
    engines/zvision/scripting/script_manager.h
    engines/zvision/sound/zork_raw.cpp
    engines/zvision/sound/zork_raw.h
    engines/zvision/text/string_manager.cpp
    engines/zvision/text/string_manager.h
    engines/zvision/text/text.cpp
    engines/zvision/text/text.h
    engines/zvision/video/rlf_decoder.cpp
    engines/zvision/video/rlf_decoder.h
    engines/zvision/video/video.cpp
    engines/zvision/video/zork_avi_decoder.cpp
    engines/zvision/video/zork_avi_decoder.h
    engines/zvision/zvision.cpp
    engines/zvision/zvision.h
    graphics/fonts/ttf.cpp
    gui/Tooltip.cpp
    gui/Tooltip.h
    gui/about.cpp
    gui/credits.h
    gui/debugger.cpp
    gui/debugger.h
    gui/dialog.cpp
    gui/launcher.cpp
    gui/options.cpp
    gui/saveload-dialog.cpp
    gui/themes/translations.dat
    icons/scummvm.info
    icons/scummvm_drawer.info
    image/codecs/cinepak.cpp
    image/codecs/cinepak.h
    image/codecs/codec.cpp
    image/codecs/codec.h
    image/codecs/qtrle.cpp
    image/codecs/qtrle.h
    image/codecs/rpza.cpp
    image/codecs/rpza.h
    po/POTFILES
    po/be_BY.po
    po/ca_ES.po
    po/cs_CZ.po
    po/da_DA.po
    po/de_DE.po
    po/es_ES.po
    po/eu.po
    po/fi_FI.po
    po/fr_FR.po
    po/gl_ES.po
    po/hu_HU.po
    po/it_IT.po
    po/nb_NO.po
    po/nl_NL.po
    po/nn_NO.po
    po/pl_PL.po
    po/pt_BR.po
    po/ru_RU.po
    po/scummvm.pot
    po/se_SE.po
    po/uk_UA.po
    ports.mk
    test/audio/timestamp.h
    test/common/endian.h
    test/common/memoryreadstream.h
    test/common/memoryreadstreamendian.h
    test/cxxtest/cxxtestgen.py
    video/avi_decoder.cpp
    video/avi_decoder.h
    video/module.mk
    video/qt_decoder.cpp
    video/qt_decoder.h
    video/theora_decoder.cpp
    video/theora_decoder.h
    video/video_decoder.cpp
    video/video_decoder.h





Commit: 76ba9185dd6e26451e3cd8e0dacce8a539156b1c
    https://github.com/scummvm/scummvm/commit/76ba9185dd6e26451e3cd8e0dacce8a539156b1c
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-10-18T12:36:56-04:00

Commit Message:
XEEN: Change sprite drawing to use the same algorithm as original

Changed paths:
    engines/xeen/sprites.cpp
    engines/xeen/sprites.h



diff --git a/engines/xeen/sprites.cpp b/engines/xeen/sprites.cpp
index b596432..8ae7e41 100644
--- a/engines/xeen/sprites.cpp
+++ b/engines/xeen/sprites.cpp
@@ -117,6 +117,17 @@ void SpriteResource::clear() {
  */
 void SpriteResource::drawOffset(XSurface &dest, uint16 offset, const Common::Point &pt, 
 		const Common::Rect &bounds, int flags, int scale) {
+	static const uint SCALE_TABLE[] = { 
+		0xFFFF, 0xFFEF, 0xEFEF, 0xEFEE, 0xEEEE, 0xEEAE, 0xAEAE, 0xAEAA,
+		0xAAAA, 0xAA8A, 0x8A8A, 0x8A88, 0x8888, 0x8880, 0x8080, 0x8000
+	};
+	static const int PATTERN_STEPS[] = { 0, 1, 1, 1, 2, 2, 3, 3, 0, -1, -1, -1, -2, -2, -3, -3 };
+
+	uint16 scaleMask = SCALE_TABLE[scale];
+	uint16 scaleMaskX = scaleMask, scaleMaskY = scaleMask;
+	bool flipped = (flags & SPRFLAG_HORIZ_FLIPPED) != 0;
+	int xInc = flipped ? -1 : 1;
+
 	// Get cell header
 	Common::MemoryReadStream f(_data, _filesize);
 	f.seek(offset);
@@ -125,62 +136,65 @@ void SpriteResource::drawOffset(XSurface &dest, uint16 offset, const Common::Poi
 	int yOffset = f.readUint16LE();
 	int height = f.readUint16LE();
 
-	// TODO: I don't currently know the algorithm the original used for scaling.
-	// This is a best fit estimate that every increment of the scale field
-	// reduces the size of a sprite by approximately 6.6%
-	int newScale = MAX(100.0 - 6.6 * scale, 0.0);
-	if (newScale == 0)
-		return;
-	setupScaling(newScale, xOffset + width, yOffset + height);
-
-	Common::Point destPos = pt;
-	destPos.x += (xOffset + width - _scaledWidth) / 2;
-
-	bool flipped = (flags & SPRFLAG_HORIZ_FLIPPED) != 0;
-	int xInc = flipped ? -1 : 1;
-
+	// Figure out drawing x, y
+	Common::Point destPos;
+	destPos.x = pt.x + getScaledVal(xOffset, scaleMaskX);
+	destPos.x += (width - getScaledVal(width, scaleMaskX)) / 2;
+	
+	destPos.y = pt.y + getScaledVal(yOffset, scaleMaskY);
+	
+	// If the flags allow the dest surface to be resized, ensure dest surface is big enough
 	if (flags & SPRFLAG_RESIZE) {
 		if (dest.w < (xOffset + width) || dest.h < (yOffset + height))
 			dest.create(xOffset + width, yOffset + height);
 	}
-	// The pattern steps used in the pattern command
-	const int patternSteps[] = { 0, 1, 1, 1, 2, 2, 3, 3, 0, -1, -1, -1, -2, -2, -3, -3 };
+	
+	uint16 scaleMaskXCopy = scaleMaskX;
+	Common::Rect drawBounds;
+	drawBounds.left = SCREEN_WIDTH;
+	drawBounds.top = SCREEN_HEIGHT;
+	drawBounds.right = drawBounds.bottom = 0;
 
 	// Main loop
-	int opr1, opr2;
-	int32 pos;
-	int yIndex = yOffset;
-	int yPos = destPos.y + getScaledValue(yOffset);
-	for (int yCtr = 0, byteCount = 0; yCtr < height; ++yCtr, ++yIndex, byteCount = 0) {
+	for (int yCtr = height; yCtr > 0; --yCtr) {
 		// The number of bytes in this scan line
 		int lineLength = f.readByte();
 
 		if (lineLength == 0) {
 			// Skip the specified number of scan lines
 			int numLines = f.readByte();
-			for (int idx = 0; idx < numLines; ++idx, ++yIndex, ++yCtr) {
-				if (_lineDist[yIndex])
-					++yPos;
-			}
-		} else if (destPos.y < bounds.top || yPos >= bounds.bottom 
-				|| !_lineDist[yIndex]) {
+			destPos.y += getScaledVal(numLines, scaleMaskY);
+			yCtr -= numLines;
+			continue;
+		}
+
+		// Roll the scale mask 
+		uint bit = (scaleMaskY >> 15) & 1;
+		scaleMaskY = ((scaleMaskY & 0x7fff) << 1) + bit;
+		
+		if (!bit) {
+			// Not a line to be drawn due to scaling down
+			f.skip(lineLength);
+		} else if (destPos.y < bounds.top || destPos.y >= bounds.bottom) {
 			// Skip over the bytes of the line
 			f.skip(lineLength);
+			destPos.y++;
 		} else {
-			const byte *lineStartP = (const byte *)dest.getBasePtr(bounds.left, yPos);
-			const byte *lineEndP = (const byte *)dest.getBasePtr(bounds.right, yPos);
-
-			// Skip the transparent pixels at the beginning of the scan line
-			int xPos = f.readByte() + xOffset; ++byteCount;
-			int xAmt = getScaledValue(flipped ? xOffset + width - xPos : xPos);
-			int xIndex = 0;
-
-			byte *destP = (byte *)dest.getBasePtr(destPos.x + xAmt, yPos);
-			++yPos;
-
-			while (byteCount < lineLength) {
-				// The next byte is an opcode that determines what 
-				// operators are to follow and how to interpret them.
+			scaleMaskX = scaleMaskXCopy;
+			int xOffset = f.readByte();
+			
+			// Initialize the array to hold the temporary data for the line. We do this to make it simpler
+			// to handle both deciding which pixels to draw in a scaled image, as well as when images
+			// have been horizontally flipped
+			int tempLine[SCREEN_WIDTH];
+			Common::fill(&tempLine[0], &tempLine[SCREEN_WIDTH], -1);
+			int *lineP = flipped ? &tempLine[width - 1 - xOffset] : &tempLine[xOffset];
+
+			// Build up the line
+			int byteCount, opr1, opr2;
+			int32 pos;
+			for (byteCount = 1; byteCount < lineLength; ) {
+				// The next byte is an opcode that determines what operators are to follow and how to interpret them.
 				int opcode = f.readByte(); ++byteCount;
 
 				// Decode the opcode
@@ -190,26 +204,18 @@ void SpriteResource::drawOffset(XSurface &dest, uint16 offset, const Common::Poi
 				switch (cmd) {
 				case 0:   // The following len + 1 bytes are stored as indexes into the color table.
 				case 1:   // The following len + 33 bytes are stored as indexes into the color table.
-					for (int i = 0; i < opcode + 1; ++i, ++xPos) {
+					for (int i = 0; i < opcode + 1; ++i, ++byteCount) {
 						byte b = f.readByte();
-						++byteCount;
-
-						if (_lineDist[xIndex++]) {
-							if (destP >= lineStartP && destP < lineEndP)
-								*destP = b;
-							destP += xInc;
-						}
+						*lineP = b;
+						lineP += xInc;
 					}
 					break;
 
 				case 2:   // The following byte is an index into the color table, draw it len + 3 times.
 					opr1 = f.readByte(); ++byteCount;
-					for (int i = 0; i < len + 3; ++i, ++xPos) {
-						if (_lineDist[xIndex++]) {
-							if (destP >= lineStartP && destP < lineEndP)
-								*destP = opr1;
-							destP += xInc;
-						}
+					for (int i = 0; i < len + 3; ++i) {
+						*lineP = opr1;
+						lineP += xInc;
 					}
 					break;
 
@@ -218,13 +224,9 @@ void SpriteResource::drawOffset(XSurface &dest, uint16 offset, const Common::Poi
 					pos = f.pos();
 					f.seek(-opr1, SEEK_CUR);
 
-					for (int i = 0; i < len + 4; ++i, ++xPos) {
-						byte b = f.readByte();
-						if (_lineDist[xIndex++]) {
-							if (destP >= lineStartP && destP < lineEndP)
-								*destP = b;
-							destP += xInc;
-						}
+					for (int i = 0; i < len + 4; ++i) {
+						*lineP = f.readByte();
+						lineP += xInc;
 					}
 
 					f.seek(pos, SEEK_SET);
@@ -233,31 +235,16 @@ void SpriteResource::drawOffset(XSurface &dest, uint16 offset, const Common::Poi
 				case 4:   // The following two bytes are indexes into the color table, draw the pair len + 2 times.
 					opr1 = f.readByte(); ++byteCount;
 					opr2 = f.readByte(); ++byteCount;
-					for (int i = 0; i < len + 2; ++i, xPos += 2) {
-						if (destP < lineStartP || destP >= (lineEndP - 1)) {
-							if (_lineDist[xIndex++])
-								destP += xInc;
-							if (_lineDist[xIndex++])
-								destP += xInc;
-						} else {
-							if (_lineDist[xIndex++]) {
-								*destP = opr1;
-								destP += xInc;
-							}
-							if (_lineDist[xIndex++]) {
-								*destP = opr2;
-								destP += xInc;
-							}
-						}
+					for (int i = 0; i < len + 2; ++i) {
+						*lineP = opr1;
+						lineP += xInc;
+						*lineP = opr2;
+						lineP += xInc;
 					}
 					break;
 
-				case 5:   // Skip len + 1 pixels filling them with the transparent color.
-					for (int idx = 0; idx < (len + 1); ++idx) {
-						if (_lineDist[xIndex++])
-							destP += xInc;
-						++xPos;
-					}
+				case 5:   // Skip len + 1 pixels
+					lineP += len + 1;
 					break;
 
 				case 6:   // Pattern command.
@@ -267,30 +254,54 @@ void SpriteResource::drawOffset(XSurface &dest, uint16 offset, const Common::Poi
 					cmd = (opcode >> 2) & 0x0E;
 
 					opr1 = f.readByte(); ++byteCount;
-					for (int i = 0; i < len + 3; ++i, ++xPos) {
-						if (_lineDist[xIndex++]) {
-							if (destP >= lineStartP && destP < lineEndP)
-								*destP = opr1;
-							destP += xInc;
-						}
-						opr1 += patternSteps[cmd + (i % 2)];
+					for (int i = 0; i < len + 3; ++i) {
+						*lineP = opr1;
+						lineP += xInc;
+						opr1 += PATTERN_STEPS[cmd + (i % 2)];
 					}
 					break;
+
 				default:
 					break;
 				}
 			}
-
 			assert(byteCount == lineLength);
+
+			drawBounds.top = MIN(drawBounds.top, destPos.y);
+			drawBounds.bottom = MAX(drawBounds.bottom, destPos.y);
+
+			// Handle drawing out the line
+			byte *destP = (byte *)dest.getBasePtr(destPos.x, destPos.y);
+			int16 xp = destPos.x;
+			lineP = &tempLine[0];
+
+			for (int xCtr = 0; xCtr < width; ++xCtr, ++lineP) {
+				bit = (scaleMaskX >> 15) & 1;
+				scaleMaskX = ((scaleMaskX & 0x7fff) << 1) + bit;
+
+				if (bit) {
+					if (*lineP != -1 && xp >= bounds.left && xp < bounds.right) {
+						*destP = (byte)*lineP;
+						drawBounds.left = MIN(drawBounds.left, xp);
+						drawBounds.right = MAX(drawBounds.right, xp);
+					}
+
+					++destP;
+					++xp;
+				}
+			}
+
+			++destPos.y;
 		}
 	}
-	
-	Common::Rect r(Common::Rect(
-		destPos.x + getScaledValue(xOffset), destPos.y + getScaledValue(yOffset),
-		destPos.x + getScaledValue(xOffset + width), destPos.y + getScaledValue(yOffset + height)));
-	r.clip(Common::Rect(0, 0, dest.w, dest.h));
-	if (!r.isEmpty())
-		dest.addDirtyRect(r);
+	dest.addDirtyRect(Common::Rect(0, 0, dest.w, dest.h));
+	/*
+	if (drawBounds.isValidRect()) {
+		drawBounds.clip(Common::Rect(0, 0, dest.w, dest.h));
+		if (!drawBounds.isEmpty())
+			dest.addDirtyRect(drawBounds);
+	}
+	*/
 }
 
 void SpriteResource::draw(XSurface &dest, int frame, const Common::Point &destPos,
@@ -303,9 +314,6 @@ void SpriteResource::draw(Window &dest, int frame, const Common::Point &destPos,
 	draw(dest, frame, destPos, dest.getBounds(), flags, scale);
 }
 
-/**
- * Draw the sprite onto the given surface
- */
 void SpriteResource::draw(XSurface &dest, int frame, const Common::Point &destPos, 
 		const Common::Rect &bounds, int flags, int scale) {
 	// TODO: TO test when I find sprites using scale values and flags
@@ -318,47 +326,22 @@ void SpriteResource::draw(XSurface &dest, int frame, const Common::Point &destPo
 		drawOffset(dest, _index[frame]._offset2, destPos, bounds, flags, scale);
 }
 
-/**
- * Draw the sprite onto the given surface
- */
 void SpriteResource::draw(XSurface &dest, int frame) {
 	draw(dest, frame, Common::Point());
 }
 
-void SpriteResource::setupScaling(int scale, int frameWidth, int frameHeight) {
-	int highestDim = MAX(frameWidth, frameHeight);
-	int distCtr = 0;
-	int distIndex = 0;
-	_scaledWidth = _scaledHeight = 0;
-
-	do {
-		distCtr += scale;
-		if (distCtr < 100) {
-			_lineDist[distIndex] = false;
-		} else {
-			_lineDist[distIndex] = true;
-			distCtr -= 100;
-
-			if (distIndex < frameWidth)
-				++_scaledWidth;
-
-			if (distIndex < frameHeight)
-				++_scaledHeight;
-		}
-	} while (++distIndex < highestDim);
-}
+uint SpriteResource::getScaledVal(int xy, uint16 &scaleMask) {
+	if (!xy)
+		return 0;
 
-/**
- * Returns a scaled value based on a passed in x or y distance
- */
-int SpriteResource::getScaledValue(int xy) {
-	int newVal = 0;
+	uint result = 0;
 	for (int idx = 0; idx < xy; ++idx) {
-		if (_lineDist[idx])
-			++newVal;
+		uint bit = (scaleMask >> 15) & 1;
+		scaleMask = ((scaleMask & 0x7fff) << 1) + bit;
+		result += bit;
 	}
-
-	return newVal;
+	
+	return result;
 }
 
 } // End of namespace Xeen
diff --git a/engines/xeen/sprites.h b/engines/xeen/sprites.h
index 0e3a3c3..ce7b786 100644
--- a/engines/xeen/sprites.h
+++ b/engines/xeen/sprites.h
@@ -50,15 +50,22 @@ private:
 
 	void load(Common::SeekableReadStream &f);
 
+	/**
+	 * Draw the sprite onto the given surface
+	 */
 	void draw(XSurface &dest, int frame, const Common::Point &destPos,
 		const Common::Rect &bounds, int flags = 0, int scale = 0);
 
+	/**
+	 * Draw a sprite frame based on a passed offset into the data stream
+	 */
 	void drawOffset(XSurface &dest, uint16 offset, const Common::Point &pt, 
 		const Common::Rect &bounds, int flags, int scale);
 
-	void setupScaling(int scale, int frameWidth, int frameHeight);
-
-	int getScaledValue(int xy);
+	/**
+	 * Scale a co-ordinate value based on the passed scaling mask
+	 */
+	static uint getScaledVal(int xy, uint16 &scaleMask);
 public:
 	SpriteResource();
 	SpriteResource(const Common::String &filename);
@@ -79,6 +86,9 @@ public:
 	void draw(Window &dest, int frame, const Common::Point &destPos,
 		int flags = 0, int scale = 0);
 
+	/**
+	 * Draw the sprite onto the given surface
+	 */
 	void draw(XSurface &dest, int frame);
 
 	int size() const { return _index.size(); }


Commit: 80fcbaf4410c6486986420ba4565c1c3361a1f74
    https://github.com/scummvm/scummvm/commit/80fcbaf4410c6486986420ba4565c1c3361a1f74
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-10-18T12:55:16-04:00

Commit Message:
XEEN: Restore dirty rect handling in sprite drawing

Changed paths:
    engines/xeen/sprites.cpp



diff --git a/engines/xeen/sprites.cpp b/engines/xeen/sprites.cpp
index 8ae7e41..218e712 100644
--- a/engines/xeen/sprites.cpp
+++ b/engines/xeen/sprites.cpp
@@ -294,14 +294,12 @@ void SpriteResource::drawOffset(XSurface &dest, uint16 offset, const Common::Poi
 			++destPos.y;
 		}
 	}
-	dest.addDirtyRect(Common::Rect(0, 0, dest.w, dest.h));
-	/*
+
 	if (drawBounds.isValidRect()) {
 		drawBounds.clip(Common::Rect(0, 0, dest.w, dest.h));
 		if (!drawBounds.isEmpty())
 			dest.addDirtyRect(drawBounds);
 	}
-	*/
 }
 
 void SpriteResource::draw(XSurface &dest, int frame, const Common::Point &destPos,


Commit: c2c00894f22ed8cf0b3d5fa469d8554ab0df96ef
    https://github.com/scummvm/scummvm/commit/c2c00894f22ed8cf0b3d5fa469d8554ab0df96ef
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-10-18T21:35:35-04:00

Commit Message:
XEEN: Implement SPRFLAG_SCENE_CLIPPED drawing flag

Changed paths:
    engines/xeen/interface_map.cpp
    engines/xeen/sprites.cpp
    engines/xeen/sprites.h



diff --git a/engines/xeen/interface_map.cpp b/engines/xeen/interface_map.cpp
index a9e71d4..a08ce80 100644
--- a/engines/xeen/interface_map.cpp
+++ b/engines/xeen/interface_map.cpp
@@ -60,11 +60,11 @@ OutdoorDrawList::OutdoorDrawList() : _sky1(_data[0]), _sky2(_data[1]),
 	_data[25] = DrawStruct(0, 8, 109);
 	_data[26] = DrawStruct(0, 201, 109);
 	_data[27] = DrawStruct(0, 8, 109);
-	_data[28] = DrawStruct(1, -64, 61, 14, SPRFLAG_2000);
+	_data[28] = DrawStruct(1, -64, 61, 14, SPRFLAG_SCENE_CLIPPED);
 	_data[29] = DrawStruct(1, -40, 61, 14, 0);
 	_data[30] = DrawStruct(1, -16, 61, 14, 0);
 	_data[31] = DrawStruct(1, 8, 61, 14, 0);
-	_data[32] = DrawStruct(1, 128, 61, 14, SPRFLAG_HORIZ_FLIPPED | SPRFLAG_2000);
+	_data[32] = DrawStruct(1, 128, 61, 14, SPRFLAG_HORIZ_FLIPPED | SPRFLAG_SCENE_CLIPPED);
 	_data[33] = DrawStruct(1, 104, 61, 14, SPRFLAG_HORIZ_FLIPPED);
 	_data[34] = DrawStruct(1, 80, 61, 14, SPRFLAG_HORIZ_FLIPPED);
 	_data[35] = DrawStruct(1, 56, 61, 14, SPRFLAG_HORIZ_FLIPPED);
@@ -120,10 +120,10 @@ OutdoorDrawList::OutdoorDrawList() : _sky1(_data[0]), _sky2(_data[1]),
 	_data[85] = DrawStruct(2, 146, 40, 0, SPRFLAG_HORIZ_FLIPPED);
 	_data[86] = DrawStruct(1, 32, 40, 6, 0);
 	_data[87] = DrawStruct(0, -7, 30, 7, 0);
-	_data[88] = DrawStruct(0, -112, 30, 7, SPRFLAG_2000);
-	_data[89] = DrawStruct(0, 98, 30, 7, SPRFLAG_2000);
-	_data[90] = DrawStruct(0, -112, 30, 8, SPRFLAG_2000);
-	_data[91] = DrawStruct(0, 98, 30, 8, SPRFLAG_2000);
+	_data[88] = DrawStruct(0, -112, 30, 7, SPRFLAG_SCENE_CLIPPED);
+	_data[89] = DrawStruct(0, 98, 30, 7, SPRFLAG_SCENE_CLIPPED);
+	_data[90] = DrawStruct(0, -112, 30, 8, SPRFLAG_SCENE_CLIPPED);
+	_data[91] = DrawStruct(0, 98, 30, 8, SPRFLAG_SCENE_CLIPPED);
 	_data[92] = DrawStruct(0, -38, 30, 8, 0);
 	_data[93] = DrawStruct(0, 25, 30, 8, 0);
 	_data[94] = DrawStruct(0, -7, 30, 8, 0);
@@ -138,22 +138,22 @@ OutdoorDrawList::OutdoorDrawList() : _sky1(_data[0]), _sky2(_data[1]),
 	_data[103] = DrawStruct(0, 8, 24);
 	_data[104] = DrawStruct(0, 169, 24, 0, SPRFLAG_HORIZ_FLIPPED);
 	_data[105] = DrawStruct(1, 32, 24);
-	_data[106] = DrawStruct(0, -23, 40, 0, SPRFLAG_2000);
-	_data[107] = DrawStruct(0, 200, 40, 0, SPRFLAG_HORIZ_FLIPPED | SPRFLAG_2000);
+	_data[106] = DrawStruct(0, -23, 40, 0, SPRFLAG_SCENE_CLIPPED);
+	_data[107] = DrawStruct(0, 200, 40, 0, SPRFLAG_HORIZ_FLIPPED | SPRFLAG_SCENE_CLIPPED);
 	_data[108] = DrawStruct(0, 8, 47);
 	_data[109] = DrawStruct(0, 169, 47, 0, SPRFLAG_HORIZ_FLIPPED);
-	_data[110] = DrawStruct(1, -56, -4, 0x8000, SPRFLAG_4000 | SPRFLAG_2000);
-	_data[111] = DrawStruct(0, -5, 2, 0, SPRFLAG_4000 | SPRFLAG_2000);
-	_data[112] = DrawStruct(0, -67, 2, 0, SPRFLAG_4000 | SPRFLAG_2000);
+	_data[110] = DrawStruct(1, -56, -4, 0x8000, SPRFLAG_4000 | SPRFLAG_SCENE_CLIPPED);
+	_data[111] = DrawStruct(0, -5, 2, 0, SPRFLAG_4000 | SPRFLAG_SCENE_CLIPPED);
+	_data[112] = DrawStruct(0, -67, 2, 0, SPRFLAG_4000 | SPRFLAG_SCENE_CLIPPED);
 	_data[113] = DrawStruct(0, 44, 73);
 	_data[114] = DrawStruct(0, 44, 73);
-	_data[115] = DrawStruct(0, 58, 14, 0, SPRFLAG_4000 | SPRFLAG_2000);
+	_data[115] = DrawStruct(0, 58, 14, 0, SPRFLAG_4000 | SPRFLAG_SCENE_CLIPPED);
 	_data[116] = DrawStruct(0, 169, 73);
 	_data[117] = DrawStruct(0, 169, 73);
-	_data[118] = DrawStruct(0, -5, 14, 0, SPRFLAG_4000 | SPRFLAG_2000);
+	_data[118] = DrawStruct(0, -5, 14, 0, SPRFLAG_4000 | SPRFLAG_SCENE_CLIPPED);
 	_data[119] = DrawStruct(0, 110, 73);
 	_data[120] = DrawStruct(0, 110, 73);
-	_data[121] = DrawStruct(0, -5, 14, 0, SPRFLAG_4000 | SPRFLAG_2000);
+	_data[121] = DrawStruct(0, -5, 14, 0, SPRFLAG_4000 | SPRFLAG_SCENE_CLIPPED);
 	_data[122] = DrawStruct(0, 110, 73);
 	_data[123] = DrawStruct(0, 110, 73);
 	_data[124] = DrawStruct(0, 72, 43);
@@ -280,16 +280,16 @@ IndoorDrawList::IndoorDrawList() :
 	_data[84] = DrawStruct(0, 71, 53, 12, SPRFLAG_HORIZ_FLIPPED);
 	_data[85] = DrawStruct(0, 80, 57, 12, 0);
 	_data[86] = DrawStruct(0, 64, 57, 12, SPRFLAG_HORIZ_FLIPPED);
-	_data[87] = DrawStruct(7, -24, 52, 0, SPRFLAG_2000);
+	_data[87] = DrawStruct(7, -24, 52, 0, SPRFLAG_SCENE_CLIPPED);
 	_data[88] = DrawStruct(7, 32, 52);
 	_data[89] = DrawStruct(7, 88, 52);
 	_data[90] = DrawStruct(0, 144, 52);
-	_data[91] = DrawStruct(0, 200, 52, 0, SPRFLAG_2000);
-	_data[92] = DrawStruct(0, -79, 52, 11, SPRFLAG_2000);
+	_data[91] = DrawStruct(0, 200, 52, 0, SPRFLAG_SCENE_CLIPPED);
+	_data[92] = DrawStruct(0, -79, 52, 11, SPRFLAG_SCENE_CLIPPED);
 	_data[93] = DrawStruct(0, -27, 52, 11, 0);
 	_data[94] = DrawStruct(0, 32, 52, 11, 0);
 	_data[95] = DrawStruct(0, 89, 52, 11, 0);
-	_data[96] = DrawStruct(0, 145, 52, 11, SPRFLAG_2000);
+	_data[96] = DrawStruct(0, 145, 52, 11, SPRFLAG_SCENE_CLIPPED);
 	_data[97] = DrawStruct(0, -8, 50, 12, 0);
 	_data[98] = DrawStruct(0, -65, 50, 12, 0);
 	_data[99] = DrawStruct(0, 49, 50, 12, 0);
@@ -312,17 +312,17 @@ IndoorDrawList::IndoorDrawList() :
 	_data[116] = DrawStruct(0, 63, 47, 8, SPRFLAG_HORIZ_FLIPPED);
 	_data[117] = DrawStruct(0, 94, 52, 8, 0);
 	_data[118] = DrawStruct(0, 50, 52, 8, SPRFLAG_HORIZ_FLIPPED);
-	_data[119] = DrawStruct(6, -40, 40, 0, SPRFLAG_2000);
+	_data[119] = DrawStruct(6, -40, 40, 0, SPRFLAG_SCENE_CLIPPED);
 	_data[120] = DrawStruct(6, 64, 40);
-	_data[121] = DrawStruct(0, 168, 40, 0, SPRFLAG_2000);
-	_data[122] = DrawStruct(0, -72, 40, 6, SPRFLAG_2000);
+	_data[121] = DrawStruct(0, 168, 40, 0, SPRFLAG_SCENE_CLIPPED);
+	_data[122] = DrawStruct(0, -72, 40, 6, SPRFLAG_SCENE_CLIPPED);
 	_data[123] = DrawStruct(0, 32, 40, 6, 0);
-	_data[124] = DrawStruct(0, 137, 40, 6, SPRFLAG_2000);
+	_data[124] = DrawStruct(0, 137, 40, 6, SPRFLAG_SCENE_CLIPPED);
 	_data[125] = DrawStruct(0, -7, 25, 7, 0);
-	_data[126] = DrawStruct(0, -112, 25, 7, SPRFLAG_2000);
-	_data[127] = DrawStruct(0, 98, 25, 7, SPRFLAG_2000);
-	_data[128] = DrawStruct(0, -112, 29, 8, SPRFLAG_2000);
-	_data[129] = DrawStruct(0, 98, 29, 8, SPRFLAG_2000);
+	_data[126] = DrawStruct(0, -112, 25, 7, SPRFLAG_SCENE_CLIPPED);
+	_data[127] = DrawStruct(0, 98, 25, 7, SPRFLAG_SCENE_CLIPPED);
+	_data[128] = DrawStruct(0, -112, 29, 8, SPRFLAG_SCENE_CLIPPED);
+	_data[129] = DrawStruct(0, 98, 29, 8, SPRFLAG_SCENE_CLIPPED);
 	_data[130] = DrawStruct(0, -38, 29, 8, 0);
 	_data[131] = DrawStruct(0, 25, 29, 8, 0);
 	_data[132] = DrawStruct(0, -7, 29, 8, 0);
@@ -336,23 +336,23 @@ IndoorDrawList::IndoorDrawList() :
 	_data[140] = DrawStruct(0, 55, 41, 4, SPRFLAG_HORIZ_FLIPPED);
 	_data[141] = DrawStruct(0, 106, 47, 4, 0);
 	_data[142] = DrawStruct(0, 38, 47, 4, SPRFLAG_HORIZ_FLIPPED);
-	_data[143] = DrawStruct(0, -136, 24, 0, SPRFLAG_2000);
+	_data[143] = DrawStruct(0, -136, 24, 0, SPRFLAG_SCENE_CLIPPED);
 	_data[144] = DrawStruct(0, 8, 12);
 	_data[145] = DrawStruct(0, 32, 24);
 	_data[146] = DrawStruct(0, 200, 12, 0, SPRFLAG_HORIZ_FLIPPED);
-	_data[147] = DrawStruct(0, 200, 24, 0, SPRFLAG_2000);
+	_data[147] = DrawStruct(0, 200, 24, 0, SPRFLAG_SCENE_CLIPPED);
 	_data[148] = DrawStruct(0, 32, 24);
-	_data[149] = DrawStruct(0, -5, 2, 0, SPRFLAG_4000 | SPRFLAG_2000);
-	_data[150] = DrawStruct(0, -67, 10, 0, SPRFLAG_4000 | SPRFLAG_2000);
+	_data[149] = DrawStruct(0, -5, 2, 0, SPRFLAG_4000 | SPRFLAG_SCENE_CLIPPED);
+	_data[150] = DrawStruct(0, -67, 10, 0, SPRFLAG_4000 | SPRFLAG_SCENE_CLIPPED);
 	_data[151] = DrawStruct(0, 44, 73);
 	_data[152] = DrawStruct(0, 44, 73);
-	_data[153] = DrawStruct(0, 58, 14, 0, SPRFLAG_4000 | SPRFLAG_2000);
+	_data[153] = DrawStruct(0, 58, 14, 0, SPRFLAG_4000 | SPRFLAG_SCENE_CLIPPED);
 	_data[154] = DrawStruct(0, 169, 73);
 	_data[155] = DrawStruct(0, 169, 73);
-	_data[156] = DrawStruct(0, -5, 14, 0, SPRFLAG_4000 | SPRFLAG_2000);
+	_data[156] = DrawStruct(0, -5, 14, 0, SPRFLAG_4000 | SPRFLAG_SCENE_CLIPPED);
 	_data[157] = DrawStruct(0, 110, 73);
 	_data[158] = DrawStruct(0, 110, 73);
-	_data[159] = DrawStruct(0, -5, 14, 0, SPRFLAG_4000 | SPRFLAG_2000);
+	_data[159] = DrawStruct(0, -5, 14, 0, SPRFLAG_4000 | SPRFLAG_SCENE_CLIPPED);
 	_data[160] = DrawStruct(0, 110, 73);
 	_data[161] = DrawStruct(0, 110, 73);
 	_data[162] = DrawStruct(0, 72, 43);
@@ -478,7 +478,7 @@ void InterfaceMap::drawMap() {
 						ds2._y = 73;
 					}
 
-					ds2._flags = SPRFLAG_4000 | SPRFLAG_2000;
+					ds2._flags = SPRFLAG_4000 | SPRFLAG_SCENE_CLIPPED;
 					ds2._sprites = &_charPowSprites;
 				}
 
@@ -489,7 +489,7 @@ void InterfaceMap::drawMap() {
 
 					if (ds1._scale == 0x8000)
 						ds1._x /= 3;
-					ds1._flags = SPRFLAG_4000 | SPRFLAG_2000;
+					ds1._flags = SPRFLAG_4000 | SPRFLAG_SCENE_CLIPPED;
 					ds1._sprites = &_charPowSprites;
 				}
 			}
@@ -612,7 +612,7 @@ void InterfaceMap::drawMap() {
 						ds1._y = 73;
 					}
 
-					ds1._flags = SPRFLAG_4000 | SPRFLAG_2000;
+					ds1._flags = SPRFLAG_4000 | SPRFLAG_SCENE_CLIPPED;
 					ds1._sprites = &_charPowSprites;
 				}
 
@@ -622,7 +622,7 @@ void InterfaceMap::drawMap() {
 					ds2._scale = combat._elemScale[idx];
 					if (ds2._scale == 0x8000)
 						ds2._x /= 3;
-					ds2._flags = SPRFLAG_4000 | SPRFLAG_2000;
+					ds2._flags = SPRFLAG_4000 | SPRFLAG_SCENE_CLIPPED;
 					ds2._sprites = &_charPowSprites;
 				}
 			}
diff --git a/engines/xeen/sprites.cpp b/engines/xeen/sprites.cpp
index 218e712..288d304 100644
--- a/engines/xeen/sprites.cpp
+++ b/engines/xeen/sprites.cpp
@@ -30,6 +30,9 @@
 
 namespace Xeen {
 
+#define SCENE_CLIP_LEFT 8
+#define SCENE_CLIP_RIGHT 223
+
 SpriteResource::SpriteResource() {
 	_filesize = 0;
 	_data = nullptr;
@@ -280,7 +283,8 @@ void SpriteResource::drawOffset(XSurface &dest, uint16 offset, const Common::Poi
 				scaleMaskX = ((scaleMaskX & 0x7fff) << 1) + bit;
 
 				if (bit) {
-					if (*lineP != -1 && xp >= bounds.left && xp < bounds.right) {
+					if (*lineP != -1 && xp >= bounds.left && xp < bounds.right &&
+							(!(flags & SPRFLAG_SCENE_CLIPPED) || (xp >= SCENE_CLIP_LEFT && xp < SCENE_CLIP_RIGHT))) {
 						*destP = (byte)*lineP;
 						drawBounds.left = MIN(drawBounds.left, xp);
 						drawBounds.right = MAX(drawBounds.right, xp);
@@ -317,7 +321,6 @@ void SpriteResource::draw(XSurface &dest, int frame, const Common::Point &destPo
 	// TODO: TO test when I find sprites using scale values and flags
 	assert(scale != 0x8000); 
 	assert(scale >= 0);
-//	assert((flags & SPRFLAG_2000) == 0);
 
 	drawOffset(dest, _index[frame]._offset1, destPos, bounds, flags, scale);
 	if (_index[frame]._offset2)
diff --git a/engines/xeen/sprites.h b/engines/xeen/sprites.h
index ce7b786..2a00eca 100644
--- a/engines/xeen/sprites.h
+++ b/engines/xeen/sprites.h
@@ -34,7 +34,7 @@ namespace Xeen {
 class XeenEngine;
 class Window;
 
-enum SpriteFlags { SPRFLAG_2000 = 0x2000, SPRFLAG_4000 = 0x4000, 
+enum SpriteFlags { SPRFLAG_SCENE_CLIPPED = 0x2000, SPRFLAG_4000 = 0x4000, 
 	SPRFLAG_HORIZ_FLIPPED = 0x8000, SPRFLAG_RESIZE = 0x10000 };
 
 class SpriteResource {


Commit: 0bb223cd3a4840f3da7c3faac701e7814e1ebf82
    https://github.com/scummvm/scummvm/commit/0bb223cd3a4840f3da7c3faac701e7814e1ebf82
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-10-19T08:55:13-04:00

Commit Message:
XEEN: Fix graphic corruption on images with skipped pixels

Changed paths:
    engines/xeen/sprites.cpp



diff --git a/engines/xeen/sprites.cpp b/engines/xeen/sprites.cpp
index 288d304..1e7a48e 100644
--- a/engines/xeen/sprites.cpp
+++ b/engines/xeen/sprites.cpp
@@ -247,7 +247,7 @@ void SpriteResource::drawOffset(XSurface &dest, uint16 offset, const Common::Poi
 					break;
 
 				case 5:   // Skip len + 1 pixels
-					lineP += len + 1;
+					lineP += (len + 1) * xInc;
 					break;
 
 				case 6:   // Pattern command.


Commit: 43e16714df3688113d8d12533dc780a1d6f872d9
    https://github.com/scummvm/scummvm/commit/43e16714df3688113d8d12533dc780a1d6f872d9
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-10-20T07:33:30-04:00

Commit Message:
XEEN: Implement sprite enlargement drawing

Changed paths:
    engines/xeen/sprites.cpp



diff --git a/engines/xeen/sprites.cpp b/engines/xeen/sprites.cpp
index 1e7a48e..3491f6f 100644
--- a/engines/xeen/sprites.cpp
+++ b/engines/xeen/sprites.cpp
@@ -126,10 +126,11 @@ void SpriteResource::drawOffset(XSurface &dest, uint16 offset, const Common::Poi
 	};
 	static const int PATTERN_STEPS[] = { 0, 1, 1, 1, 2, 2, 3, 3, 0, -1, -1, -1, -2, -2, -3, -3 };
 
-	uint16 scaleMask = SCALE_TABLE[scale];
+	uint16 scaleMask = SCALE_TABLE[scale & 0x7fff];
 	uint16 scaleMaskX = scaleMask, scaleMaskY = scaleMask;
 	bool flipped = (flags & SPRFLAG_HORIZ_FLIPPED) != 0;
 	int xInc = flipped ? -1 : 1;
+	bool enlarge = (scale & 0x8000) != 0;
 
 	// Get cell header
 	Common::MemoryReadStream f(_data, _filesize);
@@ -283,11 +284,15 @@ void SpriteResource::drawOffset(XSurface &dest, uint16 offset, const Common::Poi
 				scaleMaskX = ((scaleMaskX & 0x7fff) << 1) + bit;
 
 				if (bit) {
+					// Check whether there's a pixel to write, and we're within the allowable bounds. Note that for
+					// the SPRFLAG_SCENE_CLIPPED or when scale == 0x8000, we also have an extra horizontal bounds check
 					if (*lineP != -1 && xp >= bounds.left && xp < bounds.right &&
-							(!(flags & SPRFLAG_SCENE_CLIPPED) || (xp >= SCENE_CLIP_LEFT && xp < SCENE_CLIP_RIGHT))) {
-						*destP = (byte)*lineP;
+							((!(flags & SPRFLAG_SCENE_CLIPPED) && !enlarge) || (xp >= SCENE_CLIP_LEFT && xp < SCENE_CLIP_RIGHT))) {
 						drawBounds.left = MIN(drawBounds.left, xp);
 						drawBounds.right = MAX(drawBounds.right, xp);
+						*destP = (byte)*lineP;
+						if (enlarge)
+							*(destP + SCREEN_WIDTH) = (byte)*lineP;
 					}
 
 					++destP;
@@ -296,6 +301,8 @@ void SpriteResource::drawOffset(XSurface &dest, uint16 offset, const Common::Poi
 			}
 
 			++destPos.y;
+			if (enlarge)
+				++destPos.y;
 		}
 	}
 
@@ -318,9 +325,6 @@ void SpriteResource::draw(Window &dest, int frame, const Common::Point &destPos,
 
 void SpriteResource::draw(XSurface &dest, int frame, const Common::Point &destPos, 
 		const Common::Rect &bounds, int flags, int scale) {
-	// TODO: TO test when I find sprites using scale values and flags
-	assert(scale != 0x8000); 
-	assert(scale >= 0);
 
 	drawOffset(dest, _index[frame]._offset1, destPos, bounds, flags, scale);
 	if (_index[frame]._offset2)


Commit: e06c879a477b4e187a31859e2519767f7e992bdb
    https://github.com/scummvm/scummvm/commit/e06c879a477b4e187a31859e2519767f7e992bdb
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-10-23T08:40:56-04:00

Commit Message:
XEEN: Fix displaying sky when outdoors

Changed paths:
    engines/xeen/map.cpp



diff --git a/engines/xeen/map.cpp b/engines/xeen/map.cpp
index 021c417..ff79387 100644
--- a/engines/xeen/map.cpp
+++ b/engines/xeen/map.cpp
@@ -1114,6 +1114,7 @@ void Map::load(int mapId) {
 
 		_groundSprites.load("water.out");
 		_tileSprites.load("outdoor.til");
+		outdoorList._sky1._sprites = &_skySprites[0];
 		outdoorList._sky2._sprites = &_skySprites[0];
 		outdoorList._groundSprite._sprites = &_groundSprites;
 		


Commit: 569f3c65b724a1c7be7a64bbfc61ec8aef060033
    https://github.com/scummvm/scummvm/commit/569f3c65b724a1c7be7a64bbfc61ec8aef060033
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-10-24T16:14:15-04:00

Commit Message:
XEEN: Beginnings of work on copy protection check method

Changed paths:
    engines/xeen/scripts.cpp



diff --git a/engines/xeen/scripts.cpp b/engines/xeen/scripts.cpp
index 790e3d7..175292f 100644
--- a/engines/xeen/scripts.cpp
+++ b/engines/xeen/scripts.cpp
@@ -20,6 +20,7 @@
  *
  */
 
+#include "common/config-manager.h"
 #include "xeen/scripts.h"
 #include "xeen/dialogs_input.h"
 #include "xeen/dialogs_whowill.h"
@@ -1792,7 +1793,11 @@ bool Scripts::ifProc(int action, uint32 mask, int mode, int charIndex) {
 }
 
 bool Scripts::copyProtectionCheck() {
-	// Currentl not implemented
+	// Only bother doing the protection check if it's been explicitly turned on
+	if (!ConfMan.getBool("copy_protection"))
+		return true;
+
+	// Currently not implemented
 	return true;
 }
 


Commit: 619a165f359251ed82dcd84d2c0ab221671af1d7
    https://github.com/scummvm/scummvm/commit/619a165f359251ed82dcd84d2c0ab221671af1d7
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-11-17T21:08:07-05:00

Commit Message:
XEEN: Merge Clouds and DarkSide engines into WorldOfXeenEngine

Changed paths:
  R engines/xeen/clouds/clouds_game.cpp
  R engines/xeen/clouds/clouds_game.h
  R engines/xeen/darkside/darkside_game.cpp
  R engines/xeen/darkside/darkside_game.h
    engines/xeen/detection.cpp
    engines/xeen/module.mk
    engines/xeen/worldofxeen/worldofxeen_game.cpp
    engines/xeen/worldofxeen/worldofxeen_game.h



diff --git a/engines/xeen/clouds/clouds_game.cpp b/engines/xeen/clouds/clouds_game.cpp
deleted file mode 100644
index 4987ce0..0000000
--- a/engines/xeen/clouds/clouds_game.cpp
+++ /dev/null
@@ -1,38 +0,0 @@
-/* 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 "xeen/clouds/clouds_game.h"
-
-namespace Xeen {
-
-CloudsEngine::CloudsEngine(OSystem *syst, const XeenGameDescription *gameDesc)
-		: XeenEngine(syst, gameDesc) {
-}
-
-void CloudsEngine::playGame() {
-	cloudsIntro();
-}
-
-void CloudsEngine::cloudsIntro() {
-}
-
-} // End of namespace Xeen
diff --git a/engines/xeen/clouds/clouds_game.h b/engines/xeen/clouds/clouds_game.h
deleted file mode 100644
index a8c4fbe..0000000
--- a/engines/xeen/clouds/clouds_game.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/* 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_CLOUDS_GAME_H
-#define XEEN_CLOUDS_GAME_H
-
-#include "xeen/xeen.h"
-
-namespace Xeen {
-
-class CloudsEngine : virtual public XeenEngine {
-protected:
-	void cloudsIntro();
-
-	virtual void playGame();
-public:
-	CloudsEngine(OSystem *syst, const XeenGameDescription *gameDesc);
-	virtual ~CloudsEngine() {}
-};
-
-} // End of namespace Xeen
-
-#endif /* XEEN_CLOUDS_GAME_H */
diff --git a/engines/xeen/darkside/darkside_game.cpp b/engines/xeen/darkside/darkside_game.cpp
deleted file mode 100644
index fe8c161..0000000
--- a/engines/xeen/darkside/darkside_game.cpp
+++ /dev/null
@@ -1,228 +0,0 @@
-/* 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 "xeen/darkside/darkside_game.h"
-#include "xeen/resources.h"
-#include "xeen/screen.h"
-
-namespace Xeen {
-
-DarkSideEngine::DarkSideEngine(OSystem *syst, const XeenGameDescription *gameDesc)
-		: XeenEngine(syst, gameDesc) {
-}
-
-void DarkSideEngine::playGame() {
-	// TODO
-}
-
-bool DarkSideEngine::pause(uint amount) {
-	while (!shouldQuit() && _events->timeElapsed() < amount) {
-		_events->pollEventsAndWait();
-		if (_events->isKeyMousePressed())
-			return true;
-	}
-
-	return shouldQuit();
-}
-
-void DarkSideEngine::darkSideIntro() {
-	/*
-	showTitle1();
-	if (shouldQuit())
-		return;
-
-	showTitle2();
-	if (shouldQuit())
-		return;
-		*/
-	// TODO: Only show startup if not seen before
-	showStartSequence();
-}
-
-void DarkSideEngine::showTitle1() {
-	// TODO: Starting method, and sound
-	//sub_28F40
-	_screen->loadPalette("dark.pal");
-	SpriteResource nwc[4] = {
-		SpriteResource("nwc1.int"), SpriteResource("nwc2.int"),
-		SpriteResource("nwc3.int"), SpriteResource("nwc4.int")
-	};
-	Common::File voc[3];
-	voc[0].open("dragon1.voc");
-	voc[1].open("dragon2.voc");
-	voc[2].open("dragon3.voc");
-
-	// Load backgrounds
-	_screen->loadBackground("nwc1.raw");
-	_screen->loadPage(0);
-	_screen->loadBackground("nwc2.raw");
-	_screen->loadPage(1);
-
-	// Draw the screen and fade it in
-	_screen->horizMerge(0);
-	_screen->draw();
-	_screen->fadeIn(4);
-
-	// Initial loop for dragon roaring
-	int nwcIndex = 0, nwcFrame = 0;
-	for (int idx = 0; idx < 55 && !shouldQuit(); ++idx) {
-		// Render the next frame
-		_events->updateGameCounter();
-		_screen->vertMerge(0);
-		nwc[nwcIndex].draw(*_screen, nwcFrame);
-		_screen->draw();
-
-		switch (idx) {
-		case 17:
-			_sound->proc2(voc[0]);
-			break;
-		case 34:
-		case 44:
-			++nwcIndex;
-			nwcFrame = 0;
-			break;
-		case 35:
-			_sound->proc2(voc[1]);
-			break;
-		default:
-			++nwcFrame;
-		}
-
-		if (pause(2))
-			return;
-	}
-
-	// Loop for dragon using flyspray
-	for (int idx = 0; idx < 42 && !shouldQuit(); ++idx) {
-		_events->updateGameCounter();
-		_screen->vertMerge(SCREEN_HEIGHT);
-		nwc[3].draw(*_screen, idx);
-		_screen->draw();
-
-		switch (idx) {
-		case 3:
-			_sound->startMusic(40);
-			break;
-		case 11:
-			_sound->startMusic(0);
-		case 27:
-		case 30:
-			_sound->startMusic(3);
-			break;
-		case 31:
-			_sound->proc2(voc[2]);
-			break;
-		case 33:
-			_sound->startMusic(2);
-			break;
-		default:
-			break;
-		}
-
-		if (pause(2))
-			return;
-	}
-
-	// Pause for a bit
-	pause(10);
-}
-
-void DarkSideEngine::showTitle2() {
-	_screen->fadeOut(8);
-	//TODO: Stuff
-
-	_screen->loadBackground("jvc.raw");
-	_screen->draw();
-	_screen->fadeIn(4);
-	
-	_events->updateGameCounter();
-	pause(60);
-}
-	
-void DarkSideEngine::showStartSequence() {
-	_screen->fadeOut(8);
-	_screen->loadBackground("pyramid2.raw");
-	_screen->loadPage(0);
-	_screen->loadPage(1);
-	_screen->loadBackground("pyramid3.raw");
-	_screen->saveBackground(1);
-
-	SpriteResource sprites[3] = {
-		SpriteResource("title.int"), SpriteResource("pyratop.int"), SpriteResource("pyramid.int")
-	};
-	Common::File voc[2];
-	voc[0].open("pharoh1a.voc");
-	voc[1].open("pharoh1b.voc");
-
-	_screen->vertMerge(SCREEN_HEIGHT);
-	_screen->loadPage(0);
-	_screen->loadPage(1);
-
-	int yp = 0;
-	int frame = 0;
-	int idx1 = 0;
-	bool skipElapsed = false;
-	uint32 timeExpired = 0;
-//	bool fadeFlag = true;
-
-	for (int idx = 200; idx > 0; ) {
-		_events->updateGameCounter();
-		_screen->vertMerge(yp);
-
-		sprites[0].draw(*_screen, 0);
-		if (frame)
-			sprites[0].draw(*_screen, frame);
-
-		idx1 = (idx1 + 1) % 4;
-		if (!idx1)
-			frame = (frame + 1) % 10;
-
-		_screen->draw();
-		if (!skipElapsed) {
-			timeExpired = MAX(_events->timeElapsed(), (uint32)1);
-			skipElapsed = true;
-		}
-
-		idx -= timeExpired;
-		frame = MIN(frame + timeExpired, (uint)200);
-
-		while (_events->timeElapsed() < 1) {
-			_events->pollEventsAndWait();
-			if (_events->isKeyMousePressed())
-				return;
-		}
-	}
-
-	_screen->vertMerge(SCREEN_HEIGHT);
-	_screen->saveBackground(1);
-	_screen->draw();
-	_screen->freePages();
-
-	_events->updateGameCounter();
-	pause(30);
-
-	// TODO: More
-	_sound->playSong(voc[0]);
-	_sound->playSong(voc[1]);
-}
-
-} // End of namespace Xeen
diff --git a/engines/xeen/darkside/darkside_game.h b/engines/xeen/darkside/darkside_game.h
deleted file mode 100644
index 979885c..0000000
--- a/engines/xeen/darkside/darkside_game.h
+++ /dev/null
@@ -1,50 +0,0 @@
-/* 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_DARKSIDE_GAME_H
-#define XEEN_DARKSIDE_GAME_H
-
-#include "xeen/xeen.h"
-
-namespace Xeen {
-
-class DarkSideEngine : virtual public XeenEngine {
-private:
-	bool pause(uint amount);
-
-	void showTitle1();
-
-	void showTitle2();
-
-	void showStartSequence();
-protected:
-	void darkSideIntro();
-
-	virtual void playGame();
-public:
-	DarkSideEngine(OSystem *syst, const XeenGameDescription *gameDesc);
-	virtual ~DarkSideEngine() {}
-};
-
-} // End of namespace Xeen
-
-#endif /* XEEN_DARKSIDE_GAME_H */
diff --git a/engines/xeen/detection.cpp b/engines/xeen/detection.cpp
index 3bd4c22..64b28bf 100644
--- a/engines/xeen/detection.cpp
+++ b/engines/xeen/detection.cpp
@@ -21,8 +21,6 @@
  */
 
 #include "xeen/xeen.h"
-#include "xeen/clouds/clouds_game.h"
-#include "xeen/darkside/darkside_game.h"
 #include "xeen/worldofxeen/worldofxeen_game.h"
 
 #include "base/plugins.h"
@@ -116,11 +114,7 @@ bool XeenMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGame
 
 	switch (gd->gameID) {
 	case Xeen::GType_Clouds:
-		*engine = new Xeen::CloudsEngine(syst, gd);
-		break;
 	case Xeen::GType_DarkSide:
-		*engine = new Xeen::DarkSideEngine(syst, gd);
-		break;
 	case Xeen::GType_WorldOfXeen:
 		*engine = new Xeen::WorldOfXeenEngine(syst, gd);
 		break;
diff --git a/engines/xeen/module.mk b/engines/xeen/module.mk
index 4e64b8e..711be84 100644
--- a/engines/xeen/module.mk
+++ b/engines/xeen/module.mk
@@ -1,8 +1,6 @@
 MODULE := engines/xeen
 
 MODULE_OBJS := \
-	clouds/clouds_game.o \
-	darkside/darkside_game.o \
 	worldofxeen/worldofxeen_game.o \
 	character.o \
 	combat.o \
diff --git a/engines/xeen/worldofxeen/worldofxeen_game.cpp b/engines/xeen/worldofxeen/worldofxeen_game.cpp
index bcfbaa1..3b0efb2 100644
--- a/engines/xeen/worldofxeen/worldofxeen_game.cpp
+++ b/engines/xeen/worldofxeen/worldofxeen_game.cpp
@@ -25,12 +25,191 @@
 namespace Xeen {
 
 WorldOfXeenEngine::WorldOfXeenEngine(OSystem *syst, const XeenGameDescription *gameDesc)
-		: CloudsEngine(syst, gameDesc), DarkSideEngine(syst, gameDesc), 
-		XeenEngine(syst, gameDesc) {
+		: XeenEngine(syst, gameDesc) {
 }
 
 void WorldOfXeenEngine::playGame () {
 	XeenEngine::playGame();
 }
 
+void WorldOfXeenEngine::showDarkSideTitle() {
+	showDarkSideTitle1();
+	if (shouldQuit())
+	return;
+
+	showDarkSideTitle2();
+	if (shouldQuit())
+	return;
+	
+	// TODO: Only show intro sequence if not seen before
+	showDarkSideIntroSequence();
+}
+
+void WorldOfXeenEngine::showDarkSideTitle1() {
+	// TODO: Starting method, and sound
+	//sub_28F40
+	_screen->loadPalette("dark.pal");
+	SpriteResource nwc[4] = {
+		SpriteResource("nwc1.int"), SpriteResource("nwc2.int"),
+		SpriteResource("nwc3.int"), SpriteResource("nwc4.int")
+	};
+	Common::File voc[3];
+	voc[0].open("dragon1.voc");
+	voc[1].open("dragon2.voc");
+	voc[2].open("dragon3.voc");
+
+	// Load backgrounds
+	_screen->loadBackground("nwc1.raw");
+	_screen->loadPage(0);
+	_screen->loadBackground("nwc2.raw");
+	_screen->loadPage(1);
+
+	// Draw the screen and fade it in
+	_screen->horizMerge(0);
+	_screen->draw();
+	_screen->fadeIn(4);
+
+	// Initial loop for dragon roaring
+	int nwcIndex = 0, nwcFrame = 0;
+	for (int idx = 0; idx < 55 && !shouldQuit(); ++idx) {
+		// Render the next frame
+		_events->updateGameCounter();
+		_screen->vertMerge(0);
+		nwc[nwcIndex].draw(*_screen, nwcFrame);
+		_screen->draw();
+
+		switch (idx) {
+		case 17:
+			_sound->proc2(voc[0]);
+			break;
+		case 34:
+		case 44:
+			++nwcIndex;
+			nwcFrame = 0;
+			break;
+		case 35:
+			_sound->proc2(voc[1]);
+			break;
+		default:
+			++nwcFrame;
+		}
+
+		if (_events->wait(2, true))
+			return;
+	}
+
+	// Loop for dragon using flyspray
+	for (int idx = 0; idx < 42 && !shouldQuit(); ++idx) {
+		_events->updateGameCounter();
+		_screen->vertMerge(SCREEN_HEIGHT);
+		nwc[3].draw(*_screen, idx);
+		_screen->draw();
+
+		switch (idx) {
+		case 3:
+			_sound->startMusic(40);
+			break;
+		case 11:
+			_sound->startMusic(0);
+		case 27:
+		case 30:
+			_sound->startMusic(3);
+			break;
+		case 31:
+			_sound->proc2(voc[2]);
+			break;
+		case 33:
+			_sound->startMusic(2);
+			break;
+		default:
+			break;
+		}
+
+		if (_events->wait(2, true))
+			return;
+	}
+
+	// Pause for a bit
+	_events->wait(10, true);
+}
+
+void WorldOfXeenEngine::showDarkSideTitle2() {
+	_screen->fadeOut(8);
+	//TODO: Stuff
+
+	_screen->loadBackground("jvc.raw");
+	_screen->draw();
+	_screen->fadeIn(4);
+
+	_events->updateGameCounter();
+	_events->wait(60, true);
+}
+
+void WorldOfXeenEngine::showDarkSideIntroSequence() {
+	_screen->fadeOut(8);
+	_screen->loadBackground("pyramid2.raw");
+	_screen->loadPage(0);
+	_screen->loadPage(1);
+	_screen->loadBackground("pyramid3.raw");
+	_screen->saveBackground(1);
+
+	SpriteResource sprites[3] = {
+		SpriteResource("title.int"), SpriteResource("pyratop.int"), SpriteResource("pyramid.int")
+	};
+	Common::File voc[2];
+	voc[0].open("pharoh1a.voc");
+	voc[1].open("pharoh1b.voc");
+
+	_screen->vertMerge(SCREEN_HEIGHT);
+	_screen->loadPage(0);
+	_screen->loadPage(1);
+
+	int yp = 0;
+	int frame = 0;
+	int idx1 = 0;
+	bool skipElapsed = false;
+	uint32 timeExpired = 0;
+	//	bool fadeFlag = true;
+
+	for (int idx = 200; idx > 0; ) {
+		_events->updateGameCounter();
+		_screen->vertMerge(yp);
+
+		sprites[0].draw(*_screen, 0);
+		if (frame)
+			sprites[0].draw(*_screen, frame);
+
+		idx1 = (idx1 + 1) % 4;
+		if (!idx1)
+			frame = (frame + 1) % 10;
+
+		_screen->draw();
+		if (!skipElapsed) {
+			timeExpired = MAX(_events->timeElapsed(), (uint32)1);
+			skipElapsed = true;
+		}
+
+		idx -= timeExpired;
+		frame = MIN(frame + timeExpired, (uint)200);
+
+		while (_events->timeElapsed() < 1) {
+			_events->pollEventsAndWait();
+			if (_events->isKeyMousePressed())
+				return;
+		}
+	}
+
+	_screen->vertMerge(SCREEN_HEIGHT);
+	_screen->saveBackground(1);
+	_screen->draw();
+	_screen->freePages();
+
+	_events->updateGameCounter();
+	_events->wait(30, true);
+
+	// TODO: More
+	_sound->playSong(voc[0]);
+	_sound->playSong(voc[1]);
+}
+
 } // End of namespace Xeen
diff --git a/engines/xeen/worldofxeen/worldofxeen_game.h b/engines/xeen/worldofxeen/worldofxeen_game.h
index 7227e11..9a3cee1 100644
--- a/engines/xeen/worldofxeen/worldofxeen_game.h
+++ b/engines/xeen/worldofxeen/worldofxeen_game.h
@@ -23,12 +23,36 @@
 #ifndef XEEN_WORLDOFXEEN_GAME_H
 #define XEEN_WORLDOFXEEN_GAME_H
 
-#include "xeen/clouds/clouds_game.h"
-#include "xeen/darkside/darkside_game.h"
+#include "xeen/xeen.h"
 
 namespace Xeen {
 
-class WorldOfXeenEngine : public DarkSideEngine, CloudsEngine {
+/**
+ * Implements a descendant of the base Xeen engine to handle 
+ * Clouds of Xeen, Dark Side of Xeen, and Worlds of Xeen specific
+ * game code
+ */
+class WorldOfXeenEngine: public XeenEngine {
+private:
+	/**
+	 * Shows the first part of the Dark Side of Xeen title sequence
+	 */
+	void showDarkSideTitle1();
+
+	/**
+	 * Shows the second part of the Dark Side of Xeen title sequence
+	 */
+	void showDarkSideTitle2();
+
+	/**
+	 * Shows the Dark Side of Xeen title sequence
+	 */
+	void showDarkSideTitle();
+
+	/**
+	 * Shows the Dark Side of Xeen introduction sequence
+	 */
+	void showDarkSideIntroSequence();
 protected:
 	virtual void playGame();
 public:


Commit: b6e39dbf79801b5d96ca9292a47825d39f1e3fb4
    https://github.com/scummvm/scummvm/commit/b6e39dbf79801b5d96ca9292a47825d39f1e3fb4
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-11-20T20:11:23-05:00

Commit Message:
XEEN: Some initial work on better sound manager

Changed paths:
    engines/xeen/sound.cpp
    engines/xeen/sound.h
    engines/xeen/worldofxeen/worldofxeen_game.cpp
    engines/xeen/worldofxeen/worldofxeen_game.h
    engines/xeen/xeen.cpp
    engines/xeen/xeen.h



diff --git a/engines/xeen/sound.cpp b/engines/xeen/sound.cpp
index 7c7524a..a71584c 100644
--- a/engines/xeen/sound.cpp
+++ b/engines/xeen/sound.cpp
@@ -24,6 +24,18 @@
 
 namespace Xeen {
 
+VOC::~VOC() {
+	stop();
+}
+
+void VOC::play() {
+	warning("TODO: VOC::play");
+}
+
+void VOC::stop() {
+	warning("TODO: VOC::stop");
+}
+
 SoundManager::SoundManager(XeenEngine *vm): _vm(vm) {
 }
 
diff --git a/engines/xeen/sound.h b/engines/xeen/sound.h
index 7e7df9c..b44bff7 100644
--- a/engines/xeen/sound.h
+++ b/engines/xeen/sound.h
@@ -29,6 +29,21 @@
 
 namespace Xeen {
 
+class VOC: public Common::File {
+public:
+	virtual ~VOC();
+
+	/**
+	 * Play the given loaded sound
+	 */
+	void play();
+
+	/**
+	 * Stop playing the sound
+	 */
+	void stop();
+};
+
 class SoundManager {
 private:
 	XeenEngine *_vm;
diff --git a/engines/xeen/worldofxeen/worldofxeen_game.cpp b/engines/xeen/worldofxeen/worldofxeen_game.cpp
index 3b0efb2..836f039 100644
--- a/engines/xeen/worldofxeen/worldofxeen_game.cpp
+++ b/engines/xeen/worldofxeen/worldofxeen_game.cpp
@@ -21,6 +21,7 @@
  */
 
 #include "xeen/worldofxeen/worldofxeen_game.h"
+#include "xeen/sound.h"
 
 namespace Xeen {
 
@@ -28,24 +29,15 @@ WorldOfXeenEngine::WorldOfXeenEngine(OSystem *syst, const XeenGameDescription *g
 		: XeenEngine(syst, gameDesc) {
 }
 
-void WorldOfXeenEngine::playGame () {
-	XeenEngine::playGame();
-}
-
-void WorldOfXeenEngine::showDarkSideTitle() {
-	showDarkSideTitle1();
-	if (shouldQuit())
-	return;
+void WorldOfXeenEngine::showIntro() {
+	// **DEBUG**
+	if (gDebugLevel == 0)
+		return;
 
-	showDarkSideTitle2();
-	if (shouldQuit())
-	return;
-	
-	// TODO: Only show intro sequence if not seen before
-	showDarkSideIntroSequence();
+	showDarkSideTitle();
 }
 
-void WorldOfXeenEngine::showDarkSideTitle1() {
+void WorldOfXeenEngine::showDarkSideTitle() {
 	// TODO: Starting method, and sound
 	//sub_28F40
 	_screen->loadPalette("dark.pal");
@@ -53,11 +45,22 @@ void WorldOfXeenEngine::showDarkSideTitle1() {
 		SpriteResource("nwc1.int"), SpriteResource("nwc2.int"),
 		SpriteResource("nwc3.int"), SpriteResource("nwc4.int")
 	};
-	Common::File voc[3];
+	VOC voc[3];
 	voc[0].open("dragon1.voc");
 	voc[1].open("dragon2.voc");
 	voc[2].open("dragon3.voc");
-
+/*
+	Common::File f;
+	f.open("adsnd");
+	Common::DumpFile df;
+	byte *b = new byte[f.size()];
+	f.read(b, f.size());
+	df.open("d:\\temp\\adsnd.bin");
+	df.write(b, f.size());
+	df.close();
+	f.close();
+	delete[] b;
+	*/
 	// Load backgrounds
 	_screen->loadBackground("nwc1.raw");
 	_screen->loadPage(0);
@@ -97,6 +100,8 @@ void WorldOfXeenEngine::showDarkSideTitle1() {
 		if (_events->wait(2, true))
 			return;
 	}
+	if (shouldQuit())
+		return;
 
 	// Loop for dragon using flyspray
 	for (int idx = 0; idx < 42 && !shouldQuit(); ++idx) {
@@ -130,10 +135,16 @@ void WorldOfXeenEngine::showDarkSideTitle1() {
 	}
 
 	// Pause for a bit
-	_events->wait(10, true);
-}
+	if (_events->wait(10, true))
+		return;
+	if (shouldQuit())
+		return;
+
+	voc[0].stop();
+	voc[1].stop();
+	voc[2].stop();
+
 
-void WorldOfXeenEngine::showDarkSideTitle2() {
 	_screen->fadeOut(8);
 	//TODO: Stuff
 
@@ -145,7 +156,7 @@ void WorldOfXeenEngine::showDarkSideTitle2() {
 	_events->wait(60, true);
 }
 
-void WorldOfXeenEngine::showDarkSideIntroSequence() {
+void WorldOfXeenEngine::showDarkSideIntro() {
 	_screen->fadeOut(8);
 	_screen->loadBackground("pyramid2.raw");
 	_screen->loadPage(0);
@@ -191,7 +202,7 @@ void WorldOfXeenEngine::showDarkSideIntroSequence() {
 
 		idx -= timeExpired;
 		frame = MIN(frame + timeExpired, (uint)200);
-
+		 
 		while (_events->timeElapsed() < 1) {
 			_events->pollEventsAndWait();
 			if (_events->isKeyMousePressed())
diff --git a/engines/xeen/worldofxeen/worldofxeen_game.h b/engines/xeen/worldofxeen/worldofxeen_game.h
index 9a3cee1..f35f25b 100644
--- a/engines/xeen/worldofxeen/worldofxeen_game.h
+++ b/engines/xeen/worldofxeen/worldofxeen_game.h
@@ -35,16 +35,6 @@ namespace Xeen {
 class WorldOfXeenEngine: public XeenEngine {
 private:
 	/**
-	 * Shows the first part of the Dark Side of Xeen title sequence
-	 */
-	void showDarkSideTitle1();
-
-	/**
-	 * Shows the second part of the Dark Side of Xeen title sequence
-	 */
-	void showDarkSideTitle2();
-
-	/**
 	 * Shows the Dark Side of Xeen title sequence
 	 */
 	void showDarkSideTitle();
@@ -52,9 +42,9 @@ private:
 	/**
 	 * Shows the Dark Side of Xeen introduction sequence
 	 */
-	void showDarkSideIntroSequence();
+	void showDarkSideIntro();
 protected:
-	virtual void playGame();
+	virtual void showIntro();
 public:
 	WorldOfXeenEngine(OSystem *syst, const XeenGameDescription *gameDesc);
 	virtual ~WorldOfXeenEngine() {}
diff --git a/engines/xeen/xeen.cpp b/engines/xeen/xeen.cpp
index fb7edea..9034985 100644
--- a/engines/xeen/xeen.cpp
+++ b/engines/xeen/xeen.cpp
@@ -266,10 +266,6 @@ void XeenEngine::writeSavegameHeader(Common::OutSaveFile *out, XeenSavegameHeade
 //	out->writeUint32LE(_events->getFrameCounter());
 }
 
-void XeenEngine::showIntro() {
-
-}
-
 void XeenEngine::showMainMenu() {
 	//OptionsMenu::show(this);
 }
diff --git a/engines/xeen/xeen.h b/engines/xeen/xeen.h
index 4180a17..cd1b98b 100644
--- a/engines/xeen/xeen.h
+++ b/engines/xeen/xeen.h
@@ -104,8 +104,6 @@ private:
 	Common::RandomSource _randomSource;
 	int _loadSaveSlot;
 
-	void showIntro();
-
 	void showMainMenu();
 
 	void play();
@@ -114,6 +112,8 @@ private:
 
 	void gameLoop();
 protected:
+	virtual void showIntro() = 0;
+
 	/**
 	* Play the game
 	*/


Commit: 0ade2da5f1647ae1942a2a3e7aa26f219e5b7a2d
    https://github.com/scummvm/scummvm/commit/0ade2da5f1647ae1942a2a3e7aa26f219e5b7a2d
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-11-21T14:34:08-05:00

Commit Message:
XEEN: Further work on VOC sound method prototypes

Changed paths:
    engines/xeen/sound.h
    engines/xeen/worldofxeen/worldofxeen_game.cpp



diff --git a/engines/xeen/sound.h b/engines/xeen/sound.h
index b44bff7..fae3d76 100644
--- a/engines/xeen/sound.h
+++ b/engines/xeen/sound.h
@@ -29,14 +29,15 @@
 
 namespace Xeen {
 
+class SoundManager;
+
 class VOC: public Common::File {
+	friend class SoundManager;
+private:
+	SoundManager *_sound;
 public:
-	virtual ~VOC();
-
-	/**
-	 * Play the given loaded sound
-	 */
-	void play();
+	VOC() : _sound(nullptr) {}
+	virtual ~VOC() { stop(); }
 
 	/**
 	 * Stop playing the sound
@@ -58,6 +59,8 @@ public:
 
 	void playSong(Common::SeekableReadStream &f) {}
 
+	void playSound(VOC &voc) {}
+
 	void playSample(const Common::SeekableReadStream *stream, int v2 = 1) {}
 
 	bool playSample(int v1, int v2) { return false; }
diff --git a/engines/xeen/worldofxeen/worldofxeen_game.cpp b/engines/xeen/worldofxeen/worldofxeen_game.cpp
index 836f039..665507d 100644
--- a/engines/xeen/worldofxeen/worldofxeen_game.cpp
+++ b/engines/xeen/worldofxeen/worldofxeen_game.cpp
@@ -83,7 +83,7 @@ void WorldOfXeenEngine::showDarkSideTitle() {
 
 		switch (idx) {
 		case 17:
-			_sound->proc2(voc[0]);
+			_sound->playSound(voc[0]);
 			break;
 		case 34:
 		case 44:
@@ -91,7 +91,7 @@ void WorldOfXeenEngine::showDarkSideTitle() {
 			nwcFrame = 0;
 			break;
 		case 35:
-			_sound->proc2(voc[1]);
+			_sound->playSound(voc[1]);
 			break;
 		default:
 			++nwcFrame;


Commit: 82117272854a11ecd2ed5db1c7715de7f15f96c0
    https://github.com/scummvm/scummvm/commit/82117272854a11ecd2ed5db1c7715de7f15f96c0
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-11-21T16:22:50-05:00

Commit Message:
XEEN: Remove duplicate methods

Changed paths:
    engines/xeen/sound.cpp



diff --git a/engines/xeen/sound.cpp b/engines/xeen/sound.cpp
index a71584c..e0b1221 100644
--- a/engines/xeen/sound.cpp
+++ b/engines/xeen/sound.cpp
@@ -24,14 +24,6 @@
 
 namespace Xeen {
 
-VOC::~VOC() {
-	stop();
-}
-
-void VOC::play() {
-	warning("TODO: VOC::play");
-}
-
 void VOC::stop() {
 	warning("TODO: VOC::stop");
 }


Commit: 9c92f9fa476219b7c775676565d7b3ebdd8d2c1e
    https://github.com/scummvm/scummvm/commit/9c92f9fa476219b7c775676565d7b3ebdd8d2c1e
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-11-29T11:34:28-05:00

Commit Message:
XEEN: Moved in-progress Dark Side intro to it's own file

Changed paths:
  A engines/xeen/worldofxeen/darkside_intro.cpp
  A engines/xeen/worldofxeen/darkside_intro.h
    engines/xeen/module.mk
    engines/xeen/worldofxeen/worldofxeen_game.cpp
    engines/xeen/worldofxeen/worldofxeen_game.h



diff --git a/engines/xeen/module.mk b/engines/xeen/module.mk
index 711be84..a1e62e1 100644
--- a/engines/xeen/module.mk
+++ b/engines/xeen/module.mk
@@ -1,6 +1,7 @@
 MODULE := engines/xeen
 
 MODULE_OBJS := \
+	worldofxeen/darkside_intro.o \
 	worldofxeen/worldofxeen_game.o \
 	character.o \
 	combat.o \
diff --git a/engines/xeen/worldofxeen/darkside_intro.cpp b/engines/xeen/worldofxeen/darkside_intro.cpp
new file mode 100644
index 0000000..2d284c1
--- /dev/null
+++ b/engines/xeen/worldofxeen/darkside_intro.cpp
@@ -0,0 +1,222 @@
+/* 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 "xeen/worldofxeen/worldofxeen_game.h"
+#include "xeen/sound.h"
+
+namespace Xeen {
+
+void showDarkSideTitle(XeenEngine &vm) {
+	EventsManager &events = *vm._events;
+	Screen &screen = *vm._screen;
+	SoundManager &sound = *vm._sound;
+	
+	// TODO: Starting method, and sound
+	//sub_28F40
+	screen.loadPalette("dark.pal");
+	SpriteResource nwc[4] = {
+		SpriteResource("nwc1.int"), SpriteResource("nwc2.int"),
+		SpriteResource("nwc3.int"), SpriteResource("nwc4.int")
+	};
+	VOC voc[3];
+	voc[0].open("dragon1.voc");
+	voc[1].open("dragon2.voc");
+	voc[2].open("dragon3.voc");
+/*
+	Common::File f;
+	f.open("adsnd");
+	Common::DumpFile df;
+	byte *b = new byte[f.size()];
+	f.read(b, f.size());
+	df.open("d:\\temp\\adsnd.bin");
+	df.write(b, f.size());
+	df.close();
+	f.close();
+	delete[] b;
+	*/
+	// Load backgrounds
+	screen.loadBackground("nwc1.raw");
+	screen.loadPage(0);
+	screen.loadBackground("nwc2.raw");
+	screen.loadPage(1);
+
+	// Draw the screen and fade it in
+	screen.horizMerge(0);
+	screen.draw();
+	screen.fadeIn(4);
+
+	// Initial loop for dragon roaring
+	int nwcIndex = 0, nwcFrame = 0;
+	for (int idx = 0; idx < 55 && !vm.shouldQuit(); ++idx) {
+		// Render the next frame
+		events.updateGameCounter();
+		screen.vertMerge(0);
+		nwc[nwcIndex].draw(screen, nwcFrame);
+		screen.draw();
+
+		switch (idx) {
+		case 17:
+			sound.playSound(voc[0]);
+			break;
+		case 34:
+		case 44:
+			++nwcIndex;
+			nwcFrame = 0;
+			break;
+		case 35:
+			sound.playSound(voc[1]);
+			break;
+		default:
+			++nwcFrame;
+		}
+
+		if (events.wait(2, true))
+			return;
+	}
+	if (vm.shouldQuit())
+		return;
+
+	// Loop for dragon using flyspray
+	for (int idx = 0; idx < 42 && !vm.shouldQuit(); ++idx) {
+		events.updateGameCounter();
+		screen.vertMerge(SCREEN_HEIGHT);
+		nwc[3].draw(screen, idx);
+		screen.draw();
+
+		switch (idx) {
+		case 3:
+			sound.startMusic(40);
+			break;
+		case 11:
+			sound.startMusic(0);
+		case 27:
+		case 30:
+			sound.startMusic(3);
+			break;
+		case 31:
+			sound.proc2(voc[2]);
+			break;
+		case 33:
+			sound.startMusic(2);
+			break;
+		default:
+			break;
+		}
+
+		if (events.wait(2, true))
+			return;
+	}
+
+	// Pause for a bit
+	if (events.wait(10, true))
+		return;
+	if (vm.shouldQuit())
+		return;
+
+	voc[0].stop();
+	voc[1].stop();
+	voc[2].stop();
+
+
+	screen.fadeOut(8);
+	//TODO: Stuff
+
+	screen.loadBackground("jvc.raw");
+	screen.draw();
+	screen.fadeIn(4);
+
+	events.updateGameCounter();
+	events.wait(60, true);
+}
+
+void showDarkSideIntro(XeenEngine &vm) {
+	EventsManager &events = *vm._events;
+	Screen &screen = *vm._screen;
+	SoundManager &sound = *vm._sound;
+
+	screen.fadeOut(8);
+	screen.loadBackground("pyramid2.raw");
+	screen.loadPage(0);
+	screen.loadPage(1);
+	screen.loadBackground("pyramid3.raw");
+	screen.saveBackground(1);
+
+	SpriteResource sprites[3] = {
+		SpriteResource("title.int"), SpriteResource("pyratop.int"), SpriteResource("pyramid.int")
+	};
+	Common::File voc[2];
+	voc[0].open("pharoh1a.voc");
+	voc[1].open("pharoh1b.voc");
+
+	screen.vertMerge(SCREEN_HEIGHT);
+	screen.loadPage(0);
+	screen.loadPage(1);
+
+	int yp = 0;
+	int frame = 0;
+	int idx1 = 0;
+	bool skipElapsed = false;
+	uint32 timeExpired = 0;
+	//	bool fadeFlag = true;
+
+	for (int idx = 200; idx > 0; ) {
+		events.updateGameCounter();
+		screen.vertMerge(yp);
+
+		sprites[0].draw(screen, 0);
+		if (frame)
+			sprites[0].draw(screen, frame);
+
+		idx1 = (idx1 + 1) % 4;
+		if (!idx1)
+			frame = (frame + 1) % 10;
+
+		screen.draw();
+		if (!skipElapsed) {
+			timeExpired = MAX(events.timeElapsed(), (uint32)1);
+			skipElapsed = true;
+		}
+
+		idx -= timeExpired;
+		frame = MIN(frame + timeExpired, (uint)200);
+		 
+		while (events.timeElapsed() < 1) {
+			events.pollEventsAndWait();
+			if (events.isKeyMousePressed())
+				return;
+		}
+	}
+
+	screen.vertMerge(SCREEN_HEIGHT);
+	screen.saveBackground(1);
+	screen.draw();
+	screen.freePages();
+
+	events.updateGameCounter();
+	events.wait(30, true);
+
+	// TODO: More
+	sound.playSong(voc[0]);
+	sound.playSong(voc[1]);
+}
+
+} // End of namespace Xeen
diff --git a/engines/xeen/worldofxeen/darkside_intro.h b/engines/xeen/worldofxeen/darkside_intro.h
new file mode 100644
index 0000000..535ee21
--- /dev/null
+++ b/engines/xeen/worldofxeen/darkside_intro.h
@@ -0,0 +1,36 @@
+/* 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_DARKSIDE_INTRO_H
+#define XEEN_DARKSIDE_INTRO_H
+
+#include "xeen/xeen.h"
+
+namespace Xeen {
+
+void showDarkSideTitle(XeenEngine &vm);
+
+void showDarkSideIntro(XeenEngine &vm);
+
+} // End of namespace Xeen
+
+#endif /* XEEN_DARKSIDE_INTRO_H */
diff --git a/engines/xeen/worldofxeen/worldofxeen_game.cpp b/engines/xeen/worldofxeen/worldofxeen_game.cpp
index 665507d..125f9f2 100644
--- a/engines/xeen/worldofxeen/worldofxeen_game.cpp
+++ b/engines/xeen/worldofxeen/worldofxeen_game.cpp
@@ -21,6 +21,7 @@
  */
 
 #include "xeen/worldofxeen/worldofxeen_game.h"
+#include "xeen/worldofxeen/darkside_intro.h"
 #include "xeen/sound.h"
 
 namespace Xeen {
@@ -34,193 +35,7 @@ void WorldOfXeenEngine::showIntro() {
 	if (gDebugLevel == 0)
 		return;
 
-	showDarkSideTitle();
-}
-
-void WorldOfXeenEngine::showDarkSideTitle() {
-	// TODO: Starting method, and sound
-	//sub_28F40
-	_screen->loadPalette("dark.pal");
-	SpriteResource nwc[4] = {
-		SpriteResource("nwc1.int"), SpriteResource("nwc2.int"),
-		SpriteResource("nwc3.int"), SpriteResource("nwc4.int")
-	};
-	VOC voc[3];
-	voc[0].open("dragon1.voc");
-	voc[1].open("dragon2.voc");
-	voc[2].open("dragon3.voc");
-/*
-	Common::File f;
-	f.open("adsnd");
-	Common::DumpFile df;
-	byte *b = new byte[f.size()];
-	f.read(b, f.size());
-	df.open("d:\\temp\\adsnd.bin");
-	df.write(b, f.size());
-	df.close();
-	f.close();
-	delete[] b;
-	*/
-	// Load backgrounds
-	_screen->loadBackground("nwc1.raw");
-	_screen->loadPage(0);
-	_screen->loadBackground("nwc2.raw");
-	_screen->loadPage(1);
-
-	// Draw the screen and fade it in
-	_screen->horizMerge(0);
-	_screen->draw();
-	_screen->fadeIn(4);
-
-	// Initial loop for dragon roaring
-	int nwcIndex = 0, nwcFrame = 0;
-	for (int idx = 0; idx < 55 && !shouldQuit(); ++idx) {
-		// Render the next frame
-		_events->updateGameCounter();
-		_screen->vertMerge(0);
-		nwc[nwcIndex].draw(*_screen, nwcFrame);
-		_screen->draw();
-
-		switch (idx) {
-		case 17:
-			_sound->playSound(voc[0]);
-			break;
-		case 34:
-		case 44:
-			++nwcIndex;
-			nwcFrame = 0;
-			break;
-		case 35:
-			_sound->playSound(voc[1]);
-			break;
-		default:
-			++nwcFrame;
-		}
-
-		if (_events->wait(2, true))
-			return;
-	}
-	if (shouldQuit())
-		return;
-
-	// Loop for dragon using flyspray
-	for (int idx = 0; idx < 42 && !shouldQuit(); ++idx) {
-		_events->updateGameCounter();
-		_screen->vertMerge(SCREEN_HEIGHT);
-		nwc[3].draw(*_screen, idx);
-		_screen->draw();
-
-		switch (idx) {
-		case 3:
-			_sound->startMusic(40);
-			break;
-		case 11:
-			_sound->startMusic(0);
-		case 27:
-		case 30:
-			_sound->startMusic(3);
-			break;
-		case 31:
-			_sound->proc2(voc[2]);
-			break;
-		case 33:
-			_sound->startMusic(2);
-			break;
-		default:
-			break;
-		}
-
-		if (_events->wait(2, true))
-			return;
-	}
-
-	// Pause for a bit
-	if (_events->wait(10, true))
-		return;
-	if (shouldQuit())
-		return;
-
-	voc[0].stop();
-	voc[1].stop();
-	voc[2].stop();
-
-
-	_screen->fadeOut(8);
-	//TODO: Stuff
-
-	_screen->loadBackground("jvc.raw");
-	_screen->draw();
-	_screen->fadeIn(4);
-
-	_events->updateGameCounter();
-	_events->wait(60, true);
-}
-
-void WorldOfXeenEngine::showDarkSideIntro() {
-	_screen->fadeOut(8);
-	_screen->loadBackground("pyramid2.raw");
-	_screen->loadPage(0);
-	_screen->loadPage(1);
-	_screen->loadBackground("pyramid3.raw");
-	_screen->saveBackground(1);
-
-	SpriteResource sprites[3] = {
-		SpriteResource("title.int"), SpriteResource("pyratop.int"), SpriteResource("pyramid.int")
-	};
-	Common::File voc[2];
-	voc[0].open("pharoh1a.voc");
-	voc[1].open("pharoh1b.voc");
-
-	_screen->vertMerge(SCREEN_HEIGHT);
-	_screen->loadPage(0);
-	_screen->loadPage(1);
-
-	int yp = 0;
-	int frame = 0;
-	int idx1 = 0;
-	bool skipElapsed = false;
-	uint32 timeExpired = 0;
-	//	bool fadeFlag = true;
-
-	for (int idx = 200; idx > 0; ) {
-		_events->updateGameCounter();
-		_screen->vertMerge(yp);
-
-		sprites[0].draw(*_screen, 0);
-		if (frame)
-			sprites[0].draw(*_screen, frame);
-
-		idx1 = (idx1 + 1) % 4;
-		if (!idx1)
-			frame = (frame + 1) % 10;
-
-		_screen->draw();
-		if (!skipElapsed) {
-			timeExpired = MAX(_events->timeElapsed(), (uint32)1);
-			skipElapsed = true;
-		}
-
-		idx -= timeExpired;
-		frame = MIN(frame + timeExpired, (uint)200);
-		 
-		while (_events->timeElapsed() < 1) {
-			_events->pollEventsAndWait();
-			if (_events->isKeyMousePressed())
-				return;
-		}
-	}
-
-	_screen->vertMerge(SCREEN_HEIGHT);
-	_screen->saveBackground(1);
-	_screen->draw();
-	_screen->freePages();
-
-	_events->updateGameCounter();
-	_events->wait(30, true);
-
-	// TODO: More
-	_sound->playSong(voc[0]);
-	_sound->playSong(voc[1]);
+	showDarkSideTitle(*this);
 }
 
 } // End of namespace Xeen
diff --git a/engines/xeen/worldofxeen/worldofxeen_game.h b/engines/xeen/worldofxeen/worldofxeen_game.h
index f35f25b..f81f566 100644
--- a/engines/xeen/worldofxeen/worldofxeen_game.h
+++ b/engines/xeen/worldofxeen/worldofxeen_game.h
@@ -33,16 +33,6 @@ namespace Xeen {
  * game code
  */
 class WorldOfXeenEngine: public XeenEngine {
-private:
-	/**
-	 * Shows the Dark Side of Xeen title sequence
-	 */
-	void showDarkSideTitle();
-
-	/**
-	 * Shows the Dark Side of Xeen introduction sequence
-	 */
-	void showDarkSideIntro();
 protected:
 	virtual void showIntro();
 public:


Commit: 5b0f460581e9deb08fc0f66e8faeb356f31c2ae5
    https://github.com/scummvm/scummvm/commit/5b0f460581e9deb08fc0f66e8faeb356f31c2ae5
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-11-29T22:32:07-05:00

Commit Message:
XEEN: Implementing more of Dark Side intro

Changed paths:
    engines/xeen/sound.cpp
    engines/xeen/sound.h
    engines/xeen/worldofxeen/darkside_intro.cpp
    engines/xeen/worldofxeen/darkside_intro.h
    engines/xeen/worldofxeen/worldofxeen_game.cpp
    engines/xeen/worldofxeen/worldofxeen_game.h



diff --git a/engines/xeen/sound.cpp b/engines/xeen/sound.cpp
index e0b1221..00b9247 100644
--- a/engines/xeen/sound.cpp
+++ b/engines/xeen/sound.cpp
@@ -39,5 +39,8 @@ void SoundManager::startMusic(int v1) {
 
 }
 
+void SoundManager::stopMusic(int id) {
+}
+
 
 } // End of namespace Xeen
diff --git a/engines/xeen/sound.h b/engines/xeen/sound.h
index fae3d76..5c123d7 100644
--- a/engines/xeen/sound.h
+++ b/engines/xeen/sound.h
@@ -57,6 +57,8 @@ public:
 
 	void startMusic(int v1);
 
+	void stopMusic(int id);
+
 	void playSong(Common::SeekableReadStream &f) {}
 
 	void playSound(VOC &voc) {}
diff --git a/engines/xeen/worldofxeen/darkside_intro.cpp b/engines/xeen/worldofxeen/darkside_intro.cpp
index 2d284c1..8148e24 100644
--- a/engines/xeen/worldofxeen/darkside_intro.cpp
+++ b/engines/xeen/worldofxeen/darkside_intro.cpp
@@ -25,7 +25,7 @@
 
 namespace Xeen {
 
-void showDarkSideTitle(XeenEngine &vm) {
+bool showDarkSideTitle(XeenEngine &vm) {
 	EventsManager &events = *vm._events;
 	Screen &screen = *vm._screen;
 	SoundManager &sound = *vm._sound;
@@ -41,18 +41,7 @@ void showDarkSideTitle(XeenEngine &vm) {
 	voc[0].open("dragon1.voc");
 	voc[1].open("dragon2.voc");
 	voc[2].open("dragon3.voc");
-/*
-	Common::File f;
-	f.open("adsnd");
-	Common::DumpFile df;
-	byte *b = new byte[f.size()];
-	f.read(b, f.size());
-	df.open("d:\\temp\\adsnd.bin");
-	df.write(b, f.size());
-	df.close();
-	f.close();
-	delete[] b;
-	*/
+
 	// Load backgrounds
 	screen.loadBackground("nwc1.raw");
 	screen.loadPage(0);
@@ -90,10 +79,8 @@ void showDarkSideTitle(XeenEngine &vm) {
 		}
 
 		if (events.wait(2, true))
-			return;
+			return false;
 	}
-	if (vm.shouldQuit())
-		return;
 
 	// Loop for dragon using flyspray
 	for (int idx = 0; idx < 42 && !vm.shouldQuit(); ++idx) {
@@ -123,35 +110,41 @@ void showDarkSideTitle(XeenEngine &vm) {
 		}
 
 		if (events.wait(2, true))
-			return;
+			return false;
 	}
 
 	// Pause for a bit
 	if (events.wait(10, true))
-		return;
-	if (vm.shouldQuit())
-		return;
+		return false;
 
 	voc[0].stop();
 	voc[1].stop();
 	voc[2].stop();
-
-
-	screen.fadeOut(8);
-	//TODO: Stuff
+	sound.stopMusic(95);
 
 	screen.loadBackground("jvc.raw");
+	screen.fadeOut(8);
 	screen.draw();
 	screen.fadeIn(4);
 
 	events.updateGameCounter();
 	events.wait(60, true);
+	return true;
 }
 
-void showDarkSideIntro(XeenEngine &vm) {
+bool showDarkSideIntro(XeenEngine &vm) {
 	EventsManager &events = *vm._events;
 	Screen &screen = *vm._screen;
 	SoundManager &sound = *vm._sound;
+	const int XLIST1[] = {
+		0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 58, 60, 62
+	};
+	const int YLIST1[] = {
+		0, 5, 10, 15, 20, 25, 30, 35, 40, 40, 39, 37, 35, 33, 31
+	};
+	const int XLIST2[] = {
+		160, 155, 150, 145, 140, 135, 130, 125, 120, 115, 110, 105, 98, 90, 82
+	};
 
 	screen.fadeOut(8);
 	screen.loadBackground("pyramid2.raw");
@@ -171,38 +164,42 @@ void showDarkSideIntro(XeenEngine &vm) {
 	screen.loadPage(0);
 	screen.loadPage(1);
 
+	// Show Might and Magic Darkside of Xeen title, and gradualy scroll
+	// the background vertically down to show the Pharoah's base
 	int yp = 0;
-	int frame = 0;
+	int frameNum = 0;
 	int idx1 = 0;
 	bool skipElapsed = false;
 	uint32 timeExpired = 0;
-	//	bool fadeFlag = true;
+	bool fadeFlag = true;
 
-	for (int idx = 200; idx > 0; ) {
+	for (int yCtr = SCREEN_HEIGHT; yCtr > 0; ) {
 		events.updateGameCounter();
 		screen.vertMerge(yp);
 
 		sprites[0].draw(screen, 0);
-		if (frame)
-			sprites[0].draw(screen, frame);
+		if (frameNum)
+			sprites[0].draw(screen, frameNum);
 
 		idx1 = (idx1 + 1) % 4;
 		if (!idx1)
-			frame = (frame + 1) % 10;
+			frameNum = (frameNum + 1) % 10;
 
 		screen.draw();
 		if (!skipElapsed) {
-			timeExpired = MAX(events.timeElapsed(), (uint32)1);
+			timeExpired = MAX((int)events.timeElapsed() - 1, 1);
 			skipElapsed = true;
 		}
 
-		idx -= timeExpired;
-		frame = MIN(frame + timeExpired, (uint)200);
+		yCtr -= timeExpired;
+		yp = MIN(yp + timeExpired, (uint)200);
 		 
-		while (events.timeElapsed() < 1) {
-			events.pollEventsAndWait();
-			if (events.isKeyMousePressed())
-				return;
+		if (events.wait(1, true))
+			return false;
+
+		if (fadeFlag) {
+			screen.fadeIn(4);
+			fadeFlag = false;
 		}
 	}
 
@@ -214,9 +211,24 @@ void showDarkSideIntro(XeenEngine &vm) {
 	events.updateGameCounter();
 	events.wait(30, true);
 
+	// Zoom into the Pharoah's base closeup view
+	for (int idx = 14; idx >= 0; --idx) {
+		events.updateGameCounter();
+		sprites[1].draw(screen, 0, Common::Point(XLIST1[idx], YLIST1[idx]));
+		sprites[1].draw(screen, 1, Common::Point(XLIST2[idx], YLIST1[idx]));
+		screen.draw();
+
+		if (idx == 2)
+			sound.stopMusic(48);
+		if (events.wait(2, true))
+			return false;
+	}
+
 	// TODO: More
 	sound.playSong(voc[0]);
 	sound.playSong(voc[1]);
+
+	return true;
 }
 
 } // End of namespace Xeen
diff --git a/engines/xeen/worldofxeen/darkside_intro.h b/engines/xeen/worldofxeen/darkside_intro.h
index 535ee21..e37f095 100644
--- a/engines/xeen/worldofxeen/darkside_intro.h
+++ b/engines/xeen/worldofxeen/darkside_intro.h
@@ -27,9 +27,9 @@
 
 namespace Xeen {
 
-void showDarkSideTitle(XeenEngine &vm);
+bool showDarkSideTitle(XeenEngine &vm);
 
-void showDarkSideIntro(XeenEngine &vm);
+bool showDarkSideIntro(XeenEngine &vm);
 
 } // End of namespace Xeen
 
diff --git a/engines/xeen/worldofxeen/worldofxeen_game.cpp b/engines/xeen/worldofxeen/worldofxeen_game.cpp
index 125f9f2..f7c9336 100644
--- a/engines/xeen/worldofxeen/worldofxeen_game.cpp
+++ b/engines/xeen/worldofxeen/worldofxeen_game.cpp
@@ -28,6 +28,7 @@ namespace Xeen {
 
 WorldOfXeenEngine::WorldOfXeenEngine(OSystem *syst, const XeenGameDescription *gameDesc)
 		: XeenEngine(syst, gameDesc) {
+	_seenDarkSideIntro = false;
 }
 
 void WorldOfXeenEngine::showIntro() {
@@ -35,7 +36,9 @@ void WorldOfXeenEngine::showIntro() {
 	if (gDebugLevel == 0)
 		return;
 
-	showDarkSideTitle(*this);
+	bool completed = showDarkSideTitle(*this);
+	if (!_seenDarkSideIntro && completed)
+		showDarkSideIntro(*this);
 }
 
 } // End of namespace Xeen
diff --git a/engines/xeen/worldofxeen/worldofxeen_game.h b/engines/xeen/worldofxeen/worldofxeen_game.h
index f81f566..97a8754 100644
--- a/engines/xeen/worldofxeen/worldofxeen_game.h
+++ b/engines/xeen/worldofxeen/worldofxeen_game.h
@@ -36,6 +36,8 @@ class WorldOfXeenEngine: public XeenEngine {
 protected:
 	virtual void showIntro();
 public:
+	bool _seenDarkSideIntro;
+public:
 	WorldOfXeenEngine(OSystem *syst, const XeenGameDescription *gameDesc);
 	virtual ~WorldOfXeenEngine() {}
 };


Commit: d8c28d15ae553d047b7e571f98727fa79ee143f3
    https://github.com/scummvm/scummvm/commit/d8c28d15ae553d047b7e571f98727fa79ee143f3
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-11-29T23:34:34-05:00

Commit Message:
XEEN: Create stub files for other Clouds/DarkSide cutscenes

Changed paths:
  A engines/xeen/worldofxeen/clouds_ending.cpp
  A engines/xeen/worldofxeen/clouds_ending.h
  A engines/xeen/worldofxeen/clouds_intro.cpp
  A engines/xeen/worldofxeen/clouds_intro.h
  A engines/xeen/worldofxeen/darkside_ending.cpp
  A engines/xeen/worldofxeen/darkside_ending.h
    engines/xeen/module.mk
    engines/xeen/worldofxeen/darkside_intro.cpp



diff --git a/engines/xeen/module.mk b/engines/xeen/module.mk
index a1e62e1..58a2f1a 100644
--- a/engines/xeen/module.mk
+++ b/engines/xeen/module.mk
@@ -1,6 +1,9 @@
 MODULE := engines/xeen
 
 MODULE_OBJS := \
+	worldofxeen/clouds_ending.o \
+	worldofxeen/clouds_intro.o \
+	worldofxeen/darkside_ending.o \
 	worldofxeen/darkside_intro.o \
 	worldofxeen/worldofxeen_game.o \
 	character.o \
diff --git a/engines/xeen/worldofxeen/clouds_ending.cpp b/engines/xeen/worldofxeen/clouds_ending.cpp
new file mode 100644
index 0000000..75c8755
--- /dev/null
+++ b/engines/xeen/worldofxeen/clouds_ending.cpp
@@ -0,0 +1,36 @@
+/* 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 "xeen/worldofxeen/clouds_ending.h"
+#include "xeen/sound.h"
+
+namespace Xeen {
+
+bool showCloudsEnding(XeenEngine &vm) {
+	EventsManager &events = *vm._events;
+	Screen &screen = *vm._screen;
+	SoundManager &sound = *vm._sound;
+
+	return true;
+}
+
+} // End of namespace Xeen
diff --git a/engines/xeen/worldofxeen/clouds_ending.h b/engines/xeen/worldofxeen/clouds_ending.h
new file mode 100644
index 0000000..fc7945f
--- /dev/null
+++ b/engines/xeen/worldofxeen/clouds_ending.h
@@ -0,0 +1,34 @@
+/* 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_CLOUDS_ENDING_H
+#define XEEN_CLOUDS_ENDING_H
+
+#include "xeen/xeen.h"
+
+namespace Xeen {
+
+bool showCloudsEnding(XeenEngine &vm);
+
+} // End of namespace Xeen
+
+#endif /* XEEN_CLOUDS_ENDING_H */
diff --git a/engines/xeen/worldofxeen/clouds_intro.cpp b/engines/xeen/worldofxeen/clouds_intro.cpp
new file mode 100644
index 0000000..1ea6765
--- /dev/null
+++ b/engines/xeen/worldofxeen/clouds_intro.cpp
@@ -0,0 +1,36 @@
+/* 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 "xeen/worldofxeen/clouds_intro.h"
+#include "xeen/sound.h"
+
+namespace Xeen {
+
+bool showCloudsTitle(XeenEngine &vm) {
+	return true;
+}
+
+bool showCloudsIntro(XeenEngine &vm) {
+	return true;
+}
+
+} // End of namespace Xeen
diff --git a/engines/xeen/worldofxeen/clouds_intro.h b/engines/xeen/worldofxeen/clouds_intro.h
new file mode 100644
index 0000000..0bd5633
--- /dev/null
+++ b/engines/xeen/worldofxeen/clouds_intro.h
@@ -0,0 +1,36 @@
+/* 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_CLOUDS_INTRO_H
+#define XEEN_CLOUDS_INTRO_H
+
+#include "xeen/xeen.h"
+
+namespace Xeen {
+
+bool showCloudsTitle(XeenEngine &vm);
+
+bool showCloudsIntro(XeenEngine &vm);
+
+} // End of namespace Xeen
+
+#endif /* XEEN_CLOUDS_INTRO_H */
diff --git a/engines/xeen/worldofxeen/darkside_ending.cpp b/engines/xeen/worldofxeen/darkside_ending.cpp
new file mode 100644
index 0000000..0a8211f
--- /dev/null
+++ b/engines/xeen/worldofxeen/darkside_ending.cpp
@@ -0,0 +1,32 @@
+/* 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 "xeen/worldofxeen/darkside_ending.h"
+#include "xeen/sound.h"
+
+namespace Xeen {
+
+bool showDarkSideEnding(XeenEngine &vm) {
+	return true;
+}
+
+} // End of namespace Xeen
diff --git a/engines/xeen/worldofxeen/darkside_ending.h b/engines/xeen/worldofxeen/darkside_ending.h
new file mode 100644
index 0000000..49dcf2d
--- /dev/null
+++ b/engines/xeen/worldofxeen/darkside_ending.h
@@ -0,0 +1,34 @@
+/* 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_DARKSIDE_ENDING_H
+#define XEEN_DARKSIDE_ENDING_H
+
+#include "xeen/xeen.h"
+
+namespace Xeen {
+
+bool showDarkSideEnding(XeenEngine &vm);
+
+} // End of namespace Xeen
+
+#endif /* XEEN_DARKSIDE_ENDING_H */
diff --git a/engines/xeen/worldofxeen/darkside_intro.cpp b/engines/xeen/worldofxeen/darkside_intro.cpp
index 8148e24..7ea0328 100644
--- a/engines/xeen/worldofxeen/darkside_intro.cpp
+++ b/engines/xeen/worldofxeen/darkside_intro.cpp
@@ -20,7 +20,7 @@
  *
  */
 
-#include "xeen/worldofxeen/worldofxeen_game.h"
+#include "xeen/worldofxeen/darkside_intro.h"
 #include "xeen/sound.h"
 
 namespace Xeen {


Commit: 504cf6ecb688a3f1c65a857bffd527d8b0e6ba63
    https://github.com/scummvm/scummvm/commit/504cf6ecb688a3f1c65a857bffd527d8b0e6ba63
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2016-07-26T19:48:14-04:00

Commit Message:
Merge branch 'master' into xeen

Changed paths:
  A backends/audiocd/audiocd-stream.cpp
  A backends/audiocd/audiocd-stream.h
  A backends/audiocd/linux/linux-audiocd.cpp
  A backends/audiocd/linux/linux-audiocd.h
  A backends/audiocd/macosx/macosx-audiocd.cpp
  A backends/audiocd/macosx/macosx-audiocd.h
  A backends/audiocd/win32/msvc/ntddcdrm.h
  A backends/audiocd/win32/win32-audiocd.cpp
  A backends/audiocd/win32/win32-audiocd.h
  A backends/events/androidsdl/androidsdl-events.cpp
  A backends/events/androidsdl/androidsdl-events.h
  A backends/fs/chroot/chroot-fs-factory.cpp
  A backends/fs/chroot/chroot-fs-factory.h
  A backends/fs/chroot/chroot-fs.cpp
  A backends/fs/chroot/chroot-fs.h
  A backends/graphics/androidsdl/androidsdl-graphics.cpp
  A backends/graphics/androidsdl/androidsdl-graphics.h
  A backends/graphics/opengl/context.cpp
  A backends/graphics/opengl/framebuffer.cpp
  A backends/graphics/opengl/framebuffer.h
  A backends/graphics/opengl/opengl-defs.h
  A backends/graphics/opengl/opengl-func.h
  A backends/graphics/opengl/pipelines/clut8.cpp
  A backends/graphics/opengl/pipelines/clut8.h
  A backends/graphics/opengl/pipelines/fixed.cpp
  A backends/graphics/opengl/pipelines/fixed.h
  A backends/graphics/opengl/pipelines/pipeline.cpp
  A backends/graphics/opengl/pipelines/pipeline.h
  A backends/graphics/opengl/pipelines/shader.cpp
  A backends/graphics/opengl/pipelines/shader.h
  A backends/graphics/opengl/shader.cpp
  A backends/graphics/opengl/shader.h
  A backends/platform/3ds/3ds.mk
  A backends/platform/3ds/README
  A backends/platform/3ds/app/banner.png
  A backends/platform/3ds/app/banner.wav
  A backends/platform/3ds/app/icon.png
  A backends/platform/3ds/app/scummvm.rsf
  A backends/platform/3ds/config.cpp
  A backends/platform/3ds/config.h
  A backends/platform/3ds/gui.cpp
  A backends/platform/3ds/gui.h
  A backends/platform/3ds/main.cpp
  A backends/platform/3ds/module.mk
  A backends/platform/3ds/options-dialog.cpp
  A backends/platform/3ds/options-dialog.h
  A backends/platform/3ds/osystem-audio.cpp
  A backends/platform/3ds/osystem-events.cpp
  A backends/platform/3ds/osystem-graphics.cpp
  A backends/platform/3ds/osystem.cpp
  A backends/platform/3ds/osystem.h
  A backends/platform/3ds/shader.v.pica
  A backends/platform/3ds/sprite.cpp
  A backends/platform/3ds/sprite.h
  A backends/platform/androidsdl/androidsdl-main.cpp
  A backends/platform/androidsdl/androidsdl-sdl.cpp
  A backends/platform/androidsdl/androidsdl-sdl.h
  A backends/platform/androidsdl/androidsdl.mk
  A backends/platform/androidsdl/module.mk
  A backends/platform/dingux/README.GCW0
  A backends/platform/dingux/build.gcw0.sh
  A backends/platform/ios7/README.md
  A backends/platform/ios7/ios7_app_delegate.h
  A backends/platform/ios7/ios7_app_delegate.mm
  A backends/platform/ios7/ios7_common.h
  A backends/platform/ios7/ios7_keyboard.h
  A backends/platform/ios7/ios7_keyboard.mm
  A backends/platform/ios7/ios7_main.mm
  A backends/platform/ios7/ios7_osys_events.cpp
  A backends/platform/ios7/ios7_osys_main.cpp
  A backends/platform/ios7/ios7_osys_main.h
  A backends/platform/ios7/ios7_osys_sound.cpp
  A backends/platform/ios7/ios7_osys_video.mm
  A backends/platform/ios7/ios7_scummvm_view_controller.h
  A backends/platform/ios7/ios7_scummvm_view_controller.mm
  A backends/platform/ios7/ios7_video.h
  A backends/platform/ios7/ios7_video.mm
  A backends/platform/ios7/module.mk
  A backends/platform/sdl/raspberrypi/README.RASPBERRYPI
  A backends/platform/symbian/mmp/scummvm_sherlock.mmp.in
  A backends/taskbar/macosx/dockplugin/dockplugin.m
  A backends/updates/win32/win32-updates.cpp
  A backends/updates/win32/win32-updates.h
  A common/updates.cpp
  A devtools/create_access/amazon_resources.cpp
  A devtools/create_access/amazon_resources.h
  A devtools/create_access/create_access_dat.cpp
  A devtools/create_access/create_access_dat.h
  A devtools/create_access/martian_resources.cpp
  A devtools/create_access/martian_resources.h
  A devtools/create_access/module.mk
  A devtools/create_classicmacfonts.sh
  A devtools/create_project/cmake.cpp
  A devtools/create_project/cmake.h
  A devtools/create_project/cmake/CMakeLists.txt
  A devtools/encode-macbinary.sh
  A dists/amiga/RM2AG.rx
  A dists/amiga/convertRM.sed
  A dists/android/res/drawable-xhdpi/leanback_icon.png
  A dists/androidsdl/scummvm/AndroidAppSettings.cfg
  A dists/androidsdl/scummvm/AndroidAppSettings.cfg.in
  A dists/androidsdl/scummvm/AndroidBuild.sh
  A dists/androidsdl/scummvm/AndroidData/logo.png
  A dists/androidsdl/scummvm/DataBuild.sh
  A dists/androidsdl/scummvm/banner.png
  A dists/androidsdl/scummvm/icon.png
  A dists/engine-data/access.dat
  A dists/engine-data/testbed-audiocd-files/TESTBED
  A dists/ios7/Images.xcassets/AppIcon.appiconset/Contents.json
  A dists/ios7/Images.xcassets/AppIcon.appiconset/icon4-29.png
  A dists/ios7/Images.xcassets/AppIcon.appiconset/icon4-29 at 2x.png
  A dists/ios7/Images.xcassets/AppIcon.appiconset/icon4-29 at 3x.png
  A dists/ios7/Images.xcassets/AppIcon.appiconset/icon4-40.png
  A dists/ios7/Images.xcassets/AppIcon.appiconset/icon4-40 at 2x.png
  A dists/ios7/Images.xcassets/AppIcon.appiconset/icon4-40 at 3x.png
  A dists/ios7/Images.xcassets/AppIcon.appiconset/icon4-60 at 2x.png
  A dists/ios7/Images.xcassets/AppIcon.appiconset/icon4-60 at 3x.png
  A dists/ios7/Images.xcassets/AppIcon.appiconset/icon4-76.png
  A dists/ios7/Images.xcassets/AppIcon.appiconset/icon4-76 at 2x.png
  A dists/ios7/Images.xcassets/AppIcon.appiconset/icon4-83.5 at 2x.png
  A dists/ios7/Images.xcassets/Contents.json
  A dists/ios7/Images.xcassets/LaunchImage.launchimage/Contents.json
  A dists/ios7/Images.xcassets/LaunchImage.launchimage/ScummVM-splash-1024x768.png
  A dists/ios7/Images.xcassets/LaunchImage.launchimage/ScummVM-splash-1242x2208.png
  A dists/ios7/Images.xcassets/LaunchImage.launchimage/ScummVM-splash-1536x2048.png
  A dists/ios7/Images.xcassets/LaunchImage.launchimage/ScummVM-splash-2048x1536.png
  A dists/ios7/Images.xcassets/LaunchImage.launchimage/ScummVM-splash-2208x1242.png
  A dists/ios7/Images.xcassets/LaunchImage.launchimage/ScummVM-splash-640x1136-1.png
  A dists/ios7/Images.xcassets/LaunchImage.launchimage/ScummVM-splash-750x1334.png
  A dists/ios7/Images.xcassets/LaunchImage.launchimage/ScummVM-splash-768x1024.png
  A dists/ios7/Info.plist
  A dists/ios7/Info.plist.in
  A dists/macosx/dockplugin/Info.plist
  A dists/macosx/dockplugin/Info.plist.in
  A dists/macosx/dsa_pub.pem
  A dists/macosx/scummvm_appcast.xml
  A dists/scummvm_logo.bmp
  A engines/access/video/movie_decoder.cpp
  A engines/access/video/movie_decoder.h
  A engines/adl/POTFILES
  A engines/adl/adl.cpp
  A engines/adl/adl.h
  A engines/adl/adl_v2.cpp
  A engines/adl/adl_v2.h
  A engines/adl/adl_v3.cpp
  A engines/adl/adl_v3.h
  A engines/adl/configure.engine
  A engines/adl/console.cpp
  A engines/adl/console.h
  A engines/adl/detection.cpp
  A engines/adl/detection.h
  A engines/adl/disk.cpp
  A engines/adl/disk.h
  A engines/adl/display.cpp
  A engines/adl/display.h
  A engines/adl/graphics.cpp
  A engines/adl/graphics.h
  A engines/adl/graphics_v1.cpp
  A engines/adl/graphics_v2.cpp
  A engines/adl/hires1.cpp
  A engines/adl/hires1.h
  A engines/adl/hires2.cpp
  A engines/adl/hires2.h
  A engines/adl/hires6.cpp
  A engines/adl/hires6.h
  A engines/adl/module.mk
  A engines/adl/speaker.cpp
  A engines/adl/speaker.h
  A engines/agi/appleIIgs_timedelay_overwrite.h
  A engines/agi/font.cpp
  A engines/agi/inv.h
  A engines/agi/mouse_cursor.h
  A engines/agi/palette.h
  A engines/agi/systemui.cpp
  A engines/agi/systemui.h
  A engines/agi/text.h
  A engines/agi/words.h
  A engines/avalanche/POTFILES
  A engines/cine/POTFILES
  A engines/gnap/character.cpp
  A engines/gnap/character.h
  A engines/gnap/configure.engine
  A engines/gnap/datarchive.cpp
  A engines/gnap/datarchive.h
  A engines/gnap/debugger.cpp
  A engines/gnap/debugger.h
  A engines/gnap/detection.cpp
  A engines/gnap/fontdata.h
  A engines/gnap/gamesys.cpp
  A engines/gnap/gamesys.h
  A engines/gnap/gnap.cpp
  A engines/gnap/gnap.h
  A engines/gnap/grid.cpp
  A engines/gnap/menu.cpp
  A engines/gnap/module.mk
  A engines/gnap/music.cpp
  A engines/gnap/music.h
  A engines/gnap/resource.cpp
  A engines/gnap/resource.h
  A engines/gnap/scenes/arcade.cpp
  A engines/gnap/scenes/arcade.h
  A engines/gnap/scenes/group0.cpp
  A engines/gnap/scenes/group0.h
  A engines/gnap/scenes/group1.cpp
  A engines/gnap/scenes/group1.h
  A engines/gnap/scenes/group2.cpp
  A engines/gnap/scenes/group2.h
  A engines/gnap/scenes/group3.cpp
  A engines/gnap/scenes/group3.h
  A engines/gnap/scenes/group4.cpp
  A engines/gnap/scenes/group4.h
  A engines/gnap/scenes/group5.cpp
  A engines/gnap/scenes/group5.h
  A engines/gnap/scenes/groupcs.cpp
  A engines/gnap/scenes/groupcs.h
  A engines/gnap/scenes/intro.cpp
  A engines/gnap/scenes/intro.h
  A engines/gnap/scenes/scenecore.cpp
  A engines/gnap/scenes/scenecore.h
  A engines/gnap/sound.cpp
  A engines/gnap/sound.h
  A engines/hugo/POTFILES
  A engines/lab/anim.cpp
  A engines/lab/anim.h
  A engines/lab/configure.engine
  A engines/lab/console.cpp
  A engines/lab/console.h
  A engines/lab/detection.cpp
  A engines/lab/dispman.cpp
  A engines/lab/dispman.h
  A engines/lab/engine.cpp
  A engines/lab/eventman.cpp
  A engines/lab/eventman.h
  A engines/lab/image.cpp
  A engines/lab/image.h
  A engines/lab/interface.cpp
  A engines/lab/interface.h
  A engines/lab/intro.cpp
  A engines/lab/intro.h
  A engines/lab/lab.cpp
  A engines/lab/lab.h
  A engines/lab/labsets.cpp
  A engines/lab/labsets.h
  A engines/lab/map.cpp
  A engines/lab/module.mk
  A engines/lab/music.cpp
  A engines/lab/music.h
  A engines/lab/processroom.cpp
  A engines/lab/processroom.h
  A engines/lab/resource.cpp
  A engines/lab/resource.h
  A engines/lab/savegame.cpp
  A engines/lab/special.cpp
  A engines/lab/speciallocks.cpp
  A engines/lab/speciallocks.h
  A engines/lab/utils.cpp
  A engines/lab/utils.h
  A engines/logo_data.h
  A engines/mads/camera.cpp
  A engines/mads/camera.h
  A engines/mads/conversations.cpp
  A engines/mads/conversations.h
  A engines/mads/dragonsphere/dragonsphere_scenes1.cpp
  A engines/mads/dragonsphere/dragonsphere_scenes1.h
  A engines/mads/dragonsphere/globals_dragonsphere.cpp
  A engines/mads/dragonsphere/globals_dragonsphere.h
  A engines/mads/phantom/phantom_scenes2.cpp
  A engines/mads/phantom/phantom_scenes2.h
  A engines/mads/phantom/phantom_scenes3.cpp
  A engines/mads/phantom/phantom_scenes3.h
  A engines/mads/phantom/phantom_scenes4.cpp
  A engines/mads/phantom/phantom_scenes4.h
  A engines/mads/phantom/phantom_scenes5.cpp
  A engines/mads/phantom/phantom_scenes5.h
  A engines/prince/videoplayer.cpp
  A engines/sci/graphics/celobj32.cpp
  A engines/sci/graphics/celobj32.h
  A engines/sci/graphics/lists32.h
  A engines/sci/graphics/palette32.cpp
  A engines/sci/graphics/palette32.h
  A engines/sci/graphics/plane32.cpp
  A engines/sci/graphics/plane32.h
  A engines/sci/graphics/remap.cpp
  A engines/sci/graphics/remap.h
  A engines/sci/graphics/remap32.cpp
  A engines/sci/graphics/remap32.h
  A engines/sci/graphics/screen_item32.cpp
  A engines/sci/graphics/screen_item32.h
  A engines/sci/graphics/video32.cpp
  A engines/sci/graphics/video32.h
  A engines/sci/sound/audio32.cpp
  A engines/sci/sound/audio32.h
  A engines/sci/sound/decoders/sol.cpp
  A engines/sci/sound/decoders/sol.h
  A engines/sci/sound/sync.cpp
  A engines/sci/sound/sync.h
  A engines/scumm/he/logic/moonbase_logic.cpp
  A engines/scumm/he/moonbase/ai_defenseunit.cpp
  A engines/scumm/he/moonbase/ai_defenseunit.h
  A engines/scumm/he/moonbase/ai_main.cpp
  A engines/scumm/he/moonbase/ai_main.h
  A engines/scumm/he/moonbase/ai_node.cpp
  A engines/scumm/he/moonbase/ai_node.h
  A engines/scumm/he/moonbase/ai_pattern.h
  A engines/scumm/he/moonbase/ai_targetacquisition.cpp
  A engines/scumm/he/moonbase/ai_targetacquisition.h
  A engines/scumm/he/moonbase/ai_traveller.cpp
  A engines/scumm/he/moonbase/ai_traveller.h
  A engines/scumm/he/moonbase/ai_tree.cpp
  A engines/scumm/he/moonbase/ai_tree.h
  A engines/scumm/he/moonbase/ai_types.cpp
  A engines/scumm/he/moonbase/ai_types.h
  A engines/scumm/he/moonbase/ai_weapon.cpp
  A engines/scumm/he/moonbase/ai_weapon.h
  A engines/scumm/he/moonbase/distortion.cpp
  A engines/scumm/he/moonbase/moonbase.cpp
  A engines/scumm/he/moonbase/moonbase.h
  A engines/scumm/he/moonbase/moonbase_fow.cpp
  A engines/sherlock/POTFILES
  A engines/sherlock/scalpel/3do/scalpel_3do_screen.cpp
  A engines/sherlock/scalpel/3do/scalpel_3do_screen.h
  A engines/sherlock/tattoo/tattoo_screen.cpp
  A engines/sherlock/tattoo/tattoo_screen.h
  A engines/sword25/POTFILES
  A engines/toon/POTFILES
  A engines/tsage/screen.cpp
  A engines/tsage/screen.h
  A engines/voyeur/screen.cpp
  A engines/voyeur/screen.h
  A engines/wage/combat.cpp
  A engines/wage/configure.engine
  A engines/wage/debugger.cpp
  A engines/wage/debugger.h
  A engines/wage/design.cpp
  A engines/wage/design.h
  A engines/wage/detection.cpp
  A engines/wage/detection_tables.h
  A engines/wage/dialog.cpp
  A engines/wage/dialog.h
  A engines/wage/entities.cpp
  A engines/wage/entities.h
  A engines/wage/gui-console.cpp
  A engines/wage/gui.cpp
  A engines/wage/gui.h
  A engines/wage/macmenu.cpp
  A engines/wage/macmenu.h
  A engines/wage/macwindow.cpp
  A engines/wage/macwindow.h
  A engines/wage/macwindowmanager.cpp
  A engines/wage/macwindowmanager.h
  A engines/wage/module.mk
  A engines/wage/randomhat.cpp
  A engines/wage/randomhat.h
  A engines/wage/script.cpp
  A engines/wage/script.h
  A engines/wage/sound.cpp
  A engines/wage/sound.h
  A engines/wage/util.cpp
  A engines/wage/wage.cpp
  A engines/wage/wage.h
  A engines/wage/world.cpp
  A engines/wage/world.h
  A engines/wintermute/base/scriptables/debuggable/debuggable_script.cpp
  A engines/wintermute/base/scriptables/debuggable/debuggable_script.h
  A engines/wintermute/base/scriptables/debuggable/debuggable_script_engine.cpp
  A engines/wintermute/base/scriptables/debuggable/debuggable_script_engine.h
  A engines/wintermute/debugger/breakpoint.cpp
  A engines/wintermute/debugger/breakpoint.h
  A engines/wintermute/debugger/debugger_controller.cpp
  A engines/wintermute/debugger/debugger_controller.h
  A engines/wintermute/debugger/error.cpp
  A engines/wintermute/debugger/error.h
  A engines/wintermute/debugger/listing.cpp
  A engines/wintermute/debugger/listing.h
  A engines/wintermute/debugger/listing_provider.h
  A engines/wintermute/debugger/listing_providers/basic_source_listing_provider.cpp
  A engines/wintermute/debugger/listing_providers/basic_source_listing_provider.h
  A engines/wintermute/debugger/listing_providers/blank_listing.cpp
  A engines/wintermute/debugger/listing_providers/blank_listing.h
  A engines/wintermute/debugger/listing_providers/blank_listing_provider.cpp
  A engines/wintermute/debugger/listing_providers/blank_listing_provider.h
  A engines/wintermute/debugger/listing_providers/cached_source_listing_provider.cpp
  A engines/wintermute/debugger/listing_providers/cached_source_listing_provider.h
  A engines/wintermute/debugger/listing_providers/source_listing.cpp
  A engines/wintermute/debugger/listing_providers/source_listing.h
  A engines/wintermute/debugger/listing_providers/source_listing_provider.h
  A engines/wintermute/debugger/script_monitor.cpp
  A engines/wintermute/debugger/script_monitor.h
  A engines/wintermute/debugger/watch.cpp
  A engines/wintermute/debugger/watch.h
  A engines/wintermute/debugger/watch_instance.cpp
  A engines/wintermute/debugger/watch_instance.h
  A graphics/managed_surface.cpp
  A graphics/managed_surface.h
  A graphics/nine_patch.cpp
  A graphics/nine_patch.h
  A graphics/pixelformat.cpp
  A graphics/screen.cpp
  A graphics/screen.h
  A gui/filebrowser-dialog.cpp
  A gui/filebrowser-dialog.h
  A gui/updates-dialog.cpp
  A gui/updates-dialog.h
  A gui/widgets/scrollcontainer.cpp
  A gui/widgets/scrollcontainer.h
  A image/codecs/msrle4.cpp
  A image/codecs/msrle4.h
  A po/da_DK.po
  A po/sv_SE.po
  A po/zh-Latn_CN.po
  R backends/graphics/opengl/extensions.cpp
  R backends/graphics/opengl/extensions.h
  R backends/mixer/sdl13/sdl13-mixer.cpp
  R backends/mixer/sdl13/sdl13-mixer.h
  R dists/macosx/scummvm_osx_appcast.xml
  R engines/sci/graphics/paint.cpp
  R engines/sci/graphics/paint.h
  R engines/scumm/he/logic/moonbase.cpp
  R engines/sherlock/decompress.cpp
  R engines/voyeur/graphics.cpp
  R engines/voyeur/graphics.h
  R po/da_DA.po
  R po/se_SE.po
    .gitignore
    AUTHORS
    COPYRIGHT
    Makefile.common
    NEWS
    README
    audio/adlib.cpp
    audio/decoders/3do.cpp
    audio/decoders/3do.h
    audio/decoders/adpcm.cpp
    audio/decoders/adpcm.h
    audio/decoders/adpcm_intern.h
    audio/decoders/aiff.cpp
    audio/decoders/vorbis.h
    audio/decoders/wave.cpp
    audio/decoders/wave.h
    audio/midiparser_smf.cpp
    audio/midiparser_xmidi.cpp
    audio/miles_adlib.cpp
    audio/mods/maxtrax.cpp
    audio/mods/protracker.cpp
    audio/rate.cpp
    audio/rate_arm.cpp
    audio/rate_arm_asm.s
    audio/softsynth/fluidsynth.cpp
    audio/softsynth/fmtowns_pc98/towns_audio.cpp
    audio/softsynth/fmtowns_pc98/towns_audio.h
    audio/softsynth/fmtowns_pc98/towns_euphony.cpp
    audio/softsynth/fmtowns_pc98/towns_euphony.h
    audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.cpp
    audio/softsynth/mt32.cpp
    audio/softsynth/mt32/ROMInfo.cpp
    audio/softsynth/opl/mame.cpp
    backends/audiocd/audiocd.h
    backends/audiocd/default/default-audiocd.cpp
    backends/audiocd/default/default-audiocd.h
    backends/audiocd/sdl/sdl-audiocd.cpp
    backends/audiocd/sdl/sdl-audiocd.h
    backends/events/dinguxsdl/dinguxsdl-events.cpp
    backends/events/ps3sdl/ps3sdl-events.cpp
    backends/events/sdl/sdl-events.cpp
    backends/events/sdl/sdl-events.h
    backends/fs/abstract-fs.h
    backends/fs/posix/posix-fs.cpp
    backends/fs/posix/posix-fs.h
    backends/graphics/dinguxsdl/dinguxsdl-graphics.cpp
    backends/graphics/opengl/debug.cpp
    backends/graphics/opengl/debug.h
    backends/graphics/opengl/opengl-graphics.cpp
    backends/graphics/opengl/opengl-graphics.h
    backends/graphics/opengl/opengl-sys.h
    backends/graphics/opengl/texture.cpp
    backends/graphics/opengl/texture.h
    backends/graphics/openglsdl/openglsdl-graphics.cpp
    backends/graphics/openglsdl/openglsdl-graphics.h
    backends/graphics/surfacesdl/surfacesdl-graphics.cpp
    backends/graphics/surfacesdl/surfacesdl-graphics.h
    backends/midi/timidity.cpp
    backends/midi/windows.cpp
    backends/mixer/sdl/sdl-mixer.cpp
    backends/module.mk
    backends/platform/android/android.mk
    backends/platform/android/events.cpp
    backends/platform/android/gfx.cpp
    backends/platform/android/org/scummvm/scummvm/ScummVMEvents.java
    backends/platform/dc/dc.h
    backends/platform/dc/dcmain.cpp
    backends/platform/dc/vmsave.cpp
    backends/platform/dingux/dingux.mk
    backends/platform/ds/arm9/source/osystem_ds.cpp
    backends/platform/ds/arm9/source/osystem_ds.h
    backends/platform/iphone/iphone_keyboard.mm
    backends/platform/iphone/iphone_main.mm
    backends/platform/iphone/iphone_video.h
    backends/platform/iphone/iphone_video.mm
    backends/platform/iphone/osys_events.cpp
    backends/platform/iphone/osys_main.cpp
    backends/platform/iphone/osys_main.h
    backends/platform/iphone/osys_sound.cpp
    backends/platform/iphone/osys_video.mm
    backends/platform/maemo/debian/changelog
    backends/platform/maemo/debian/rules
    backends/platform/maemo/maemo.cpp
    backends/platform/psp/README.PSP
    backends/platform/sdl/amigaos/amigaos-main.cpp
    backends/platform/sdl/amigaos/amigaos.mk
    backends/platform/sdl/macosx/appmenu_osx.mm
    backends/platform/sdl/macosx/macosx.cpp
    backends/platform/sdl/macosx/macosx.h
    backends/platform/sdl/posix/posix-main.cpp
    backends/platform/sdl/posix/posix.cpp
    backends/platform/sdl/posix/posix.h
    backends/platform/sdl/ps3/ps3.cpp
    backends/platform/sdl/sdl-sys.h
    backends/platform/sdl/sdl.cpp
    backends/platform/sdl/sdl.h
    backends/platform/sdl/win32/win32-main.cpp
    backends/platform/sdl/win32/win32.cpp
    backends/platform/sdl/win32/win32.h
    backends/platform/symbian/AdaptAllMMPs.pl
    backends/platform/symbian/BuildPackageUpload_LocalSettings.pl
    backends/platform/symbian/README
    backends/platform/symbian/S60/ScummVM_S60.mmp.in
    backends/platform/symbian/S60/ScummVM_S60_App.mmp
    backends/platform/symbian/S60v3/ScummVM_A0000658_S60v3.mmp.in
    backends/platform/symbian/S60v3/ScummVM_S60v3.mmp.in
    backends/platform/symbian/S80/ScummVM_S80.mmp.in
    backends/platform/symbian/S80/ScummVM_S80_App.mmp
    backends/platform/symbian/S90/Scummvm_S90.mmp.in
    backends/platform/symbian/S90/Scummvm_S90_App.mmp
    backends/platform/symbian/UIQ2/ScummVM.rss
    backends/platform/symbian/UIQ3/ScummVM.rss
    backends/platform/symbian/UIQ3/ScummVM_A0000658.rss
    backends/platform/symbian/UIQ3/ScummVM_A0000658_UIQ3.mmp.in
    backends/platform/symbian/UIQ3/ScummVM_UIQ3.mmp.in
    backends/platform/symbian/UIQ3/scummvm_A0000658_loc.rss
    backends/platform/symbian/help/ScummVM.rtf
    backends/platform/symbian/help/build_help.mk
    backends/platform/symbian/mmp/config.mmh
    backends/platform/symbian/mmp/scummvm_access.mmp.in
    backends/platform/symbian/mmp/scummvm_agi.mmp.in
    backends/platform/symbian/mmp/scummvm_agos.mmp.in
    backends/platform/symbian/mmp/scummvm_avalanche.mmp.in
    backends/platform/symbian/mmp/scummvm_base.mmp.in
    backends/platform/symbian/mmp/scummvm_bbvs.mmp.in
    backends/platform/symbian/mmp/scummvm_cge.mmp.in
    backends/platform/symbian/mmp/scummvm_cge2.mmp.in
    backends/platform/symbian/mmp/scummvm_cine.mmp.in
    backends/platform/symbian/mmp/scummvm_composer.mmp.in
    backends/platform/symbian/mmp/scummvm_cruise.mmp.in
    backends/platform/symbian/mmp/scummvm_draci.mmp.in
    backends/platform/symbian/mmp/scummvm_drascula.mmp.in
    backends/platform/symbian/mmp/scummvm_dreamweb.mmp.in
    backends/platform/symbian/mmp/scummvm_fullpipe.mmp.in
    backends/platform/symbian/mmp/scummvm_gob.mmp.in
    backends/platform/symbian/mmp/scummvm_groovie.mmp.in
    backends/platform/symbian/mmp/scummvm_hopkins.mmp.in
    backends/platform/symbian/mmp/scummvm_hugo.mmp.in
    backends/platform/symbian/mmp/scummvm_kyra.mmp.in
    backends/platform/symbian/mmp/scummvm_lastexpress.mmp.in
    backends/platform/symbian/mmp/scummvm_lure.mmp.in
    backends/platform/symbian/mmp/scummvm_m4.mmp.in
    backends/platform/symbian/mmp/scummvm_made.mmp.in
    backends/platform/symbian/mmp/scummvm_mads.mmp.in
    backends/platform/symbian/mmp/scummvm_mohawk.mmp.in
    backends/platform/symbian/mmp/scummvm_mortevielle.mmp.in
    backends/platform/symbian/mmp/scummvm_neverhood.mmp.in
    backends/platform/symbian/mmp/scummvm_parallaction.mmp.in
    backends/platform/symbian/mmp/scummvm_pegasus.mmp.in
    backends/platform/symbian/mmp/scummvm_prince.mmp.in
    backends/platform/symbian/mmp/scummvm_queen.mmp.in
    backends/platform/symbian/mmp/scummvm_saga.mmp.in
    backends/platform/symbian/mmp/scummvm_sci.mmp.in
    backends/platform/symbian/mmp/scummvm_scumm.mmp.in
    backends/platform/symbian/mmp/scummvm_sky.mmp.in
    backends/platform/symbian/mmp/scummvm_sword1.mmp.in
    backends/platform/symbian/mmp/scummvm_sword2.mmp.in
    backends/platform/symbian/mmp/scummvm_sword25.mmp.in
    backends/platform/symbian/mmp/scummvm_teenagent.mmp.in
    backends/platform/symbian/mmp/scummvm_testbed.mmp.in
    backends/platform/symbian/mmp/scummvm_tinsel.mmp.in
    backends/platform/symbian/mmp/scummvm_toltecs.mmp.in
    backends/platform/symbian/mmp/scummvm_tony.mmp.in
    backends/platform/symbian/mmp/scummvm_toon.mmp.in
    backends/platform/symbian/mmp/scummvm_touche.mmp.in
    backends/platform/symbian/mmp/scummvm_tsage.mmp.in
    backends/platform/symbian/mmp/scummvm_tucker.mmp.in
    backends/platform/symbian/mmp/scummvm_voyeur.mmp.in
    backends/platform/symbian/mmp/scummvm_wintermute.mmp.in
    backends/platform/symbian/mmp/scummvm_zvision.mmp.in
    backends/platform/symbian/res/ScummVmAif.rss
    backends/platform/symbian/res/scummvm.rss
    backends/platform/symbian/res/scummvm_A0000658.rss
    backends/platform/symbian/src/ScummVm.hrh
    backends/platform/symbian/src/portdefs.h
    backends/platform/tizen/graphics.cpp
    backends/platform/tizen/graphics.h
    backends/platform/tizen/system.cpp
    backends/platform/wince/portdefs.h
    backends/platform/wince/wince-sdl.cpp
    backends/plugins/win32/win32-provider.cpp
    backends/saves/default/default-saves.cpp
    backends/saves/default/default-saves.h
    backends/saves/posix/posix-saves.cpp
    backends/taskbar/macosx/macosx-taskbar.h
    backends/taskbar/macosx/macosx-taskbar.mm
    backends/taskbar/win32/win32-taskbar.cpp
    backends/taskbar/win32/win32-taskbar.h
    backends/updates/macosx/macosx-updates.h
    backends/updates/macosx/macosx-updates.mm
    base/commandLine.cpp
    base/internal_version.h
    base/main.cpp
    base/version.cpp
    common/algorithm.h
    common/archive.cpp
    common/array.h
    common/dcl.cpp
    common/dcl.h
    common/fs.h
    common/gui_options.cpp
    common/gui_options.h
    common/macresman.cpp
    common/macresman.h
    common/memstream.h
    common/module.mk
    common/platform.cpp
    common/platform.h
    common/rational.h
    common/recorderfile.cpp
    common/rect.h
    common/rendermode.cpp
    common/rendermode.h
    common/savefile.h
    common/scummsys.h
    common/str.cpp
    common/str.h
    common/taskbar.h
    common/updates.h
    common/xmlparser.cpp
    config.guess
    config.sub
    configure
    devtools/convbdf.cpp
    devtools/create_kyradat/create_kyradat.cpp
    devtools/create_kyradat/create_kyradat.h
    devtools/create_kyradat/games.cpp
    devtools/create_kyradat/resources.cpp
    devtools/create_kyradat/resources/lok_dos.h
    devtools/create_kyradat/resources/lok_dos_cd.h
    devtools/create_kyradat/resources/lok_dos_oldfloppy.h
    devtools/create_kyradat/resources/lok_pc98_japanese.h
    devtools/create_project/codeblocks.cpp
    devtools/create_project/codeblocks.h
    devtools/create_project/create_project.cpp
    devtools/create_project/create_project.h
    devtools/create_project/module.mk
    devtools/create_project/msbuild.cpp
    devtools/create_project/msvc.cpp
    devtools/create_project/msvc.h
    devtools/create_project/msvc10/create_project.vcxproj
    devtools/create_project/msvc11/create_project.vcxproj
    devtools/create_project/msvc12/create_project.vcxproj
    devtools/create_project/msvc14/create_project.vcxproj
    devtools/create_project/msvc9/create_project.vcproj
    devtools/create_project/scripts/postbuild.cmd
    devtools/create_project/scripts/prebuild.cmd
    devtools/create_project/xcode.cpp
    devtools/create_project/xcode.h
    devtools/create_project/xcode/create_project.xcodeproj/project.pbxproj
    devtools/create_translations/create_translations.h
    devtools/credits.pl
    devtools/dist-scummvm.sh
    devtools/scumm-md5.txt
    devtools/skycpt/COMPACT.TXT
    devtools/skycpt/README
    devtools/update-version.pl
    dists/android/AndroidManifest.xml
    dists/android/AndroidManifest.xml.in
    dists/debian/copyright
    dists/engine-data/README
    dists/engine-data/kyra.dat
    dists/engine-data/sky.cpt
    dists/gcw0/default.gcw0.desktop
    dists/gcw0/scummvm.sh
    dists/gph/README-GPH
    dists/gph/scummvm.ini
    dists/iphone/Info.plist
    dists/irix/scummvm.spec
    dists/macosx/DS_Store
    dists/macosx/Info.plist
    dists/macosx/Info.plist.in
    dists/msvc14/create_msvc14.bat
    dists/openpandora/PXML.xml
    dists/openpandora/README-OPENPANDORA
    dists/openpandora/README-PND.txt
    dists/openpandora/index.html
    dists/openpandora/pnd_make.sh
    dists/ps3/readme-ps3.md
    dists/redhat/scummvm-tools.spec
    dists/redhat/scummvm.spec
    dists/redhat/scummvm.spec.in
    dists/samsungtv/README-SamsungTV
    dists/scummvm.rc
    dists/scummvm.rc.in
    dists/slackware/scummvm.SlackBuild
    dists/wii/meta.xml
    dists/win32/ScummVM.iss
    dists/win32/migration.bat
    dists/win32/scummvm.nsi
    dists/win32/scummvm.nsi.in
    doc/cz/PrectiMe
    doc/de/Liesmich
    doc/de/Neues
    engines/access/access.cpp
    engines/access/access.h
    engines/access/amazon/amazon_game.cpp
    engines/access/amazon/amazon_logic.cpp
    engines/access/amazon/amazon_resources.cpp
    engines/access/amazon/amazon_resources.h
    engines/access/amazon/amazon_room.cpp
    engines/access/amazon/amazon_scripts.cpp
    engines/access/animation.cpp
    engines/access/asurface.cpp
    engines/access/asurface.h
    engines/access/bubble_box.cpp
    engines/access/char.cpp
    engines/access/configure.engine
    engines/access/debugger.cpp
    engines/access/debugger.h
    engines/access/detection.cpp
    engines/access/detection_tables.h
    engines/access/events.cpp
    engines/access/events.h
    engines/access/files.cpp
    engines/access/files.h
    engines/access/font.cpp
    engines/access/font.h
    engines/access/inventory.cpp
    engines/access/martian/martian_game.cpp
    engines/access/martian/martian_resources.cpp
    engines/access/martian/martian_resources.h
    engines/access/martian/martian_room.cpp
    engines/access/module.mk
    engines/access/resources.cpp
    engines/access/resources.h
    engines/access/room.cpp
    engines/access/screen.cpp
    engines/access/screen.h
    engines/access/scripts.cpp
    engines/access/scripts.h
    engines/access/sound.cpp
    engines/access/sound.h
    engines/access/video.cpp
    engines/access/video.h
    engines/advancedDetector.cpp
    engines/advancedDetector.h
    engines/agi/agi.cpp
    engines/agi/agi.h
    engines/agi/checks.cpp
    engines/agi/console.cpp
    engines/agi/console.h
    engines/agi/cycle.cpp
    engines/agi/detection.cpp
    engines/agi/detection_tables.h
    engines/agi/font.h
    engines/agi/global.cpp
    engines/agi/graphics.cpp
    engines/agi/graphics.h
    engines/agi/id.cpp
    engines/agi/inv.cpp
    engines/agi/keyboard.cpp
    engines/agi/keyboard.h
    engines/agi/loader_v1.cpp
    engines/agi/loader_v2.cpp
    engines/agi/loader_v3.cpp
    engines/agi/logic.cpp
    engines/agi/logic.h
    engines/agi/lzw.cpp
    engines/agi/menu.cpp
    engines/agi/menu.h
    engines/agi/module.mk
    engines/agi/motion.cpp
    engines/agi/objects.cpp
    engines/agi/op_cmd.cpp
    engines/agi/op_dbg.cpp
    engines/agi/op_test.cpp
    engines/agi/opcodes.cpp
    engines/agi/opcodes.h
    engines/agi/picture.cpp
    engines/agi/picture.h
    engines/agi/preagi.cpp
    engines/agi/preagi.h
    engines/agi/preagi_mickey.cpp
    engines/agi/preagi_mickey.h
    engines/agi/preagi_troll.cpp
    engines/agi/preagi_troll.h
    engines/agi/preagi_winnie.cpp
    engines/agi/preagi_winnie.h
    engines/agi/saveload.cpp
    engines/agi/sound.cpp
    engines/agi/sound.h
    engines/agi/sound_2gs.cpp
    engines/agi/sound_2gs.h
    engines/agi/sound_midi.cpp
    engines/agi/sound_pcjr.cpp
    engines/agi/sound_pcjr.h
    engines/agi/sound_sarien.cpp
    engines/agi/sound_sarien.h
    engines/agi/sprite.cpp
    engines/agi/sprite.h
    engines/agi/text.cpp
    engines/agi/view.cpp
    engines/agi/view.h
    engines/agi/wagparser.cpp
    engines/agi/words.cpp
    engines/agos/agos.cpp
    engines/agos/agos.h
    engines/agos/animation.cpp
    engines/agos/configure.engine
    engines/agos/cursor.cpp
    engines/agos/debugger.cpp
    engines/agos/detection.cpp
    engines/agos/detection_tables.h
    engines/agos/drivers/accolade/adlib.cpp
    engines/agos/drivers/accolade/driverfile.cpp
    engines/agos/drivers/accolade/mt32.cpp
    engines/agos/event.cpp
    engines/agos/feeble.cpp
    engines/agos/icons.cpp
    engines/agos/input.cpp
    engines/agos/res.cpp
    engines/agos/res_snd.cpp
    engines/agos/saveload.cpp
    engines/agos/script.cpp
    engines/agos/script_e1.cpp
    engines/agos/script_e2.cpp
    engines/agos/script_ff.cpp
    engines/agos/script_pn.cpp
    engines/agos/script_s1.cpp
    engines/agos/script_s2.cpp
    engines/agos/script_ww.cpp
    engines/agos/sound.cpp
    engines/agos/string.cpp
    engines/agos/string_pn.cpp
    engines/agos/subroutine.cpp
    engines/agos/vga.cpp
    engines/agos/vga_e2.cpp
    engines/agos/vga_ff.cpp
    engines/agos/vga_s1.cpp
    engines/agos/vga_s2.cpp
    engines/avalanche/animation.cpp
    engines/avalanche/avalanche.cpp
    engines/avalanche/clock.cpp
    engines/avalanche/configure.engine
    engines/avalanche/detection.cpp
    engines/avalanche/dialogs.cpp
    engines/avalanche/ghostroom.cpp
    engines/avalanche/graphics.cpp
    engines/avalanche/highscore.cpp
    engines/avalanche/mainmenu.cpp
    engines/avalanche/nim.cpp
    engines/avalanche/parser.cpp
    engines/avalanche/shootemup.cpp
    engines/avalanche/sound.cpp
    engines/avalanche/sound.h
    engines/bbvs/bbvs.cpp
    engines/bbvs/bbvs.h
    engines/bbvs/configure.engine
    engines/bbvs/detection.cpp
    engines/bbvs/dialogs.cpp
    engines/bbvs/dialogs.h
    engines/bbvs/graphics.cpp
    engines/bbvs/minigames/bbairguitar.cpp
    engines/bbvs/minigames/bbtennis.cpp
    engines/bbvs/saveload.cpp
    engines/bbvs/sound.cpp
    engines/bbvs/sound.h
    engines/bbvs/spritemodule.cpp
    engines/bbvs/videoplayer.cpp
    engines/bbvs/walk.cpp
    engines/cge/POTFILES
    engines/cge/cge.h
    engines/cge/detection.cpp
    engines/cge/events.cpp
    engines/cge/sound.cpp
    engines/cge/sound.h
    engines/cge2/POTFILES
    engines/cge2/cge2.h
    engines/cge2/detection.cpp
    engines/cge2/events.cpp
    engines/cge2/saveload.cpp
    engines/cge2/sound.cpp
    engines/cge2/sound.h
    engines/cge2/vga13h.cpp
    engines/cine/anim.cpp
    engines/cine/cine.cpp
    engines/cine/cine.h
    engines/cine/detection.cpp
    engines/cine/detection_tables.h
    engines/cine/main_loop.cpp
    engines/cine/saveload.cpp
    engines/cine/script_fw.cpp
    engines/cine/sound.cpp
    engines/cine/various.cpp
    engines/composer/composer.cpp
    engines/composer/composer.h
    engines/composer/configure.engine
    engines/composer/detection.cpp
    engines/cruise/cell.cpp
    engines/cruise/ctp.cpp
    engines/cruise/dataLoader.cpp
    engines/cruise/detection.cpp
    engines/cruise/sound.cpp
    engines/dialogs.cpp
    engines/draci/detection.cpp
    engines/draci/draci.h
    engines/draci/music.cpp
    engines/drascula/actors.cpp
    engines/drascula/animation.cpp
    engines/drascula/detection.cpp
    engines/drascula/drascula.cpp
    engines/drascula/drascula.h
    engines/drascula/graphics.cpp
    engines/drascula/objects.cpp
    engines/drascula/rooms.cpp
    engines/drascula/saveload.cpp
    engines/drascula/sound.cpp
    engines/drascula/talk.cpp
    engines/dreamweb/detection.cpp
    engines/dreamweb/detection_tables.h
    engines/dreamweb/dreamweb.cpp
    engines/dreamweb/dreamweb.h
    engines/dreamweb/saveload.cpp
    engines/dreamweb/sound.cpp
    engines/dreamweb/stubs.cpp
    engines/dreamweb/vgagrafx.cpp
    engines/engine.cpp
    engines/fullpipe/behavior.cpp
    engines/fullpipe/behavior.h
    engines/fullpipe/configure.engine
    engines/fullpipe/detection.cpp
    engines/fullpipe/fullpipe.cpp
    engines/fullpipe/fullpipe.h
    engines/fullpipe/gameloader.cpp
    engines/fullpipe/interaction.cpp
    engines/fullpipe/lift.cpp
    engines/fullpipe/messagehandlers.cpp
    engines/fullpipe/mgm.cpp
    engines/fullpipe/motion.cpp
    engines/fullpipe/motion.h
    engines/fullpipe/scenes.cpp
    engines/fullpipe/scenes.h
    engines/fullpipe/scenes/scene04.cpp
    engines/fullpipe/scenes/scene06.cpp
    engines/fullpipe/scenes/scene07.cpp
    engines/fullpipe/scenes/scene08.cpp
    engines/fullpipe/scenes/scene09.cpp
    engines/fullpipe/scenes/scene10.cpp
    engines/fullpipe/scenes/scene11.cpp
    engines/fullpipe/scenes/scene13.cpp
    engines/fullpipe/scenes/scene14.cpp
    engines/fullpipe/scenes/scene16.cpp
    engines/fullpipe/scenes/scene18and19.cpp
    engines/fullpipe/scenes/scene22.cpp
    engines/fullpipe/scenes/scene23.cpp
    engines/fullpipe/scenes/scene25.cpp
    engines/fullpipe/scenes/scene26.cpp
    engines/fullpipe/scenes/scene27.cpp
    engines/fullpipe/scenes/scene28.cpp
    engines/fullpipe/scenes/scene29.cpp
    engines/fullpipe/scenes/scene32.cpp
    engines/fullpipe/scenes/scene34.cpp
    engines/fullpipe/scenes/sceneFinal.cpp
    engines/fullpipe/sound.cpp
    engines/fullpipe/sound.h
    engines/fullpipe/statics.cpp
    engines/fullpipe/utils.cpp
    engines/game.cpp
    engines/game.h
    engines/gob/detection/detection.cpp
    engines/gob/detection/tables_fascin.h
    engines/gob/detection/tables_playtoons.h
    engines/gob/gob.cpp
    engines/gob/gob.h
    engines/gob/inter_playtoons.cpp
    engines/gob/inter_v2.cpp
    engines/gob/inter_v4.cpp
    engines/gob/pregob/onceupon/onceupon.cpp
    engines/gob/pregob/pregob.h
    engines/gob/script.cpp
    engines/gob/sound/adlib.cpp
    engines/gob/sound/adlib.h
    engines/gob/sound/bgatmosphere.cpp
    engines/gob/sound/bgatmosphere.h
    engines/gob/sound/pcspeaker.cpp
    engines/gob/sound/pcspeaker.h
    engines/gob/sound/protracker.cpp
    engines/gob/sound/protracker.h
    engines/gob/sound/sound.cpp
    engines/gob/sound/sound.h
    engines/gob/sound/soundblaster.h
    engines/gob/sound/sounddesc.cpp
    engines/gob/videoplayer.cpp
    engines/gob/videoplayer.h
    engines/groovie/cell.cpp
    engines/groovie/configure.engine
    engines/groovie/cursor.cpp
    engines/groovie/detection.cpp
    engines/groovie/font.h
    engines/groovie/graphics.cpp
    engines/groovie/groovie.cpp
    engines/groovie/groovie.h
    engines/groovie/music.cpp
    engines/groovie/music.h
    engines/groovie/player.cpp
    engines/groovie/player.h
    engines/groovie/roq.cpp
    engines/groovie/script.cpp
    engines/groovie/vdx.cpp
    engines/hopkins/configure.engine
    engines/hopkins/detection.cpp
    engines/hopkins/hopkins.h
    engines/hopkins/sound.cpp
    engines/hopkins/sound.h
    engines/hugo/detection.cpp
    engines/hugo/dialogs.cpp
    engines/hugo/dialogs.h
    engines/hugo/display.cpp
    engines/hugo/display.h
    engines/hugo/file.cpp
    engines/hugo/file.h
    engines/hugo/hugo.cpp
    engines/hugo/hugo.h
    engines/hugo/intro.cpp
    engines/hugo/intro.h
    engines/hugo/mouse.cpp
    engines/hugo/mouse.h
    engines/hugo/parser.cpp
    engines/hugo/parser.h
    engines/hugo/sound.cpp
    engines/hugo/sound.h
    engines/hugo/text.cpp
    engines/hugo/util.cpp
    engines/kyra/debugger.cpp
    engines/kyra/detection.cpp
    engines/kyra/detection_tables.h
    engines/kyra/eobcommon.cpp
    engines/kyra/gui.cpp
    engines/kyra/gui_lol.cpp
    engines/kyra/gui_v1.cpp
    engines/kyra/items_lok.cpp
    engines/kyra/kyra_lok.cpp
    engines/kyra/kyra_v2.cpp
    engines/kyra/lol.h
    engines/kyra/resource.h
    engines/kyra/sound.cpp
    engines/kyra/sound_adlib.cpp
    engines/kyra/sound_intern.h
    engines/kyra/sound_lol.cpp
    engines/kyra/sound_towns.cpp
    engines/kyra/staticres.cpp
    engines/kyra/staticres_lol.cpp
    engines/lastexpress/configure.engine
    engines/lastexpress/detection.cpp
    engines/lastexpress/entities/gendarmes.cpp
    engines/lastexpress/game/savegame.cpp
    engines/lastexpress/lastexpress.h
    engines/lastexpress/sound/entry.cpp
    engines/lure/detection.cpp
    engines/lure/game.cpp
    engines/lure/hotspots.cpp
    engines/lure/lure.h
    engines/lure/menu.cpp
    engines/lure/res.cpp
    engines/lure/res_struct.cpp
    engines/lure/res_struct.h
    engines/lure/scripts.cpp
    engines/lure/surface.cpp
    engines/made/database.cpp
    engines/made/detection.cpp
    engines/made/made.cpp
    engines/made/pmvplayer.cpp
    engines/made/redreader.cpp
    engines/made/resource.cpp
    engines/made/screen.cpp
    engines/made/sound.cpp
    engines/mads/action.h
    engines/mads/animation.cpp
    engines/mads/animation.h
    engines/mads/assets.h
    engines/mads/configure.engine
    engines/mads/debugger.cpp
    engines/mads/debugger.h
    engines/mads/detection.cpp
    engines/mads/detection_tables.h
    engines/mads/dialogs.cpp
    engines/mads/dialogs.h
    engines/mads/dragonsphere/dragonsphere_scenes.cpp
    engines/mads/dragonsphere/dragonsphere_scenes.h
    engines/mads/dragonsphere/game_dragonsphere.cpp
    engines/mads/dragonsphere/game_dragonsphere.h
    engines/mads/events.cpp
    engines/mads/events.h
    engines/mads/font.cpp
    engines/mads/font.h
    engines/mads/game.cpp
    engines/mads/game.h
    engines/mads/hotspots.cpp
    engines/mads/hotspots.h
    engines/mads/mads.cpp
    engines/mads/mads.h
    engines/mads/menu_views.cpp
    engines/mads/menu_views.h
    engines/mads/messages.cpp
    engines/mads/messages.h
    engines/mads/module.mk
    engines/mads/msurface.cpp
    engines/mads/msurface.h
    engines/mads/nebular/dialogs_nebular.cpp
    engines/mads/nebular/game_nebular.cpp
    engines/mads/nebular/menu_nebular.cpp
    engines/mads/nebular/menu_nebular.h
    engines/mads/nebular/nebular_scenes.cpp
    engines/mads/nebular/nebular_scenes.h
    engines/mads/nebular/nebular_scenes1.cpp
    engines/mads/nebular/nebular_scenes2.cpp
    engines/mads/nebular/nebular_scenes3.cpp
    engines/mads/nebular/nebular_scenes3.h
    engines/mads/nebular/nebular_scenes4.cpp
    engines/mads/nebular/nebular_scenes5.cpp
    engines/mads/nebular/nebular_scenes6.cpp
    engines/mads/nebular/nebular_scenes7.cpp
    engines/mads/nebular/nebular_scenes8.cpp
    engines/mads/nebular/sound_nebular.cpp
    engines/mads/nebular/sound_nebular.h
    engines/mads/palette.h
    engines/mads/phantom/game_phantom.cpp
    engines/mads/phantom/game_phantom.h
    engines/mads/phantom/globals_phantom.cpp
    engines/mads/phantom/globals_phantom.h
    engines/mads/phantom/phantom_scenes.cpp
    engines/mads/phantom/phantom_scenes.h
    engines/mads/phantom/phantom_scenes1.cpp
    engines/mads/phantom/phantom_scenes1.h
    engines/mads/player.cpp
    engines/mads/player.h
    engines/mads/rails.cpp
    engines/mads/rails.h
    engines/mads/resources.cpp
    engines/mads/scene.cpp
    engines/mads/scene.h
    engines/mads/scene_data.cpp
    engines/mads/scene_data.h
    engines/mads/screen.cpp
    engines/mads/screen.h
    engines/mads/sequence.cpp
    engines/mads/sequence.h
    engines/mads/sound.cpp
    engines/mads/sound.h
    engines/mads/sprites.cpp
    engines/mads/user_interface.cpp
    engines/mads/user_interface.h
    engines/metaengine.h
    engines/mohawk/POTFILES
    engines/mohawk/bitmap.cpp
    engines/mohawk/configure.engine
    engines/mohawk/console.cpp
    engines/mohawk/console.h
    engines/mohawk/cstime.h
    engines/mohawk/cstime_game.cpp
    engines/mohawk/cstime_ui.cpp
    engines/mohawk/cstime_view.cpp
    engines/mohawk/cursors.cpp
    engines/mohawk/cursors.h
    engines/mohawk/detection.cpp
    engines/mohawk/detection_tables.h
    engines/mohawk/dialogs.cpp
    engines/mohawk/dialogs.h
    engines/mohawk/graphics.h
    engines/mohawk/mohawk.h
    engines/mohawk/myst.cpp
    engines/mohawk/myst.h
    engines/mohawk/myst_areas.cpp
    engines/mohawk/myst_areas.h
    engines/mohawk/myst_graphics.cpp
    engines/mohawk/myst_graphics.h
    engines/mohawk/myst_scripts.cpp
    engines/mohawk/myst_scripts.h
    engines/mohawk/myst_stacks/channelwood.cpp
    engines/mohawk/myst_stacks/channelwood.h
    engines/mohawk/myst_stacks/credits.cpp
    engines/mohawk/myst_stacks/credits.h
    engines/mohawk/myst_stacks/demo.h
    engines/mohawk/myst_stacks/dni.h
    engines/mohawk/myst_stacks/intro.cpp
    engines/mohawk/myst_stacks/intro.h
    engines/mohawk/myst_stacks/makingof.cpp
    engines/mohawk/myst_stacks/makingof.h
    engines/mohawk/myst_stacks/mechanical.cpp
    engines/mohawk/myst_stacks/mechanical.h
    engines/mohawk/myst_stacks/myst.cpp
    engines/mohawk/myst_stacks/myst.h
    engines/mohawk/myst_stacks/preview.cpp
    engines/mohawk/myst_stacks/preview.h
    engines/mohawk/myst_stacks/selenitic.cpp
    engines/mohawk/myst_stacks/selenitic.h
    engines/mohawk/myst_stacks/slides.cpp
    engines/mohawk/myst_stacks/slides.h
    engines/mohawk/myst_stacks/stoneship.cpp
    engines/mohawk/myst_stacks/stoneship.h
    engines/mohawk/myst_state.cpp
    engines/mohawk/myst_state.h
    engines/mohawk/resource.h
    engines/mohawk/riven.cpp
    engines/mohawk/riven.h
    engines/mohawk/riven_graphics.cpp
    engines/mohawk/riven_saveload.cpp
    engines/mohawk/riven_saveload.h
    engines/mohawk/sound.cpp
    engines/mohawk/sound.h
    engines/mohawk/video.cpp
    engines/mohawk/video.h
    engines/mohawk/view.cpp
    engines/mohawk/view.h
    engines/mortevielle/configure.engine
    engines/mortevielle/detection.cpp
    engines/mortevielle/mortevielle.cpp
    engines/mortevielle/saveload.cpp
    engines/mortevielle/sound.cpp
    engines/mortevielle/sound.h
    engines/mortevielle/utils.cpp
    engines/neverhood/configure.engine
    engines/neverhood/detection.cpp
    engines/neverhood/diskplayerscene.cpp
    engines/neverhood/diskplayerscene.h
    engines/neverhood/menumodule.cpp
    engines/neverhood/menumodule.h
    engines/neverhood/modules/module1300.cpp
    engines/neverhood/modules/module1300.h
    engines/neverhood/modules/module1300_sprites.h
    engines/neverhood/modules/module2700.cpp
    engines/neverhood/modules/module2700.h
    engines/neverhood/modules/module2800.cpp
    engines/neverhood/navigationscene.h
    engines/neverhood/neverhood.cpp
    engines/neverhood/neverhood.h
    engines/neverhood/resourceman.cpp
    engines/neverhood/scene.cpp
    engines/neverhood/scene.h
    engines/neverhood/screen.cpp
    engines/neverhood/screen.h
    engines/neverhood/smackerscene.cpp
    engines/neverhood/sound.cpp
    engines/neverhood/sound.h
    engines/parallaction/adlib.cpp
    engines/parallaction/balloons.cpp
    engines/parallaction/debug.cpp
    engines/parallaction/detection.cpp
    engines/parallaction/dialogue.cpp
    engines/parallaction/disk_br.cpp
    engines/parallaction/disk_ns.cpp
    engines/parallaction/exec.cpp
    engines/parallaction/font.cpp
    engines/parallaction/gfxbase.cpp
    engines/parallaction/graphics.cpp
    engines/parallaction/graphics.h
    engines/parallaction/gui_br.cpp
    engines/parallaction/gui_ns.cpp
    engines/parallaction/input.cpp
    engines/parallaction/objects.cpp
    engines/parallaction/parallaction.cpp
    engines/parallaction/parallaction.h
    engines/parallaction/parallaction_br.cpp
    engines/parallaction/parallaction_ns.cpp
    engines/parallaction/parser.cpp
    engines/parallaction/parser.h
    engines/parallaction/saveload.cpp
    engines/parallaction/sound_br.cpp
    engines/parallaction/sound_ns.cpp
    engines/parallaction/staticres.cpp
    engines/pegasus/configure.engine
    engines/pegasus/detection.cpp
    engines/pegasus/input.h
    engines/pegasus/neighborhood/caldoria/caldoria4dsystem.cpp
    engines/pegasus/neighborhood/caldoria/caldoriamessages.cpp
    engines/pegasus/neighborhood/caldoria/caldoriamirror.cpp
    engines/pegasus/neighborhood/mars/mars.cpp
    engines/pegasus/neighborhood/norad/alpha/noradalpha.cpp
    engines/pegasus/neighborhood/norad/delta/globegame.cpp
    engines/pegasus/neighborhood/norad/pressuretracker.cpp
    engines/pegasus/neighborhood/wsc/wsc.cpp
    engines/pegasus/pegasus.h
    engines/prince/configure.engine
    engines/prince/debugger.cpp
    engines/prince/detection.cpp
    engines/prince/detection.h
    engines/prince/graphics.cpp
    engines/prince/mob.h
    engines/prince/module.mk
    engines/prince/prince.cpp
    engines/prince/prince.h
    engines/prince/saveload.cpp
    engines/prince/script.cpp
    engines/prince/sound.cpp
    engines/prince/sound.h
    engines/queen/detection.cpp
    engines/queen/queen.h
    engines/queen/sound.cpp
    engines/queen/sound.h
    engines/saga/configure.engine
    engines/saga/detection.cpp
    engines/saga/detection_tables.h
    engines/saga/displayinfo.h
    engines/saga/font.cpp
    engines/saga/interface.cpp
    engines/saga/isomap.cpp
    engines/saga/itedata.cpp
    engines/saga/music.cpp
    engines/saga/music.h
    engines/saga/puzzle.cpp
    engines/saga/render.cpp
    engines/saga/saga.cpp
    engines/saga/saga.h
    engines/saga/saveload.cpp
    engines/saga/scene.cpp
    engines/saga/shorten.cpp
    engines/saga/shorten.h
    engines/saga/sound.cpp
    engines/savestate.h
    engines/sci/configure.engine
    engines/sci/console.cpp
    engines/sci/console.h
    engines/sci/decompressor.cpp
    engines/sci/detection.cpp
    engines/sci/detection_tables.h
    engines/sci/engine/features.cpp
    engines/sci/engine/features.h
    engines/sci/engine/file.cpp
    engines/sci/engine/file.h
    engines/sci/engine/gc.cpp
    engines/sci/engine/kernel.cpp
    engines/sci/engine/kernel.h
    engines/sci/engine/kernel_tables.h
    engines/sci/engine/kevent.cpp
    engines/sci/engine/kfile.cpp
    engines/sci/engine/kgraphics.cpp
    engines/sci/engine/kgraphics32.cpp
    engines/sci/engine/klists.cpp
    engines/sci/engine/kmisc.cpp
    engines/sci/engine/kpathing.cpp
    engines/sci/engine/kscripts.cpp
    engines/sci/engine/ksound.cpp
    engines/sci/engine/kstring.cpp
    engines/sci/engine/kvideo.cpp
    engines/sci/engine/message.cpp
    engines/sci/engine/object.cpp
    engines/sci/engine/object.h
    engines/sci/engine/savegame.cpp
    engines/sci/engine/savegame.h
    engines/sci/engine/script.cpp
    engines/sci/engine/script_patches.cpp
    engines/sci/engine/script_patches.h
    engines/sci/engine/scriptdebug.cpp
    engines/sci/engine/seg_manager.cpp
    engines/sci/engine/seg_manager.h
    engines/sci/engine/segment.cpp
    engines/sci/engine/segment.h
    engines/sci/engine/selector.cpp
    engines/sci/engine/selector.h
    engines/sci/engine/state.cpp
    engines/sci/engine/state.h
    engines/sci/engine/static_selectors.cpp
    engines/sci/engine/vm.cpp
    engines/sci/engine/vm.h
    engines/sci/engine/vm_types.cpp
    engines/sci/engine/vm_types.h
    engines/sci/engine/workarounds.cpp
    engines/sci/engine/workarounds.h
    engines/sci/event.cpp
    engines/sci/event.h
    engines/sci/graphics/animate.cpp
    engines/sci/graphics/animate.h
    engines/sci/graphics/cache.cpp
    engines/sci/graphics/cache.h
    engines/sci/graphics/compare.cpp
    engines/sci/graphics/compare.h
    engines/sci/graphics/controls16.cpp
    engines/sci/graphics/controls32.cpp
    engines/sci/graphics/controls32.h
    engines/sci/graphics/cursor.cpp
    engines/sci/graphics/cursor.h
    engines/sci/graphics/frameout.cpp
    engines/sci/graphics/frameout.h
    engines/sci/graphics/helpers.h
    engines/sci/graphics/maciconbar.cpp
    engines/sci/graphics/menu.cpp
    engines/sci/graphics/paint16.h
    engines/sci/graphics/paint32.cpp
    engines/sci/graphics/paint32.h
    engines/sci/graphics/palette.cpp
    engines/sci/graphics/palette.h
    engines/sci/graphics/picture.cpp
    engines/sci/graphics/picture.h
    engines/sci/graphics/portrait.cpp
    engines/sci/graphics/ports.cpp
    engines/sci/graphics/screen.cpp
    engines/sci/graphics/screen.h
    engines/sci/graphics/text16.cpp
    engines/sci/graphics/text32.cpp
    engines/sci/graphics/text32.h
    engines/sci/graphics/view.cpp
    engines/sci/graphics/view.h
    engines/sci/module.mk
    engines/sci/parser/vocabulary.cpp
    engines/sci/parser/vocabulary.h
    engines/sci/resource.cpp
    engines/sci/resource.h
    engines/sci/resource_audio.cpp
    engines/sci/sci.cpp
    engines/sci/sci.h
    engines/sci/sound/audio.cpp
    engines/sci/sound/audio.h
    engines/sci/sound/drivers/amigamac.cpp
    engines/sci/sound/drivers/midi.cpp
    engines/sci/sound/midiparser_sci.cpp
    engines/sci/sound/music.cpp
    engines/sci/sound/music.h
    engines/sci/sound/soundcmd.cpp
    engines/sci/util.cpp
    engines/sci/util.h
    engines/scumm/POTFILES
    engines/scumm/actor.cpp
    engines/scumm/actor.h
    engines/scumm/boxes.cpp
    engines/scumm/charset-fontdata.cpp
    engines/scumm/configure.engine
    engines/scumm/debugger.cpp
    engines/scumm/detection.cpp
    engines/scumm/detection_tables.h
    engines/scumm/dialogs.cpp
    engines/scumm/dialogs.h
    engines/scumm/gfx.cpp
    engines/scumm/gfx.h
    engines/scumm/he/animation_he.cpp
    engines/scumm/he/animation_he.h
    engines/scumm/he/cup_player_he.cpp
    engines/scumm/he/intern_he.h
    engines/scumm/he/logic/puttrace.cpp
    engines/scumm/he/logic_he.cpp
    engines/scumm/he/logic_he.h
    engines/scumm/he/script_v100he.cpp
    engines/scumm/he/script_v70he.cpp
    engines/scumm/he/script_v72he.cpp
    engines/scumm/he/script_v90he.cpp
    engines/scumm/he/sound_he.cpp
    engines/scumm/he/sound_he.h
    engines/scumm/he/sprite_he.cpp
    engines/scumm/he/sprite_he.h
    engines/scumm/he/wiz_he.cpp
    engines/scumm/he/wiz_he.h
    engines/scumm/imuse_digi/dimuse.h
    engines/scumm/imuse_digi/dimuse_sndmgr.cpp
    engines/scumm/imuse_digi/dimuse_sndmgr.h
    engines/scumm/imuse_digi/dimuse_track.cpp
    engines/scumm/imuse_digi/dimuse_track.h
    engines/scumm/input.cpp
    engines/scumm/insane/insane.cpp
    engines/scumm/midiparser_ro.cpp
    engines/scumm/module.mk
    engines/scumm/object.cpp
    engines/scumm/players/player_ad.cpp
    engines/scumm/players/player_ad.h
    engines/scumm/players/player_apple2.h
    engines/scumm/players/player_mac.cpp
    engines/scumm/players/player_towns.cpp
    engines/scumm/players/player_towns.h
    engines/scumm/players/player_v2.cpp
    engines/scumm/players/player_v2cms.cpp
    engines/scumm/players/player_v3m.h
    engines/scumm/players/player_v4a.cpp
    engines/scumm/players/player_v5m.h
    engines/scumm/resource.cpp
    engines/scumm/saveload.cpp
    engines/scumm/saveload.h
    engines/scumm/script_v2.cpp
    engines/scumm/scumm-md5.h
    engines/scumm/scumm.cpp
    engines/scumm/scumm.h
    engines/scumm/scumm_v0.h
    engines/scumm/scumm_v2.h
    engines/scumm/scumm_v4.h
    engines/scumm/scumm_v6.h
    engines/scumm/smush/imuse_channel.cpp
    engines/scumm/smush/smush_mixer.cpp
    engines/scumm/smush/smush_mixer.h
    engines/scumm/smush/smush_player.cpp
    engines/scumm/smush/smush_player.h
    engines/scumm/sound.cpp
    engines/scumm/sound.h
    engines/scumm/string.cpp
    engines/scumm/vars.cpp
    engines/sherlock/animation.cpp
    engines/sherlock/configure.engine
    engines/sherlock/debugger.cpp
    engines/sherlock/detection_tables.h
    engines/sherlock/events.cpp
    engines/sherlock/events.h
    engines/sherlock/fixed_text.cpp
    engines/sherlock/fixed_text.h
    engines/sherlock/fonts.cpp
    engines/sherlock/fonts.h
    engines/sherlock/image_file.cpp
    engines/sherlock/image_file.h
    engines/sherlock/journal.cpp
    engines/sherlock/journal.h
    engines/sherlock/module.mk
    engines/sherlock/music.cpp
    engines/sherlock/music.h
    engines/sherlock/objects.cpp
    engines/sherlock/people.cpp
    engines/sherlock/saveload.cpp
    engines/sherlock/scalpel/3do/movie_decoder.cpp
    engines/sherlock/scalpel/drivers/adlib.cpp
    engines/sherlock/scalpel/scalpel.cpp
    engines/sherlock/scalpel/scalpel_darts.cpp
    engines/sherlock/scalpel/scalpel_debugger.cpp
    engines/sherlock/scalpel/scalpel_fixed_text.cpp
    engines/sherlock/scalpel/scalpel_fixed_text.h
    engines/sherlock/scalpel/scalpel_inventory.cpp
    engines/sherlock/scalpel/scalpel_inventory.h
    engines/sherlock/scalpel/scalpel_journal.cpp
    engines/sherlock/scalpel/scalpel_journal.h
    engines/sherlock/scalpel/scalpel_map.cpp
    engines/sherlock/scalpel/scalpel_saveload.cpp
    engines/sherlock/scalpel/scalpel_saveload.h
    engines/sherlock/scalpel/scalpel_scene.cpp
    engines/sherlock/scalpel/scalpel_scene.h
    engines/sherlock/scalpel/scalpel_screen.cpp
    engines/sherlock/scalpel/scalpel_screen.h
    engines/sherlock/scalpel/scalpel_talk.cpp
    engines/sherlock/scalpel/scalpel_talk.h
    engines/sherlock/scalpel/scalpel_user_interface.cpp
    engines/sherlock/scalpel/scalpel_user_interface.h
    engines/sherlock/scalpel/settings.cpp
    engines/sherlock/scalpel/settings.h
    engines/sherlock/scalpel/tsage/logo.cpp
    engines/sherlock/scene.cpp
    engines/sherlock/scene.h
    engines/sherlock/screen.cpp
    engines/sherlock/screen.h
    engines/sherlock/sherlock.cpp
    engines/sherlock/sherlock.h
    engines/sherlock/sound.cpp
    engines/sherlock/sound.h
    engines/sherlock/surface.cpp
    engines/sherlock/surface.h
    engines/sherlock/talk.cpp
    engines/sherlock/talk.h
    engines/sherlock/tattoo/tattoo.cpp
    engines/sherlock/tattoo/tattoo_darts.cpp
    engines/sherlock/tattoo/tattoo_fixed_text.cpp
    engines/sherlock/tattoo/tattoo_fixed_text.h
    engines/sherlock/tattoo/tattoo_journal.cpp
    engines/sherlock/tattoo/tattoo_journal.h
    engines/sherlock/tattoo/tattoo_map.cpp
    engines/sherlock/tattoo/tattoo_people.cpp
    engines/sherlock/tattoo/tattoo_people.h
    engines/sherlock/tattoo/tattoo_resources.cpp
    engines/sherlock/tattoo/tattoo_resources.h
    engines/sherlock/tattoo/tattoo_scene.cpp
    engines/sherlock/tattoo/tattoo_talk.cpp
    engines/sherlock/tattoo/tattoo_user_interface.cpp
    engines/sherlock/tattoo/tattoo_user_interface.h
    engines/sherlock/tattoo/widget_base.cpp
    engines/sherlock/tattoo/widget_credits.cpp
    engines/sherlock/tattoo/widget_files.cpp
    engines/sherlock/tattoo/widget_files.h
    engines/sherlock/tattoo/widget_foolscap.cpp
    engines/sherlock/tattoo/widget_inventory.cpp
    engines/sherlock/tattoo/widget_options.cpp
    engines/sherlock/tattoo/widget_password.cpp
    engines/sherlock/tattoo/widget_quit.cpp
    engines/sherlock/tattoo/widget_talk.cpp
    engines/sherlock/tattoo/widget_text.cpp
    engines/sherlock/tattoo/widget_tooltip.cpp
    engines/sherlock/tattoo/widget_verbs.cpp
    engines/sky/compact.cpp
    engines/sky/compact.h
    engines/sky/control.cpp
    engines/sky/control.h
    engines/sky/detection.cpp
    engines/sky/logic.cpp
    engines/sky/music/adlibchannel.cpp
    engines/sky/music/adlibchannel.h
    engines/sky/music/adlibmusic.cpp
    engines/sky/music/adlibmusic.h
    engines/sky/sky.h
    engines/sky/skydefs.h
    engines/sword1/configure.engine
    engines/sword1/detection.cpp
    engines/sword1/logic.h
    engines/sword1/objectman.cpp
    engines/sword1/objectman.h
    engines/sword1/resman.cpp
    engines/sword1/router.cpp
    engines/sword1/sound.cpp
    engines/sword1/sound.h
    engines/sword1/sword1.cpp
    engines/sword1/sword1.h
    engines/sword2/configure.engine
    engines/sword2/interpreter.cpp
    engines/sword2/memory.cpp
    engines/sword2/music.cpp
    engines/sword2/router.cpp
    engines/sword2/screen.cpp
    engines/sword2/sword2.cpp
    engines/sword2/sword2.h
    engines/sword25/configure.engine
    engines/sword25/detection.cpp
    engines/sword25/detection_tables.h
    engines/sword25/fmv/movieplayer.cpp
    engines/sword25/fmv/movieplayer.h
    engines/sword25/gfx/animation.cpp
    engines/sword25/gfx/animationresource.cpp
    engines/sword25/gfx/fontresource.cpp
    engines/sword25/gfx/graphicengine.cpp
    engines/sword25/gfx/graphicengine.h
    engines/sword25/gfx/image/imgloader.cpp
    engines/sword25/gfx/image/imgloader.h
    engines/sword25/gfx/image/renderedimage.cpp
    engines/sword25/gfx/image/renderedimage.h
    engines/sword25/gfx/image/swimage.cpp
    engines/sword25/gfx/image/swimage.h
    engines/sword25/gfx/image/vectorimage.cpp
    engines/sword25/gfx/image/vectorimage.h
    engines/sword25/gfx/image/vectorimagerenderer.cpp
    engines/sword25/gfx/panel.cpp
    engines/sword25/gfx/renderobject.cpp
    engines/sword25/gfx/screenshot.cpp
    engines/sword25/gfx/staticbitmap.cpp
    engines/sword25/gfx/text.cpp
    engines/sword25/kernel/kernel_script.cpp
    engines/sword25/math/polygon.cpp
    engines/sword25/package/packagemanager.cpp
    engines/sword25/package/packagemanager.h
    engines/sword25/script/luacallback.cpp
    engines/sword25/script/luascript.cpp
    engines/sword25/sfx/soundengine.cpp
    engines/sword25/sfx/soundengine.h
    engines/sword25/sword25.cpp
    engines/sword25/sword25.h
    engines/sword25/util/lua/lbaselib.cpp
    engines/sword25/util/lua/ldo.cpp
    engines/sword25/util/lua/luaconf.h
    engines/sword25/util/lua/scummvm_file.cpp
    engines/sword25/util/lua_persistence_util.cpp
    engines/sword25/util/lua_persistence_util.h
    engines/sword25/util/lua_unpersist.cpp
    engines/teenagent/detection.cpp
    engines/teenagent/font.cpp
    engines/teenagent/music.cpp
    engines/teenagent/music.h
    engines/teenagent/objects.h
    engines/teenagent/resources.cpp
    engines/teenagent/scene.cpp
    engines/teenagent/scene.h
    engines/teenagent/teenagent.cpp
    engines/teenagent/teenagent.h
    engines/testbed/config.h
    engines/testbed/detection.cpp
    engines/testbed/midi.cpp
    engines/testbed/midi.h
    engines/testbed/sound.h
    engines/testbed/testbed.cpp
    engines/testbed/testbed.h
    engines/testbed/testsuite.cpp
    engines/tinsel/anim.cpp
    engines/tinsel/bmv.cpp
    engines/tinsel/bmv.h
    engines/tinsel/detection.cpp
    engines/tinsel/detection_tables.h
    engines/tinsel/dialogs.cpp
    engines/tinsel/graphics.cpp
    engines/tinsel/handle.cpp
    engines/tinsel/music.cpp
    engines/tinsel/palette.cpp
    engines/tinsel/play.cpp
    engines/tinsel/saveload.cpp
    engines/tinsel/sound.cpp
    engines/tinsel/tinsel.cpp
    engines/tinsel/tinsel.h
    engines/toltecs/animation.cpp
    engines/toltecs/configure.engine
    engines/toltecs/detection.cpp
    engines/toltecs/menu.cpp
    engines/toltecs/movie.cpp
    engines/toltecs/movie.h
    engines/toltecs/resource.cpp
    engines/toltecs/segmap.cpp
    engines/toltecs/segmap.h
    engines/toltecs/sprite.cpp
    engines/toltecs/toltecs.cpp
    engines/toltecs/toltecs.h
    engines/tony/configure.engine
    engines/tony/detection.cpp
    engines/tony/detection_tables.h
    engines/tony/font.cpp
    engines/tony/game.cpp
    engines/tony/gfxcore.cpp
    engines/tony/gfxcore.h
    engines/tony/loc.cpp
    engines/tony/loc.h
    engines/tony/mpal/loadmpc.cpp
    engines/tony/mpal/mpal.cpp
    engines/tony/mpal/mpalutils.cpp
    engines/tony/sound.cpp
    engines/tony/sound.h
    engines/tony/tony.cpp
    engines/tony/tony.h
    engines/toon/configure.engine
    engines/toon/detection.cpp
    engines/toon/toon.cpp
    engines/touche/configure.engine
    engines/touche/detection.cpp
    engines/touche/opcodes.cpp
    engines/touche/touche.cpp
    engines/touche/touche.h
    engines/tsage/blue_force/blueforce_dialogs.cpp
    engines/tsage/blue_force/blueforce_dialogs.h
    engines/tsage/blue_force/blueforce_logic.cpp
    engines/tsage/blue_force/blueforce_scenes1.cpp
    engines/tsage/blue_force/blueforce_scenes4.cpp
    engines/tsage/blue_force/blueforce_scenes5.cpp
    engines/tsage/blue_force/blueforce_scenes6.cpp
    engines/tsage/blue_force/blueforce_scenes8.cpp
    engines/tsage/converse.cpp
    engines/tsage/core.cpp
    engines/tsage/detection.cpp
    engines/tsage/detection_tables.h
    engines/tsage/dialogs.cpp
    engines/tsage/dialogs.h
    engines/tsage/events.cpp
    engines/tsage/globals.cpp
    engines/tsage/globals.h
    engines/tsage/graphics.cpp
    engines/tsage/graphics.h
    engines/tsage/module.mk
    engines/tsage/ringworld/ringworld_demo.cpp
    engines/tsage/ringworld/ringworld_dialogs.cpp
    engines/tsage/ringworld/ringworld_dialogs.h
    engines/tsage/ringworld/ringworld_logic.cpp
    engines/tsage/ringworld/ringworld_scenes2.cpp
    engines/tsage/ringworld/ringworld_scenes3.cpp
    engines/tsage/ringworld/ringworld_scenes5.cpp
    engines/tsage/ringworld2/ringworld2_dialogs.cpp
    engines/tsage/ringworld2/ringworld2_dialogs.h
    engines/tsage/ringworld2/ringworld2_logic.cpp
    engines/tsage/ringworld2/ringworld2_outpost.cpp
    engines/tsage/ringworld2/ringworld2_scenes0.cpp
    engines/tsage/ringworld2/ringworld2_scenes1.cpp
    engines/tsage/ringworld2/ringworld2_scenes2.cpp
    engines/tsage/saveload.cpp
    engines/tsage/scenes.cpp
    engines/tsage/sound.h
    engines/tsage/tsage.h
    engines/tsage/user_interface.cpp
    engines/tucker/detection.cpp
    engines/tucker/resource.cpp
    engines/tucker/sequences.cpp
    engines/tucker/staticres.cpp
    engines/tucker/tucker.cpp
    engines/tucker/tucker.h
    engines/voyeur/animation.cpp
    engines/voyeur/animation.h
    engines/voyeur/data.cpp
    engines/voyeur/debugger.cpp
    engines/voyeur/detection.cpp
    engines/voyeur/events.cpp
    engines/voyeur/files.cpp
    engines/voyeur/files.h
    engines/voyeur/files_threads.cpp
    engines/voyeur/module.mk
    engines/voyeur/sound.cpp
    engines/voyeur/sound.h
    engines/voyeur/voyeur.cpp
    engines/voyeur/voyeur.h
    engines/voyeur/voyeur_game.cpp
    engines/wintermute/ad/ad_actor.cpp
    engines/wintermute/ad/ad_entity.cpp
    engines/wintermute/ad/ad_entity.h
    engines/wintermute/ad/ad_game.cpp
    engines/wintermute/ad/ad_game.h
    engines/wintermute/ad/ad_scene.cpp
    engines/wintermute/ad/ad_scene.h
    engines/wintermute/base/base_engine.cpp
    engines/wintermute/base/base_engine.h
    engines/wintermute/base/base_frame.cpp
    engines/wintermute/base/base_frame.h
    engines/wintermute/base/base_game.cpp
    engines/wintermute/base/base_game.h
    engines/wintermute/base/base_keyboard_state.cpp
    engines/wintermute/base/base_persistence_manager.cpp
    engines/wintermute/base/base_persistence_manager.h
    engines/wintermute/base/base_region.cpp
    engines/wintermute/base/base_region.h
    engines/wintermute/base/base_script_holder.cpp
    engines/wintermute/base/base_scriptable.cpp
    engines/wintermute/base/base_scriptable.h
    engines/wintermute/base/base_sprite.cpp
    engines/wintermute/base/base_sprite.h
    engines/wintermute/base/base_sub_frame.cpp
    engines/wintermute/base/base_sub_frame.h
    engines/wintermute/base/base_viewport.cpp
    engines/wintermute/base/base_viewport.h
    engines/wintermute/base/file/base_disk_file.cpp
    engines/wintermute/base/file/base_file.cpp
    engines/wintermute/base/file/base_save_thumb_file.cpp
    engines/wintermute/base/font/base_font_truetype.cpp
    engines/wintermute/base/gfx/base_surface.cpp
    engines/wintermute/base/scriptables/script.cpp
    engines/wintermute/base/scriptables/script.h
    engines/wintermute/base/scriptables/script_engine.cpp
    engines/wintermute/base/scriptables/script_engine.h
    engines/wintermute/base/sound/base_sound_manager.cpp
    engines/wintermute/configure.engine
    engines/wintermute/debugger.cpp
    engines/wintermute/debugger.h
    engines/wintermute/detection.cpp
    engines/wintermute/detection_tables.h
    engines/wintermute/module.mk
    engines/wintermute/ui/ui_window.cpp
    engines/wintermute/utils/convert_utf.cpp
    engines/wintermute/utils/convert_utf.h
    engines/wintermute/wintermute.cpp
    engines/wintermute/wintermute.h
    engines/zvision/configure.engine
    engines/zvision/core/events.cpp
    engines/zvision/detection.cpp
    engines/zvision/scripting/actions.h
    engines/zvision/sound/midi.cpp
    engines/zvision/sound/midi.h
    engines/zvision/text/truetype_font.cpp
    engines/zvision/zvision.cpp
    graphics/VectorRenderer.cpp
    graphics/VectorRenderer.h
    graphics/VectorRendererSpec.cpp
    graphics/VectorRendererSpec.h
    graphics/font.cpp
    graphics/font.h
    graphics/fonts/ttf.cpp
    graphics/fonts/ttf.h
    graphics/module.mk
    graphics/pixelformat.h
    graphics/primitives.cpp
    graphics/primitives.h
    graphics/scaler/thumbnail_intern.cpp
    graphics/surface.cpp
    graphics/surface.h
    graphics/thumbnail.cpp
    graphics/transparent_surface.cpp
    graphics/transparent_surface.h
    gui/EventRecorder.cpp
    gui/ThemeEngine.cpp
    gui/ThemeEngine.h
    gui/ThemeEval.cpp
    gui/ThemeLayout.cpp
    gui/ThemeLayout.h
    gui/Tooltip.cpp
    gui/Tooltip.h
    gui/about.cpp
    gui/credits.h
    gui/debugger.cpp
    gui/dialog.cpp
    gui/dialog.h
    gui/gui-manager.cpp
    gui/gui-manager.h
    gui/launcher.cpp
    gui/module.mk
    gui/object.cpp
    gui/onscreendialog.cpp
    gui/options.cpp
    gui/options.h
    gui/predictivedialog.cpp
    gui/predictivedialog.h
    gui/recorderdialog.cpp
    gui/saveload-dialog.cpp
    gui/saveload.cpp
    gui/saveload.h
    gui/themes/default.inc
    gui/themes/scummclassic.zip
    gui/themes/scummclassic/THEMERC
    gui/themes/scummclassic/classic_layout.stx
    gui/themes/scummclassic/classic_layout_lowres.stx
    gui/themes/scummmodern.zip
    gui/themes/scummmodern/THEMERC
    gui/themes/scummmodern/scummmodern_layout.stx
    gui/themes/scummmodern/scummmodern_layout_lowres.stx
    gui/themes/scummtheme.py
    gui/themes/translations.dat
    gui/widget.cpp
    gui/widget.h
    gui/widgets/editable.cpp
    gui/widgets/edittext.cpp
    gui/widgets/list.cpp
    gui/widgets/popup.cpp
    gui/widgets/popup.h
    gui/widgets/scrollbar.cpp
    gui/widgets/tab.cpp
    gui/widgets/tab.h
    image/codecs/bmp_raw.cpp
    image/codecs/cinepak.cpp
    image/codecs/codec.cpp
    image/codecs/indeo3.cpp
    image/codecs/msvideo1.cpp
    image/codecs/msvideo1.h
    image/codecs/rpza.cpp
    image/module.mk
    image/pict.cpp
    po/POTFILES
    po/be_BY.po
    po/ca_ES.po
    po/cs_CZ.po
    po/de_DE.po
    po/es_ES.po
    po/eu.po
    po/fi_FI.po
    po/fr_FR.po
    po/gl_ES.po
    po/hu_HU.po
    po/it_IT.po
    po/module.mk
    po/nb_NO.po
    po/nl_NL.po
    po/nn_NO.po
    po/pl_PL.po
    po/pt_BR.po
    po/ru_RU.po
    po/scummvm.pot
    po/uk_UA.po
    ports.mk
    test/common/algorithm.h
    test/common/array.h
    test/common/rational.h
    test/common/str.h
    test/module.mk
    video/avi_decoder.cpp
    video/coktel_decoder.cpp
    video/coktel_decoder.h
    video/mpegps_decoder.cpp
    video/psx_decoder.cpp
    video/qt_decoder.cpp





Commit: 873d555add9aaf5eb0d021518f5134142e2c2ff6
    https://github.com/scummvm/scummvm/commit/873d555add9aaf5eb0d021518f5134142e2c2ff6
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2016-07-26T19:54:17-04:00

Commit Message:
XEEN: Add detection for German World of Xeen

Changed paths:
    engines/xeen/detection_tables.h



diff --git a/engines/xeen/detection_tables.h b/engines/xeen/detection_tables.h
index 0735daa..03290b9 100644
--- a/engines/xeen/detection_tables.h
+++ b/engines/xeen/detection_tables.h
@@ -42,6 +42,25 @@ static const XeenGameDescription gameDescriptions[] = {
 		0
 	},
 
+	{
+		// World of Xeen (German)
+		{
+			"worldofxeen",
+			nullptr,
+			{
+				{"xeen.cc", 0, "f4e4b3ddc43bd102dbe1637f480f1fa1", 13214150},
+				{"dark.cc", 0, "84a86bbbc5f2fe96c0b0325485ed8203", 11173657},
+				AD_LISTEND
+			},
+			Common::DE_DEU,
+			Common::kPlatformDOS,
+			ADGF_NO_FLAGS,
+			GUIO1(GUIO_NONE),
+		},
+		GType_WorldOfXeen,
+		0
+	},
+
 	{ AD_TABLE_END_MARKER, 0, 0 }
 };
 


Commit: f5ab3d1cd9eb3a884b0ab5d0b154a4f9cccc74b7
    https://github.com/scummvm/scummvm/commit/f5ab3d1cd9eb3a884b0ab5d0b154a4f9cccc74b7
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2016-08-27T13:59:08-04:00

Commit Message:
Merge branch 'master' into xeen

Changed paths:
  A .travis.yml
  A devtools/create_titanic/create_titanic_dat.cpp
  A devtools/create_titanic/file.h
  A devtools/create_titanic/hash-str.h
  A devtools/create_titanic/hashmap.cpp
  A devtools/create_titanic/hashmap.h
  A devtools/create_titanic/memorypool.cpp
  A devtools/create_titanic/memorypool.h
  A devtools/create_titanic/module.mk
  A devtools/create_titanic/script_preresponses.cpp
  A devtools/create_titanic/script_preresponses.h
  A devtools/create_titanic/script_quotes.cpp
  A devtools/create_titanic/script_quotes.h
  A devtools/create_titanic/script_ranges.cpp
  A devtools/create_titanic/script_ranges.h
  A devtools/create_titanic/script_responses.cpp
  A devtools/create_titanic/script_responses.h
  A devtools/create_titanic/script_states.cpp
  A devtools/create_titanic/script_states.h
  A devtools/create_titanic/str.cpp
  A devtools/create_titanic/str.h
  A devtools/create_titanic/tag_maps.cpp
  A devtools/create_titanic/tag_maps.h
  A devtools/create_titanic/winexe.cpp
  A devtools/create_titanic/winexe.h
  A devtools/create_titanic/winexe_pe.cpp
  A devtools/create_titanic/winexe_pe.h
  A dists/scummvm.appdata.xml
  A doc/de/LIESMICH
  A doc/de/NEUES
  A engines/adl/adl_v4.cpp
  A engines/adl/adl_v4.h
  A engines/adl/hires0.cpp
  A engines/adl/hires0.h
  A engines/adl/hires4.cpp
  A engines/adl/hires4.h
  A engines/director/configure.engine
  A engines/director/detection.cpp
  A engines/director/detection_tables.h
  A engines/director/director.cpp
  A engines/director/director.h
  A engines/director/frame.cpp
  A engines/director/frame.h
  A engines/director/images.cpp
  A engines/director/images.h
  A engines/director/lingo/lingo-builtins.cpp
  A engines/director/lingo/lingo-code.cpp
  A engines/director/lingo/lingo-codegen.cpp
  A engines/director/lingo/lingo-funcs.cpp
  A engines/director/lingo/lingo-gr.cpp
  A engines/director/lingo/lingo-gr.h
  A engines/director/lingo/lingo-gr.y
  A engines/director/lingo/lingo-lex.cpp
  A engines/director/lingo/lingo-lex.l
  A engines/director/lingo/lingo-the.cpp
  A engines/director/lingo/lingo-the.h
  A engines/director/lingo/lingo.cpp
  A engines/director/lingo/lingo.h
  A engines/director/lingo/tests/Lingo bytecode.html
  A engines/director/lingo/tests/builtin.lingo
  A engines/director/lingo/tests/factory.lingo
  A engines/director/lingo/tests/factory2.lingo
  A engines/director/lingo/tests/goto.lingo
  A engines/director/lingo/tests/if.lingo
  A engines/director/lingo/tests/ilk.lingo
  A engines/director/lingo/tests/lingotests.lingo
  A engines/director/lingo/tests/loops.lingo
  A engines/director/lingo/tests/macros.lingo
  A engines/director/lingo/tests/macros2.lingo
  A engines/director/lingo/tests/math.lingo
  A engines/director/lingo/tests/mci.lingo
  A engines/director/lingo/tests/point.lingo
  A engines/director/lingo/tests/strings.lingo
  A engines/director/lingo/tests/the.lingo
  A engines/director/module.mk
  A engines/director/movie.cpp
  A engines/director/movie.h
  A engines/director/resource.cpp
  A engines/director/resource.h
  A engines/director/score.cpp
  A engines/director/score.h
  A engines/director/sound.cpp
  A engines/director/sound.h
  A engines/director/sprite.cpp
  A engines/director/sprite.h
  A engines/fullpipe/anihandler.cpp
  A engines/fullpipe/anihandler.h
  A engines/mohawk/riven_sound.cpp
  A engines/mohawk/riven_sound.h
  A engines/sci/graphics/cursor32.cpp
  A engines/sci/graphics/cursor32.h
  A engines/sci/graphics/transitions32.cpp
  A engines/sci/graphics/transitions32.h
  A engines/titanic/carry/arm.cpp
  A engines/titanic/carry/arm.h
  A engines/titanic/carry/auditory_centre.cpp
  A engines/titanic/carry/auditory_centre.h
  A engines/titanic/carry/bowl_ear.cpp
  A engines/titanic/carry/bowl_ear.h
  A engines/titanic/carry/brain.cpp
  A engines/titanic/carry/brain.h
  A engines/titanic/carry/bridge_piece.cpp
  A engines/titanic/carry/bridge_piece.h
  A engines/titanic/carry/carry.cpp
  A engines/titanic/carry/carry.h
  A engines/titanic/carry/carry_parrot.cpp
  A engines/titanic/carry/carry_parrot.h
  A engines/titanic/carry/central_core.cpp
  A engines/titanic/carry/central_core.h
  A engines/titanic/carry/chicken.cpp
  A engines/titanic/carry/chicken.h
  A engines/titanic/carry/crushed_tv.cpp
  A engines/titanic/carry/crushed_tv.h
  A engines/titanic/carry/ear.cpp
  A engines/titanic/carry/ear.h
  A engines/titanic/carry/eye.cpp
  A engines/titanic/carry/eye.h
  A engines/titanic/carry/feathers.cpp
  A engines/titanic/carry/feathers.h
  A engines/titanic/carry/fruit.cpp
  A engines/titanic/carry/fruit.h
  A engines/titanic/carry/glass.cpp
  A engines/titanic/carry/glass.h
  A engines/titanic/carry/hammer.cpp
  A engines/titanic/carry/hammer.h
  A engines/titanic/carry/head_piece.cpp
  A engines/titanic/carry/head_piece.h
  A engines/titanic/carry/hose.cpp
  A engines/titanic/carry/hose.h
  A engines/titanic/carry/hose_end.cpp
  A engines/titanic/carry/hose_end.h
  A engines/titanic/carry/key.cpp
  A engines/titanic/carry/key.h
  A engines/titanic/carry/liftbot_head.cpp
  A engines/titanic/carry/liftbot_head.h
  A engines/titanic/carry/long_stick.cpp
  A engines/titanic/carry/long_stick.h
  A engines/titanic/carry/magazine.cpp
  A engines/titanic/carry/magazine.h
  A engines/titanic/carry/maitred_left_arm.cpp
  A engines/titanic/carry/maitred_left_arm.h
  A engines/titanic/carry/maitred_right_arm.cpp
  A engines/titanic/carry/maitred_right_arm.h
  A engines/titanic/carry/mouth.cpp
  A engines/titanic/carry/mouth.h
  A engines/titanic/carry/napkin.cpp
  A engines/titanic/carry/napkin.h
  A engines/titanic/carry/nose.cpp
  A engines/titanic/carry/nose.h
  A engines/titanic/carry/note.cpp
  A engines/titanic/carry/note.h
  A engines/titanic/carry/parcel.cpp
  A engines/titanic/carry/parcel.h
  A engines/titanic/carry/perch.cpp
  A engines/titanic/carry/perch.h
  A engines/titanic/carry/phonograph_cylinder.cpp
  A engines/titanic/carry/phonograph_cylinder.h
  A engines/titanic/carry/phonograph_ear.cpp
  A engines/titanic/carry/phonograph_ear.h
  A engines/titanic/carry/photograph.cpp
  A engines/titanic/carry/photograph.h
  A engines/titanic/carry/plug_in.cpp
  A engines/titanic/carry/plug_in.h
  A engines/titanic/carry/speech_centre.cpp
  A engines/titanic/carry/speech_centre.h
  A engines/titanic/carry/sweets.cpp
  A engines/titanic/carry/sweets.h
  A engines/titanic/carry/vision_centre.cpp
  A engines/titanic/carry/vision_centre.h
  A engines/titanic/configure.engine
  A engines/titanic/continue_save_dialog.cpp
  A engines/titanic/continue_save_dialog.h
  A engines/titanic/core/background.cpp
  A engines/titanic/core/background.h
  A engines/titanic/core/click_responder.cpp
  A engines/titanic/core/click_responder.h
  A engines/titanic/core/dont_save_file_item.cpp
  A engines/titanic/core/dont_save_file_item.h
  A engines/titanic/core/drop_target.cpp
  A engines/titanic/core/drop_target.h
  A engines/titanic/core/file_item.cpp
  A engines/titanic/core/file_item.h
  A engines/titanic/core/game_object.cpp
  A engines/titanic/core/game_object.h
  A engines/titanic/core/game_object_desc_item.cpp
  A engines/titanic/core/game_object_desc_item.h
  A engines/titanic/core/link_item.cpp
  A engines/titanic/core/link_item.h
  A engines/titanic/core/list.cpp
  A engines/titanic/core/list.h
  A engines/titanic/core/mail_man.cpp
  A engines/titanic/core/mail_man.h
  A engines/titanic/core/message_target.cpp
  A engines/titanic/core/message_target.h
  A engines/titanic/core/multi_drop_target.cpp
  A engines/titanic/core/multi_drop_target.h
  A engines/titanic/core/named_item.cpp
  A engines/titanic/core/named_item.h
  A engines/titanic/core/node_item.cpp
  A engines/titanic/core/node_item.h
  A engines/titanic/core/project_item.cpp
  A engines/titanic/core/project_item.h
  A engines/titanic/core/resource_key.cpp
  A engines/titanic/core/resource_key.h
  A engines/titanic/core/room_item.cpp
  A engines/titanic/core/room_item.h
  A engines/titanic/core/saveable_object.cpp
  A engines/titanic/core/saveable_object.h
  A engines/titanic/core/static_image.cpp
  A engines/titanic/core/static_image.h
  A engines/titanic/core/tree_item.cpp
  A engines/titanic/core/tree_item.h
  A engines/titanic/core/turn_on_object.cpp
  A engines/titanic/core/turn_on_object.h
  A engines/titanic/core/turn_on_play_sound.cpp
  A engines/titanic/core/turn_on_play_sound.h
  A engines/titanic/core/turn_on_turn_off.cpp
  A engines/titanic/core/turn_on_turn_off.h
  A engines/titanic/core/view_item.cpp
  A engines/titanic/core/view_item.h
  A engines/titanic/debugger.cpp
  A engines/titanic/debugger.h
  A engines/titanic/detection.cpp
  A engines/titanic/detection_tables.h
  A engines/titanic/events.cpp
  A engines/titanic/events.h
  A engines/titanic/game/announce.cpp
  A engines/titanic/game/announce.h
  A engines/titanic/game/annoy_barbot.cpp
  A engines/titanic/game/annoy_barbot.h
  A engines/titanic/game/arb_background.cpp
  A engines/titanic/game/arb_background.h
  A engines/titanic/game/arboretum_gate.cpp
  A engines/titanic/game/arboretum_gate.h
  A engines/titanic/game/auto_animate.cpp
  A engines/titanic/game/auto_animate.h
  A engines/titanic/game/bar_bell.cpp
  A engines/titanic/game/bar_bell.h
  A engines/titanic/game/bar_menu.cpp
  A engines/titanic/game/bar_menu.h
  A engines/titanic/game/bar_menu_button.cpp
  A engines/titanic/game/bar_menu_button.h
  A engines/titanic/game/belbot_get_light.cpp
  A engines/titanic/game/belbot_get_light.h
  A engines/titanic/game/bomb.cpp
  A engines/titanic/game/bomb.h
  A engines/titanic/game/bottom_of_well_monitor.cpp
  A engines/titanic/game/bottom_of_well_monitor.h
  A engines/titanic/game/bowl_unlocker.cpp
  A engines/titanic/game/bowl_unlocker.h
  A engines/titanic/game/brain_slot.cpp
  A engines/titanic/game/brain_slot.h
  A engines/titanic/game/bridge_door.cpp
  A engines/titanic/game/bridge_door.h
  A engines/titanic/game/bridge_view.cpp
  A engines/titanic/game/bridge_view.h
  A engines/titanic/game/broken_pell_base.cpp
  A engines/titanic/game/broken_pell_base.h
  A engines/titanic/game/broken_pellerator.cpp
  A engines/titanic/game/broken_pellerator.h
  A engines/titanic/game/broken_pellerator_froz.cpp
  A engines/titanic/game/broken_pellerator_froz.h
  A engines/titanic/game/cage.cpp
  A engines/titanic/game/cage.h
  A engines/titanic/game/captains_wheel.cpp
  A engines/titanic/game/captains_wheel.h
  A engines/titanic/game/cdrom.cpp
  A engines/titanic/game/cdrom.h
  A engines/titanic/game/cdrom_computer.cpp
  A engines/titanic/game/cdrom_computer.h
  A engines/titanic/game/cdrom_tray.cpp
  A engines/titanic/game/cdrom_tray.h
  A engines/titanic/game/cell_point_button.cpp
  A engines/titanic/game/cell_point_button.h
  A engines/titanic/game/chev_code.cpp
  A engines/titanic/game/chev_code.h
  A engines/titanic/game/chev_panel.cpp
  A engines/titanic/game/chev_panel.h
  A engines/titanic/game/chicken_cooler.cpp
  A engines/titanic/game/chicken_cooler.h
  A engines/titanic/game/chicken_dispensor.cpp
  A engines/titanic/game/chicken_dispensor.h
  A engines/titanic/game/close_broken_pel.cpp
  A engines/titanic/game/close_broken_pel.h
  A engines/titanic/game/code_wheel.cpp
  A engines/titanic/game/code_wheel.h
  A engines/titanic/game/computer.cpp
  A engines/titanic/game/computer.h
  A engines/titanic/game/computer_screen.cpp
  A engines/titanic/game/computer_screen.h
  A engines/titanic/game/cookie.cpp
  A engines/titanic/game/cookie.h
  A engines/titanic/game/credits.cpp
  A engines/titanic/game/credits.h
  A engines/titanic/game/credits_button.cpp
  A engines/titanic/game/credits_button.h
  A engines/titanic/game/dead_area.cpp
  A engines/titanic/game/dead_area.h
  A engines/titanic/game/desk_click_responder.cpp
  A engines/titanic/game/desk_click_responder.h
  A engines/titanic/game/doorbot_elevator_handler.cpp
  A engines/titanic/game/doorbot_elevator_handler.h
  A engines/titanic/game/doorbot_home_handler.cpp
  A engines/titanic/game/doorbot_home_handler.h
  A engines/titanic/game/ear_sweet_bowl.cpp
  A engines/titanic/game/ear_sweet_bowl.h
  A engines/titanic/game/eject_phonograph_button.cpp
  A engines/titanic/game/eject_phonograph_button.h
  A engines/titanic/game/elevator_action_area.cpp
  A engines/titanic/game/elevator_action_area.h
  A engines/titanic/game/emma_control.cpp
  A engines/titanic/game/emma_control.h
  A engines/titanic/game/empty_nut_bowl.cpp
  A engines/titanic/game/empty_nut_bowl.h
  A engines/titanic/game/end_credit_text.cpp
  A engines/titanic/game/end_credit_text.h
  A engines/titanic/game/end_credits.cpp
  A engines/titanic/game/end_credits.h
  A engines/titanic/game/end_explode_ship.cpp
  A engines/titanic/game/end_explode_ship.h
  A engines/titanic/game/end_game_credits.cpp
  A engines/titanic/game/end_game_credits.h
  A engines/titanic/game/end_sequence_control.cpp
  A engines/titanic/game/end_sequence_control.h
  A engines/titanic/game/fan.cpp
  A engines/titanic/game/fan.h
  A engines/titanic/game/fan_control.cpp
  A engines/titanic/game/fan_control.h
  A engines/titanic/game/fan_decrease.cpp
  A engines/titanic/game/fan_decrease.h
  A engines/titanic/game/fan_increase.cpp
  A engines/titanic/game/fan_increase.h
  A engines/titanic/game/fan_noises.cpp
  A engines/titanic/game/fan_noises.h
  A engines/titanic/game/floor_indicator.cpp
  A engines/titanic/game/floor_indicator.h
  A engines/titanic/game/games_console.cpp
  A engines/titanic/game/games_console.h
  A engines/titanic/game/get_lift_eye2.cpp
  A engines/titanic/game/get_lift_eye2.h
  A engines/titanic/game/glass_smasher.cpp
  A engines/titanic/game/glass_smasher.h
  A engines/titanic/game/gondolier/gondolier_base.cpp
  A engines/titanic/game/gondolier/gondolier_base.h
  A engines/titanic/game/gondolier/gondolier_chest.cpp
  A engines/titanic/game/gondolier/gondolier_chest.h
  A engines/titanic/game/gondolier/gondolier_face.cpp
  A engines/titanic/game/gondolier/gondolier_face.h
  A engines/titanic/game/gondolier/gondolier_mixer.cpp
  A engines/titanic/game/gondolier/gondolier_mixer.h
  A engines/titanic/game/gondolier/gondolier_slider.cpp
  A engines/titanic/game/gondolier/gondolier_slider.h
  A engines/titanic/game/hammer_clip.cpp
  A engines/titanic/game/hammer_clip.h
  A engines/titanic/game/hammer_dispensor.cpp
  A engines/titanic/game/hammer_dispensor.h
  A engines/titanic/game/hammer_dispensor_button.cpp
  A engines/titanic/game/hammer_dispensor_button.h
  A engines/titanic/game/head_slot.cpp
  A engines/titanic/game/head_slot.h
  A engines/titanic/game/head_smash_event.cpp
  A engines/titanic/game/head_smash_event.h
  A engines/titanic/game/head_smash_lever.cpp
  A engines/titanic/game/head_smash_lever.h
  A engines/titanic/game/head_spinner.cpp
  A engines/titanic/game/head_spinner.h
  A engines/titanic/game/idle_summoner.cpp
  A engines/titanic/game/idle_summoner.h
  A engines/titanic/game/leave_sec_class_state.cpp
  A engines/titanic/game/leave_sec_class_state.h
  A engines/titanic/game/lemon_dispensor.cpp
  A engines/titanic/game/lemon_dispensor.h
  A engines/titanic/game/light.cpp
  A engines/titanic/game/light.h
  A engines/titanic/game/light_switch.cpp
  A engines/titanic/game/light_switch.h
  A engines/titanic/game/little_lift_button.cpp
  A engines/titanic/game/little_lift_button.h
  A engines/titanic/game/long_stick_dispenser.cpp
  A engines/titanic/game/long_stick_dispenser.h
  A engines/titanic/game/maitred/maitred_arm_holder.cpp
  A engines/titanic/game/maitred/maitred_arm_holder.h
  A engines/titanic/game/maitred/maitred_body.cpp
  A engines/titanic/game/maitred/maitred_body.h
  A engines/titanic/game/maitred/maitred_legs.cpp
  A engines/titanic/game/maitred/maitred_legs.h
  A engines/titanic/game/maitred/maitred_prod_receptor.cpp
  A engines/titanic/game/maitred/maitred_prod_receptor.h
  A engines/titanic/game/missiveomat.cpp
  A engines/titanic/game/missiveomat.h
  A engines/titanic/game/missiveomat_button.cpp
  A engines/titanic/game/missiveomat_button.h
  A engines/titanic/game/movie_tester.cpp
  A engines/titanic/game/movie_tester.h
  A engines/titanic/game/music_console_button.cpp
  A engines/titanic/game/music_console_button.h
  A engines/titanic/game/music_room_phonograph.cpp
  A engines/titanic/game/music_room_phonograph.h
  A engines/titanic/game/music_room_stop_phonograph_button.cpp
  A engines/titanic/game/music_room_stop_phonograph_button.h
  A engines/titanic/game/music_system_lock.cpp
  A engines/titanic/game/music_system_lock.h
  A engines/titanic/game/musical_instrument.cpp
  A engines/titanic/game/musical_instrument.h
  A engines/titanic/game/nav_helmet.cpp
  A engines/titanic/game/nav_helmet.h
  A engines/titanic/game/nav_helmet_off.cpp
  A engines/titanic/game/nav_helmet_off.h
  A engines/titanic/game/nav_helmet_on.cpp
  A engines/titanic/game/nav_helmet_on.h
  A engines/titanic/game/navigation_computer.cpp
  A engines/titanic/game/navigation_computer.h
  A engines/titanic/game/no_nut_bowl.cpp
  A engines/titanic/game/no_nut_bowl.h
  A engines/titanic/game/nose_holder.cpp
  A engines/titanic/game/nose_holder.h
  A engines/titanic/game/null_port_hole.cpp
  A engines/titanic/game/null_port_hole.h
  A engines/titanic/game/nut_replacer.cpp
  A engines/titanic/game/nut_replacer.h
  A engines/titanic/game/parrot/parrot_lobby_controller.cpp
  A engines/titanic/game/parrot/parrot_lobby_controller.h
  A engines/titanic/game/parrot/parrot_lobby_link_updater.cpp
  A engines/titanic/game/parrot/parrot_lobby_link_updater.h
  A engines/titanic/game/parrot/parrot_lobby_object.cpp
  A engines/titanic/game/parrot/parrot_lobby_object.h
  A engines/titanic/game/parrot/parrot_lobby_view_object.cpp
  A engines/titanic/game/parrot/parrot_lobby_view_object.h
  A engines/titanic/game/parrot/parrot_loser.cpp
  A engines/titanic/game/parrot/parrot_loser.h
  A engines/titanic/game/parrot/parrot_nut_bowl_actor.cpp
  A engines/titanic/game/parrot/parrot_nut_bowl_actor.h
  A engines/titanic/game/parrot/parrot_nut_eater.cpp
  A engines/titanic/game/parrot/parrot_nut_eater.h
  A engines/titanic/game/parrot/parrot_perch_holder.cpp
  A engines/titanic/game/parrot/parrot_perch_holder.h
  A engines/titanic/game/parrot/parrot_trigger.cpp
  A engines/titanic/game/parrot/parrot_trigger.h
  A engines/titanic/game/parrot/player_meets_parrot.cpp
  A engines/titanic/game/parrot/player_meets_parrot.h
  A engines/titanic/game/pet/pet.cpp
  A engines/titanic/game/pet/pet.h
  A engines/titanic/game/pet/pet_class1.cpp
  A engines/titanic/game/pet/pet_class1.h
  A engines/titanic/game/pet/pet_class2.cpp
  A engines/titanic/game/pet/pet_class2.h
  A engines/titanic/game/pet/pet_class3.cpp
  A engines/titanic/game/pet/pet_class3.h
  A engines/titanic/game/pet/pet_lift.cpp
  A engines/titanic/game/pet/pet_lift.h
  A engines/titanic/game/pet/pet_monitor.cpp
  A engines/titanic/game/pet/pet_monitor.h
  A engines/titanic/game/pet/pet_pellerator.cpp
  A engines/titanic/game/pet/pet_pellerator.h
  A engines/titanic/game/pet/pet_position.cpp
  A engines/titanic/game/pet/pet_position.h
  A engines/titanic/game/pet/pet_sentinal.cpp
  A engines/titanic/game/pet/pet_sentinal.h
  A engines/titanic/game/pet/pet_sounds.cpp
  A engines/titanic/game/pet/pet_sounds.h
  A engines/titanic/game/pet/pet_transition.cpp
  A engines/titanic/game/pet/pet_transition.h
  A engines/titanic/game/pet/pet_transport.cpp
  A engines/titanic/game/pet/pet_transport.h
  A engines/titanic/game/pet/pet_val_base.cpp
  A engines/titanic/game/pet/pet_val_base.h
  A engines/titanic/game/pet_disabler.cpp
  A engines/titanic/game/pet_disabler.h
  A engines/titanic/game/phonograph.cpp
  A engines/titanic/game/phonograph.h
  A engines/titanic/game/phonograph_lid.cpp
  A engines/titanic/game/phonograph_lid.h
  A engines/titanic/game/pickup/pick_up.cpp
  A engines/titanic/game/pickup/pick_up.h
  A engines/titanic/game/pickup/pick_up_bar_glass.cpp
  A engines/titanic/game/pickup/pick_up_bar_glass.h
  A engines/titanic/game/pickup/pick_up_hose.cpp
  A engines/titanic/game/pickup/pick_up_hose.h
  A engines/titanic/game/pickup/pick_up_lemon.cpp
  A engines/titanic/game/pickup/pick_up_lemon.h
  A engines/titanic/game/pickup/pick_up_speech_centre.cpp
  A engines/titanic/game/pickup/pick_up_speech_centre.h
  A engines/titanic/game/pickup/pick_up_vis_centre.cpp
  A engines/titanic/game/pickup/pick_up_vis_centre.h
  A engines/titanic/game/placeholder/bar_shelf_vis_centre.cpp
  A engines/titanic/game/placeholder/bar_shelf_vis_centre.h
  A engines/titanic/game/placeholder/lemon_on_bar.cpp
  A engines/titanic/game/placeholder/lemon_on_bar.h
  A engines/titanic/game/placeholder/place_holder.cpp
  A engines/titanic/game/placeholder/place_holder.h
  A engines/titanic/game/placeholder/tv_on_bar.cpp
  A engines/titanic/game/placeholder/tv_on_bar.h
  A engines/titanic/game/play_music_button.cpp
  A engines/titanic/game/play_music_button.h
  A engines/titanic/game/play_on_act.cpp
  A engines/titanic/game/play_on_act.h
  A engines/titanic/game/port_hole.cpp
  A engines/titanic/game/port_hole.h
  A engines/titanic/game/record_phonograph_button.cpp
  A engines/titanic/game/record_phonograph_button.h
  A engines/titanic/game/replacement_ear.cpp
  A engines/titanic/game/replacement_ear.h
  A engines/titanic/game/reserved_table.cpp
  A engines/titanic/game/reserved_table.h
  A engines/titanic/game/restaurant_cylinder_holder.cpp
  A engines/titanic/game/restaurant_cylinder_holder.h
  A engines/titanic/game/restaurant_phonograph.cpp
  A engines/titanic/game/restaurant_phonograph.h
  A engines/titanic/game/sauce_dispensor.cpp
  A engines/titanic/game/sauce_dispensor.h
  A engines/titanic/game/search_point.cpp
  A engines/titanic/game/search_point.h
  A engines/titanic/game/season_background.cpp
  A engines/titanic/game/season_background.h
  A engines/titanic/game/season_barrel.cpp
  A engines/titanic/game/season_barrel.h
  A engines/titanic/game/seasonal_adjustment.cpp
  A engines/titanic/game/seasonal_adjustment.h
  A engines/titanic/game/service_elevator_window.cpp
  A engines/titanic/game/service_elevator_window.h
  A engines/titanic/game/sgt/armchair.cpp
  A engines/titanic/game/sgt/armchair.h
  A engines/titanic/game/sgt/basin.cpp
  A engines/titanic/game/sgt/basin.h
  A engines/titanic/game/sgt/bedfoot.cpp
  A engines/titanic/game/sgt/bedfoot.h
  A engines/titanic/game/sgt/bedhead.cpp
  A engines/titanic/game/sgt/bedhead.h
  A engines/titanic/game/sgt/chest_of_drawers.cpp
  A engines/titanic/game/sgt/chest_of_drawers.h
  A engines/titanic/game/sgt/desk.cpp
  A engines/titanic/game/sgt/desk.h
  A engines/titanic/game/sgt/deskchair.cpp
  A engines/titanic/game/sgt/deskchair.h
  A engines/titanic/game/sgt/drawer.cpp
  A engines/titanic/game/sgt/drawer.h
  A engines/titanic/game/sgt/sgt_doors.cpp
  A engines/titanic/game/sgt/sgt_doors.h
  A engines/titanic/game/sgt/sgt_nav.cpp
  A engines/titanic/game/sgt/sgt_nav.h
  A engines/titanic/game/sgt/sgt_navigation.cpp
  A engines/titanic/game/sgt/sgt_navigation.h
  A engines/titanic/game/sgt/sgt_restaurant_doors.cpp
  A engines/titanic/game/sgt/sgt_restaurant_doors.h
  A engines/titanic/game/sgt/sgt_state_control.cpp
  A engines/titanic/game/sgt/sgt_state_control.h
  A engines/titanic/game/sgt/sgt_state_room.cpp
  A engines/titanic/game/sgt/sgt_state_room.h
  A engines/titanic/game/sgt/sgt_tv.cpp
  A engines/titanic/game/sgt/sgt_tv.h
  A engines/titanic/game/sgt/sgt_upper_doors_sound.cpp
  A engines/titanic/game/sgt/sgt_upper_doors_sound.h
  A engines/titanic/game/sgt/toilet.cpp
  A engines/titanic/game/sgt/toilet.h
  A engines/titanic/game/sgt/vase.cpp
  A engines/titanic/game/sgt/vase.h
  A engines/titanic/game/sgt/washstand.cpp
  A engines/titanic/game/sgt/washstand.h
  A engines/titanic/game/ship_setting.cpp
  A engines/titanic/game/ship_setting.h
  A engines/titanic/game/ship_setting_button.cpp
  A engines/titanic/game/ship_setting_button.h
  A engines/titanic/game/show_cell_points.cpp
  A engines/titanic/game/show_cell_points.h
  A engines/titanic/game/speech_dispensor.cpp
  A engines/titanic/game/speech_dispensor.h
  A engines/titanic/game/splash_animation.cpp
  A engines/titanic/game/splash_animation.h
  A engines/titanic/game/starling_puret.cpp
  A engines/titanic/game/starling_puret.h
  A engines/titanic/game/start_action.cpp
  A engines/titanic/game/start_action.h
  A engines/titanic/game/stop_phonograph_button.cpp
  A engines/titanic/game/stop_phonograph_button.h
  A engines/titanic/game/sub_glass.cpp
  A engines/titanic/game/sub_glass.h
  A engines/titanic/game/sub_wrapper.cpp
  A engines/titanic/game/sub_wrapper.h
  A engines/titanic/game/sweet_bowl.cpp
  A engines/titanic/game/sweet_bowl.h
  A engines/titanic/game/television.cpp
  A engines/titanic/game/television.h
  A engines/titanic/game/third_class_canal.cpp
  A engines/titanic/game/third_class_canal.h
  A engines/titanic/game/throw_tv_down_well.cpp
  A engines/titanic/game/throw_tv_down_well.h
  A engines/titanic/game/titania_still_control.cpp
  A engines/titanic/game/titania_still_control.h
  A engines/titanic/game/tow_parrot_nav.cpp
  A engines/titanic/game/tow_parrot_nav.h
  A engines/titanic/game/transport/exit_pellerator.cpp
  A engines/titanic/game/transport/exit_pellerator.h
  A engines/titanic/game/transport/gondolier.cpp
  A engines/titanic/game/transport/gondolier.h
  A engines/titanic/game/transport/lift.cpp
  A engines/titanic/game/transport/lift.h
  A engines/titanic/game/transport/lift_indicator.cpp
  A engines/titanic/game/transport/lift_indicator.h
  A engines/titanic/game/transport/pellerator.cpp
  A engines/titanic/game/transport/pellerator.h
  A engines/titanic/game/transport/service_elevator.cpp
  A engines/titanic/game/transport/service_elevator.h
  A engines/titanic/game/transport/transport.cpp
  A engines/titanic/game/transport/transport.h
  A engines/titanic/game/up_lighter.cpp
  A engines/titanic/game/up_lighter.h
  A engines/titanic/game/useless_lever.cpp
  A engines/titanic/game/useless_lever.h
  A engines/titanic/game/volume_control.cpp
  A engines/titanic/game/volume_control.h
  A engines/titanic/game/wheel_button.cpp
  A engines/titanic/game/wheel_button.h
  A engines/titanic/game/wheel_hotspot.cpp
  A engines/titanic/game/wheel_hotspot.h
  A engines/titanic/game/wheel_spin.cpp
  A engines/titanic/game/wheel_spin.h
  A engines/titanic/game/wheel_spin_horn.cpp
  A engines/titanic/game/wheel_spin_horn.h
  A engines/titanic/game_location.cpp
  A engines/titanic/game_location.h
  A engines/titanic/game_manager.cpp
  A engines/titanic/game_manager.h
  A engines/titanic/game_state.cpp
  A engines/titanic/game_state.h
  A engines/titanic/game_view.cpp
  A engines/titanic/game_view.h
  A engines/titanic/gfx/act_button.cpp
  A engines/titanic/gfx/act_button.h
  A engines/titanic/gfx/changes_season_button.cpp
  A engines/titanic/gfx/changes_season_button.h
  A engines/titanic/gfx/chev_left_off.cpp
  A engines/titanic/gfx/chev_left_off.h
  A engines/titanic/gfx/chev_left_on.cpp
  A engines/titanic/gfx/chev_left_on.h
  A engines/titanic/gfx/chev_right_off.cpp
  A engines/titanic/gfx/chev_right_off.h
  A engines/titanic/gfx/chev_right_on.cpp
  A engines/titanic/gfx/chev_right_on.h
  A engines/titanic/gfx/chev_send_rec_switch.cpp
  A engines/titanic/gfx/chev_send_rec_switch.h
  A engines/titanic/gfx/chev_switch.cpp
  A engines/titanic/gfx/chev_switch.h
  A engines/titanic/gfx/edit_control.cpp
  A engines/titanic/gfx/edit_control.h
  A engines/titanic/gfx/elevator_button.cpp
  A engines/titanic/gfx/elevator_button.h
  A engines/titanic/gfx/get_from_succ.cpp
  A engines/titanic/gfx/get_from_succ.h
  A engines/titanic/gfx/helmet_on_off.cpp
  A engines/titanic/gfx/helmet_on_off.h
  A engines/titanic/gfx/home_photo.cpp
  A engines/titanic/gfx/home_photo.h
  A engines/titanic/gfx/icon_nav_action.cpp
  A engines/titanic/gfx/icon_nav_action.h
  A engines/titanic/gfx/icon_nav_butt.cpp
  A engines/titanic/gfx/icon_nav_butt.h
  A engines/titanic/gfx/icon_nav_down.cpp
  A engines/titanic/gfx/icon_nav_down.h
  A engines/titanic/gfx/icon_nav_image.cpp
  A engines/titanic/gfx/icon_nav_image.h
  A engines/titanic/gfx/icon_nav_left.cpp
  A engines/titanic/gfx/icon_nav_left.h
  A engines/titanic/gfx/icon_nav_receive.cpp
  A engines/titanic/gfx/icon_nav_receive.h
  A engines/titanic/gfx/icon_nav_right.cpp
  A engines/titanic/gfx/icon_nav_right.h
  A engines/titanic/gfx/icon_nav_send.cpp
  A engines/titanic/gfx/icon_nav_send.h
  A engines/titanic/gfx/icon_nav_up.cpp
  A engines/titanic/gfx/icon_nav_up.h
  A engines/titanic/gfx/keybrd_butt.cpp
  A engines/titanic/gfx/keybrd_butt.h
  A engines/titanic/gfx/move_object_button.cpp
  A engines/titanic/gfx/move_object_button.h
  A engines/titanic/gfx/music_control.cpp
  A engines/titanic/gfx/music_control.h
  A engines/titanic/gfx/music_slider.cpp
  A engines/titanic/gfx/music_slider.h
  A engines/titanic/gfx/music_slider_pitch.cpp
  A engines/titanic/gfx/music_slider_pitch.h
  A engines/titanic/gfx/music_slider_speed.cpp
  A engines/titanic/gfx/music_slider_speed.h
  A engines/titanic/gfx/music_switch.cpp
  A engines/titanic/gfx/music_switch.h
  A engines/titanic/gfx/music_switch_inversion.cpp
  A engines/titanic/gfx/music_switch_inversion.h
  A engines/titanic/gfx/music_switch_reverse.cpp
  A engines/titanic/gfx/music_switch_reverse.h
  A engines/titanic/gfx/music_voice_mute.cpp
  A engines/titanic/gfx/music_voice_mute.h
  A engines/titanic/gfx/send_to_succ.cpp
  A engines/titanic/gfx/send_to_succ.h
  A engines/titanic/gfx/sgt_selector.cpp
  A engines/titanic/gfx/sgt_selector.h
  A engines/titanic/gfx/slider_button.cpp
  A engines/titanic/gfx/slider_button.h
  A engines/titanic/gfx/small_chev_left_off.cpp
  A engines/titanic/gfx/small_chev_left_off.h
  A engines/titanic/gfx/small_chev_left_on.cpp
  A engines/titanic/gfx/small_chev_left_on.h
  A engines/titanic/gfx/small_chev_right_off.cpp
  A engines/titanic/gfx/small_chev_right_off.h
  A engines/titanic/gfx/small_chev_right_on.cpp
  A engines/titanic/gfx/small_chev_right_on.h
  A engines/titanic/gfx/st_button.cpp
  A engines/titanic/gfx/st_button.h
  A engines/titanic/gfx/status_change_button.cpp
  A engines/titanic/gfx/status_change_button.h
  A engines/titanic/gfx/text_down.cpp
  A engines/titanic/gfx/text_down.h
  A engines/titanic/gfx/text_skrew.cpp
  A engines/titanic/gfx/text_skrew.h
  A engines/titanic/gfx/text_up.cpp
  A engines/titanic/gfx/text_up.h
  A engines/titanic/gfx/toggle_button.cpp
  A engines/titanic/gfx/toggle_button.h
  A engines/titanic/gfx/toggle_switch.cpp
  A engines/titanic/gfx/toggle_switch.h
  A engines/titanic/input_handler.cpp
  A engines/titanic/input_handler.h
  A engines/titanic/input_translator.cpp
  A engines/titanic/input_translator.h
  A engines/titanic/main_game_window.cpp
  A engines/titanic/main_game_window.h
  A engines/titanic/messages/auto_sound_event.cpp
  A engines/titanic/messages/auto_sound_event.h
  A engines/titanic/messages/bilge_auto_sound_event.cpp
  A engines/titanic/messages/bilge_auto_sound_event.h
  A engines/titanic/messages/bilge_dispensor_event.cpp
  A engines/titanic/messages/bilge_dispensor_event.h
  A engines/titanic/messages/door_auto_sound_event.cpp
  A engines/titanic/messages/door_auto_sound_event.h
  A engines/titanic/messages/messages.cpp
  A engines/titanic/messages/messages.h
  A engines/titanic/messages/mouse_messages.cpp
  A engines/titanic/messages/mouse_messages.h
  A engines/titanic/messages/pet_messages.h
  A engines/titanic/messages/service_elevator_door.cpp
  A engines/titanic/messages/service_elevator_door.h
  A engines/titanic/module.mk
  A engines/titanic/moves/call_pellerator.cpp
  A engines/titanic/moves/call_pellerator.h
  A engines/titanic/moves/enter_bomb_room.cpp
  A engines/titanic/moves/enter_bomb_room.h
  A engines/titanic/moves/enter_bridge.cpp
  A engines/titanic/moves/enter_bridge.h
  A engines/titanic/moves/enter_exit_first_class_state.cpp
  A engines/titanic/moves/enter_exit_first_class_state.h
  A engines/titanic/moves/enter_exit_mini_lift.cpp
  A engines/titanic/moves/enter_exit_mini_lift.h
  A engines/titanic/moves/enter_exit_sec_class_mini_lift.cpp
  A engines/titanic/moves/enter_exit_sec_class_mini_lift.h
  A engines/titanic/moves/enter_exit_view.cpp
  A engines/titanic/moves/enter_exit_view.h
  A engines/titanic/moves/enter_sec_class_state.cpp
  A engines/titanic/moves/enter_sec_class_state.h
  A engines/titanic/moves/exit_arboretum.cpp
  A engines/titanic/moves/exit_arboretum.h
  A engines/titanic/moves/exit_bridge.cpp
  A engines/titanic/moves/exit_bridge.h
  A engines/titanic/moves/exit_lift.cpp
  A engines/titanic/moves/exit_lift.h
  A engines/titanic/moves/exit_pellerator.cpp
  A engines/titanic/moves/exit_pellerator.h
  A engines/titanic/moves/exit_state_room.cpp
  A engines/titanic/moves/exit_state_room.h
  A engines/titanic/moves/exit_tiania.cpp
  A engines/titanic/moves/exit_tiania.h
  A engines/titanic/moves/move_player_in_parrot_room.cpp
  A engines/titanic/moves/move_player_in_parrot_room.h
  A engines/titanic/moves/move_player_to.cpp
  A engines/titanic/moves/move_player_to.h
  A engines/titanic/moves/move_player_to_from.cpp
  A engines/titanic/moves/move_player_to_from.h
  A engines/titanic/moves/multi_move.cpp
  A engines/titanic/moves/multi_move.h
  A engines/titanic/moves/pan_from_pel.cpp
  A engines/titanic/moves/pan_from_pel.h
  A engines/titanic/moves/restaurant_pan_handler.cpp
  A engines/titanic/moves/restaurant_pan_handler.h
  A engines/titanic/moves/restricted_move.cpp
  A engines/titanic/moves/restricted_move.h
  A engines/titanic/moves/scraliontis_table.cpp
  A engines/titanic/moves/scraliontis_table.h
  A engines/titanic/moves/trip_down_canal.cpp
  A engines/titanic/moves/trip_down_canal.h
  A engines/titanic/npcs/barbot.cpp
  A engines/titanic/npcs/barbot.h
  A engines/titanic/npcs/bellbot.cpp
  A engines/titanic/npcs/bellbot.h
  A engines/titanic/npcs/bilge_succubus.cpp
  A engines/titanic/npcs/bilge_succubus.h
  A engines/titanic/npcs/callbot.cpp
  A engines/titanic/npcs/callbot.h
  A engines/titanic/npcs/character.cpp
  A engines/titanic/npcs/character.h
  A engines/titanic/npcs/deskbot.cpp
  A engines/titanic/npcs/deskbot.h
  A engines/titanic/npcs/doorbot.cpp
  A engines/titanic/npcs/doorbot.h
  A engines/titanic/npcs/liftbot.cpp
  A engines/titanic/npcs/liftbot.h
  A engines/titanic/npcs/maitre_d.cpp
  A engines/titanic/npcs/maitre_d.h
  A engines/titanic/npcs/mobile.cpp
  A engines/titanic/npcs/mobile.h
  A engines/titanic/npcs/parrot.cpp
  A engines/titanic/npcs/parrot.h
  A engines/titanic/npcs/parrot_succubus.cpp
  A engines/titanic/npcs/parrot_succubus.h
  A engines/titanic/npcs/robot_controller.cpp
  A engines/titanic/npcs/robot_controller.h
  A engines/titanic/npcs/starlings.cpp
  A engines/titanic/npcs/starlings.h
  A engines/titanic/npcs/succubus.cpp
  A engines/titanic/npcs/succubus.h
  A engines/titanic/npcs/summon_bots.cpp
  A engines/titanic/npcs/summon_bots.h
  A engines/titanic/npcs/titania.cpp
  A engines/titanic/npcs/titania.h
  A engines/titanic/npcs/true_talk_npc.cpp
  A engines/titanic/npcs/true_talk_npc.h
  A engines/titanic/pet_control/pet_control.cpp
  A engines/titanic/pet_control/pet_control.h
  A engines/titanic/pet_control/pet_conversations.cpp
  A engines/titanic/pet_control/pet_conversations.h
  A engines/titanic/pet_control/pet_drag_chev.cpp
  A engines/titanic/pet_control/pet_drag_chev.h
  A engines/titanic/pet_control/pet_element.cpp
  A engines/titanic/pet_control/pet_element.h
  A engines/titanic/pet_control/pet_frame.cpp
  A engines/titanic/pet_control/pet_frame.h
  A engines/titanic/pet_control/pet_gfx_element.cpp
  A engines/titanic/pet_control/pet_gfx_element.h
  A engines/titanic/pet_control/pet_glyphs.cpp
  A engines/titanic/pet_control/pet_glyphs.h
  A engines/titanic/pet_control/pet_graphic.cpp
  A engines/titanic/pet_control/pet_graphic.h
  A engines/titanic/pet_control/pet_graphic2.cpp
  A engines/titanic/pet_control/pet_graphic2.h
  A engines/titanic/pet_control/pet_inventory.cpp
  A engines/titanic/pet_control/pet_inventory.h
  A engines/titanic/pet_control/pet_inventory_glyphs.cpp
  A engines/titanic/pet_control/pet_inventory_glyphs.h
  A engines/titanic/pet_control/pet_leaf.cpp
  A engines/titanic/pet_control/pet_leaf.h
  A engines/titanic/pet_control/pet_load.cpp
  A engines/titanic/pet_control/pet_load.h
  A engines/titanic/pet_control/pet_load_save.cpp
  A engines/titanic/pet_control/pet_load_save.h
  A engines/titanic/pet_control/pet_message.cpp
  A engines/titanic/pet_control/pet_message.h
  A engines/titanic/pet_control/pet_mode_off.cpp
  A engines/titanic/pet_control/pet_mode_off.h
  A engines/titanic/pet_control/pet_mode_on.cpp
  A engines/titanic/pet_control/pet_mode_on.h
  A engines/titanic/pet_control/pet_mode_panel.cpp
  A engines/titanic/pet_control/pet_mode_panel.h
  A engines/titanic/pet_control/pet_pannel1.cpp
  A engines/titanic/pet_control/pet_pannel1.h
  A engines/titanic/pet_control/pet_pannel2.cpp
  A engines/titanic/pet_control/pet_pannel2.h
  A engines/titanic/pet_control/pet_pannel3.cpp
  A engines/titanic/pet_control/pet_pannel3.h
  A engines/titanic/pet_control/pet_quit.cpp
  A engines/titanic/pet_control/pet_quit.h
  A engines/titanic/pet_control/pet_real_life.cpp
  A engines/titanic/pet_control/pet_real_life.h
  A engines/titanic/pet_control/pet_remote.cpp
  A engines/titanic/pet_control/pet_remote.h
  A engines/titanic/pet_control/pet_remote_glyphs.cpp
  A engines/titanic/pet_control/pet_remote_glyphs.h
  A engines/titanic/pet_control/pet_rooms.cpp
  A engines/titanic/pet_control/pet_rooms.h
  A engines/titanic/pet_control/pet_rooms_glyphs.cpp
  A engines/titanic/pet_control/pet_rooms_glyphs.h
  A engines/titanic/pet_control/pet_save.cpp
  A engines/titanic/pet_control/pet_save.h
  A engines/titanic/pet_control/pet_section.cpp
  A engines/titanic/pet_control/pet_section.h
  A engines/titanic/pet_control/pet_slider.cpp
  A engines/titanic/pet_control/pet_slider.h
  A engines/titanic/pet_control/pet_sound.cpp
  A engines/titanic/pet_control/pet_sound.h
  A engines/titanic/pet_control/pet_starfield.cpp
  A engines/titanic/pet_control/pet_starfield.h
  A engines/titanic/pet_control/pet_text.cpp
  A engines/titanic/pet_control/pet_text.h
  A engines/titanic/room_flags.cpp
  A engines/titanic/room_flags.h
  A engines/titanic/sound/auto_music_player.cpp
  A engines/titanic/sound/auto_music_player.h
  A engines/titanic/sound/auto_music_player_base.cpp
  A engines/titanic/sound/auto_music_player_base.h
  A engines/titanic/sound/auto_sound_player.cpp
  A engines/titanic/sound/auto_sound_player.h
  A engines/titanic/sound/auto_sound_player_adsr.cpp
  A engines/titanic/sound/auto_sound_player_adsr.h
  A engines/titanic/sound/background_sound_maker.cpp
  A engines/titanic/sound/background_sound_maker.h
  A engines/titanic/sound/bird_song.cpp
  A engines/titanic/sound/bird_song.h
  A engines/titanic/sound/dome_from_top_of_well.cpp
  A engines/titanic/sound/dome_from_top_of_well.h
  A engines/titanic/sound/enter_view_toggles_other_music.cpp
  A engines/titanic/sound/enter_view_toggles_other_music.h
  A engines/titanic/sound/gondolier_song.cpp
  A engines/titanic/sound/gondolier_song.h
  A engines/titanic/sound/music_handler.cpp
  A engines/titanic/sound/music_handler.h
  A engines/titanic/sound/music_player.cpp
  A engines/titanic/sound/music_player.h
  A engines/titanic/sound/music_room.cpp
  A engines/titanic/sound/music_room.h
  A engines/titanic/sound/music_wave.cpp
  A engines/titanic/sound/music_wave.h
  A engines/titanic/sound/node_auto_sound_player.cpp
  A engines/titanic/sound/node_auto_sound_player.h
  A engines/titanic/sound/proximity.cpp
  A engines/titanic/sound/proximity.h
  A engines/titanic/sound/qmixer.cpp
  A engines/titanic/sound/qmixer.h
  A engines/titanic/sound/restricted_auto_music_player.cpp
  A engines/titanic/sound/restricted_auto_music_player.h
  A engines/titanic/sound/room_auto_sound_player.cpp
  A engines/titanic/sound/room_auto_sound_player.h
  A engines/titanic/sound/room_trigger_auto_music_player.cpp
  A engines/titanic/sound/room_trigger_auto_music_player.h
  A engines/titanic/sound/season_noises.cpp
  A engines/titanic/sound/season_noises.h
  A engines/titanic/sound/seasonal_music_player.cpp
  A engines/titanic/sound/seasonal_music_player.h
  A engines/titanic/sound/sound.cpp
  A engines/titanic/sound/sound.h
  A engines/titanic/sound/sound_manager.cpp
  A engines/titanic/sound/sound_manager.h
  A engines/titanic/sound/titania_speech.cpp
  A engines/titanic/sound/titania_speech.h
  A engines/titanic/sound/trigger_auto_music_player.cpp
  A engines/titanic/sound/trigger_auto_music_player.h
  A engines/titanic/sound/view_auto_sound_player.cpp
  A engines/titanic/sound/view_auto_sound_player.h
  A engines/titanic/sound/view_toggles_other_music.cpp
  A engines/titanic/sound/view_toggles_other_music.h
  A engines/titanic/sound/water_lapping_sounds.cpp
  A engines/titanic/sound/water_lapping_sounds.h
  A engines/titanic/sound/wave_file.cpp
  A engines/titanic/sound/wave_file.h
  A engines/titanic/star_control/base_star.cpp
  A engines/titanic/star_control/base_star.h
  A engines/titanic/star_control/dmatrix.cpp
  A engines/titanic/star_control/dmatrix.h
  A engines/titanic/star_control/dvector.cpp
  A engines/titanic/star_control/dvector.h
  A engines/titanic/star_control/error_code.h
  A engines/titanic/star_control/fmatrix.cpp
  A engines/titanic/star_control/fmatrix.h
  A engines/titanic/star_control/fpoint.cpp
  A engines/titanic/star_control/fpoint.h
  A engines/titanic/star_control/fvector.cpp
  A engines/titanic/star_control/fvector.h
  A engines/titanic/star_control/star_control.cpp
  A engines/titanic/star_control/star_control.h
  A engines/titanic/star_control/star_control_sub12.cpp
  A engines/titanic/star_control/star_control_sub12.h
  A engines/titanic/star_control/star_control_sub13.cpp
  A engines/titanic/star_control/star_control_sub13.h
  A engines/titanic/star_control/star_control_sub2.cpp
  A engines/titanic/star_control/star_control_sub2.h
  A engines/titanic/star_control/star_control_sub20.cpp
  A engines/titanic/star_control/star_control_sub20.h
  A engines/titanic/star_control/star_control_sub21.cpp
  A engines/titanic/star_control/star_control_sub21.h
  A engines/titanic/star_control/star_control_sub22.cpp
  A engines/titanic/star_control/star_control_sub22.h
  A engines/titanic/star_control/star_control_sub23.cpp
  A engines/titanic/star_control/star_control_sub23.h
  A engines/titanic/star_control/star_control_sub24.cpp
  A engines/titanic/star_control/star_control_sub24.h
  A engines/titanic/star_control/star_control_sub25.cpp
  A engines/titanic/star_control/star_control_sub25.h
  A engines/titanic/star_control/star_control_sub26.cpp
  A engines/titanic/star_control/star_control_sub26.h
  A engines/titanic/star_control/star_control_sub27.cpp
  A engines/titanic/star_control/star_control_sub27.h
  A engines/titanic/star_control/star_control_sub4.cpp
  A engines/titanic/star_control/star_control_sub4.h
  A engines/titanic/star_control/star_control_sub5.cpp
  A engines/titanic/star_control/star_control_sub5.h
  A engines/titanic/star_control/star_control_sub6.cpp
  A engines/titanic/star_control/star_control_sub6.h
  A engines/titanic/star_control/star_control_sub7.cpp
  A engines/titanic/star_control/star_control_sub7.h
  A engines/titanic/star_control/star_control_sub8.cpp
  A engines/titanic/star_control/star_control_sub8.h
  A engines/titanic/star_control/star_field.cpp
  A engines/titanic/star_control/star_field.h
  A engines/titanic/star_control/star_points1.cpp
  A engines/titanic/star_control/star_points1.h
  A engines/titanic/star_control/star_points2.cpp
  A engines/titanic/star_control/star_points2.h
  A engines/titanic/star_control/star_view.cpp
  A engines/titanic/star_control/star_view.h
  A engines/titanic/star_control/surface_area.cpp
  A engines/titanic/star_control/surface_area.h
  A engines/titanic/star_control/surface_fader.cpp
  A engines/titanic/star_control/surface_fader.h
  A engines/titanic/star_control/surface_fader_base.cpp
  A engines/titanic/star_control/surface_fader_base.h
  A engines/titanic/support/avi_surface.cpp
  A engines/titanic/support/avi_surface.h
  A engines/titanic/support/credit_text.cpp
  A engines/titanic/support/credit_text.h
  A engines/titanic/support/direct_draw.cpp
  A engines/titanic/support/direct_draw.h
  A engines/titanic/support/direct_draw_surface.cpp
  A engines/titanic/support/direct_draw_surface.h
  A engines/titanic/support/exe_resources.cpp
  A engines/titanic/support/exe_resources.h
  A engines/titanic/support/files_manager.cpp
  A engines/titanic/support/files_manager.h
  A engines/titanic/support/font.cpp
  A engines/titanic/support/font.h
  A engines/titanic/support/image.cpp
  A engines/titanic/support/image.h
  A engines/titanic/support/image_decoders.cpp
  A engines/titanic/support/image_decoders.h
  A engines/titanic/support/mouse_cursor.cpp
  A engines/titanic/support/mouse_cursor.h
  A engines/titanic/support/movie.cpp
  A engines/titanic/support/movie.h
  A engines/titanic/support/movie_clip.cpp
  A engines/titanic/support/movie_clip.h
  A engines/titanic/support/movie_event.cpp
  A engines/titanic/support/movie_event.h
  A engines/titanic/support/movie_manager.cpp
  A engines/titanic/support/movie_manager.h
  A engines/titanic/support/movie_range_info.cpp
  A engines/titanic/support/movie_range_info.h
  A engines/titanic/support/rect.cpp
  A engines/titanic/support/rect.h
  A engines/titanic/support/screen_manager.cpp
  A engines/titanic/support/screen_manager.h
  A engines/titanic/support/simple_file.cpp
  A engines/titanic/support/simple_file.h
  A engines/titanic/support/string.cpp
  A engines/titanic/support/string.h
  A engines/titanic/support/string_parser.cpp
  A engines/titanic/support/string_parser.h
  A engines/titanic/support/text_cursor.cpp
  A engines/titanic/support/text_cursor.h
  A engines/titanic/support/time_event_info.cpp
  A engines/titanic/support/time_event_info.h
  A engines/titanic/support/video_surface.cpp
  A engines/titanic/support/video_surface.h
  A engines/titanic/titanic.cpp
  A engines/titanic/titanic.h
  A engines/titanic/true_talk/barbot_script.cpp
  A engines/titanic/true_talk/barbot_script.h
  A engines/titanic/true_talk/bellbot_script.cpp
  A engines/titanic/true_talk/bellbot_script.h
  A engines/titanic/true_talk/deskbot_script.cpp
  A engines/titanic/true_talk/deskbot_script.h
  A engines/titanic/true_talk/dialogue_file.cpp
  A engines/titanic/true_talk/dialogue_file.h
  A engines/titanic/true_talk/doorbot_script.cpp
  A engines/titanic/true_talk/doorbot_script.h
  A engines/titanic/true_talk/liftbot_script.cpp
  A engines/titanic/true_talk/liftbot_script.h
  A engines/titanic/true_talk/maitred_script.cpp
  A engines/titanic/true_talk/maitred_script.h
  A engines/titanic/true_talk/parrot_script.cpp
  A engines/titanic/true_talk/parrot_script.h
  A engines/titanic/true_talk/script_handler.cpp
  A engines/titanic/true_talk/script_handler.h
  A engines/titanic/true_talk/script_support.cpp
  A engines/titanic/true_talk/script_support.h
  A engines/titanic/true_talk/succubus_script.cpp
  A engines/titanic/true_talk/succubus_script.h
  A engines/titanic/true_talk/title_engine.cpp
  A engines/titanic/true_talk/title_engine.h
  A engines/titanic/true_talk/true_talk_manager.cpp
  A engines/titanic/true_talk/true_talk_manager.h
  A engines/titanic/true_talk/tt_action.cpp
  A engines/titanic/true_talk/tt_action.h
  A engines/titanic/true_talk/tt_adj.cpp
  A engines/titanic/true_talk/tt_adj.h
  A engines/titanic/true_talk/tt_concept.cpp
  A engines/titanic/true_talk/tt_concept.h
  A engines/titanic/true_talk/tt_concept_node.cpp
  A engines/titanic/true_talk/tt_concept_node.h
  A engines/titanic/true_talk/tt_hist.cpp
  A engines/titanic/true_talk/tt_hist.h
  A engines/titanic/true_talk/tt_major_word.cpp
  A engines/titanic/true_talk/tt_major_word.h
  A engines/titanic/true_talk/tt_node.cpp
  A engines/titanic/true_talk/tt_node.h
  A engines/titanic/true_talk/tt_npc_script.cpp
  A engines/titanic/true_talk/tt_npc_script.h
  A engines/titanic/true_talk/tt_parser.cpp
  A engines/titanic/true_talk/tt_parser.h
  A engines/titanic/true_talk/tt_picture.cpp
  A engines/titanic/true_talk/tt_picture.h
  A engines/titanic/true_talk/tt_pronoun.cpp
  A engines/titanic/true_talk/tt_pronoun.h
  A engines/titanic/true_talk/tt_quotes.cpp
  A engines/titanic/true_talk/tt_quotes.h
  A engines/titanic/true_talk/tt_quotes_tree.cpp
  A engines/titanic/true_talk/tt_quotes_tree.h
  A engines/titanic/true_talk/tt_response.cpp
  A engines/titanic/true_talk/tt_response.h
  A engines/titanic/true_talk/tt_room_script.cpp
  A engines/titanic/true_talk/tt_room_script.h
  A engines/titanic/true_talk/tt_script_base.cpp
  A engines/titanic/true_talk/tt_script_base.h
  A engines/titanic/true_talk/tt_scripts.cpp
  A engines/titanic/true_talk/tt_scripts.h
  A engines/titanic/true_talk/tt_sentence.cpp
  A engines/titanic/true_talk/tt_sentence.h
  A engines/titanic/true_talk/tt_sentence_node.cpp
  A engines/titanic/true_talk/tt_sentence_node.h
  A engines/titanic/true_talk/tt_string.cpp
  A engines/titanic/true_talk/tt_string.h
  A engines/titanic/true_talk/tt_string_node.cpp
  A engines/titanic/true_talk/tt_string_node.h
  A engines/titanic/true_talk/tt_synonym.cpp
  A engines/titanic/true_talk/tt_synonym.h
  A engines/titanic/true_talk/tt_talker.cpp
  A engines/titanic/true_talk/tt_talker.h
  A engines/titanic/true_talk/tt_title_script.cpp
  A engines/titanic/true_talk/tt_title_script.h
  A engines/titanic/true_talk/tt_vocab.cpp
  A engines/titanic/true_talk/tt_vocab.h
  A engines/titanic/true_talk/tt_word.cpp
  A engines/titanic/true_talk/tt_word.h
  A engines/wage/saveload.cpp
  A graphics/macgui/macmenu.cpp
  A graphics/macgui/macmenu.h
  A graphics/macgui/macwindow.cpp
  A graphics/macgui/macwindow.h
  A graphics/macgui/macwindowborder.cpp
  A graphics/macgui/macwindowborder.h
  A graphics/macgui/macwindowmanager.cpp
  A graphics/macgui/macwindowmanager.h
  A snapcraft.yaml
  R doc/de/Liesmich
  R doc/de/Neues
  R engines/fullpipe/mgm.cpp
  R engines/fullpipe/mgm.h
  R engines/wage/macmenu.cpp
  R engines/wage/macmenu.h
  R engines/wage/macwindow.cpp
  R engines/wage/macwindow.h
  R engines/wage/macwindowmanager.cpp
  R engines/wage/macwindowmanager.h
    .gitignore
    NEWS
    audio/decoders/qdm2.cpp
    audio/decoders/wave.h
    backends/graphics/opengl/opengl-sys.h
    backends/platform/dc/vmsave.cpp
    backends/platform/n64/framfs_save_manager.h
    backends/platform/n64/pakfs_save_manager.h
    backends/platform/sdl/posix/posix.cpp
    backends/platform/sdl/posix/posix.h
    backends/platform/sdl/sdl.cpp
    backends/platform/sdl/sdl.h
    base/commandLine.cpp
    base/main.cpp
    base/plugins.h
    common/debug.cpp
    common/debug.h
    common/file.cpp
    common/file.h
    common/gui_options.h
    common/memstream.h
    common/recorderfile.cpp
    common/scummsys.h
    common/stream.cpp
    common/stream.h
    common/system.cpp
    common/system.h
    common/util.cpp
    common/util.h
    common/zlib.cpp
    configure
    devtools/create_kyradat/create_kyradat.cpp
    devtools/create_kyradat/resources/eob1_dos_italian.h
    devtools/create_project/create_project.cpp
    devtools/create_project/create_project.h
    devtools/create_project/xcode.cpp
    devtools/create_project/xcode/create_project.xcodeproj/project.pbxproj
    devtools/scumm-md5.txt
    dists/debian/control
    dists/engine-data/kyra.dat
    dists/msvc10/create_msvc10.bat
    dists/msvc11/create_msvc11.bat
    dists/msvc12/create_msvc12.bat
    dists/msvc9/create_msvc9.bat
    dists/win32/ScummVM.iss
    engines/access/access.cpp
    engines/adl/adl.cpp
    engines/adl/adl.h
    engines/adl/adl_v2.cpp
    engines/adl/adl_v2.h
    engines/adl/adl_v3.cpp
    engines/adl/adl_v3.h
    engines/adl/detection.cpp
    engines/adl/detection.h
    engines/adl/disk.cpp
    engines/adl/disk.h
    engines/adl/display.cpp
    engines/adl/display.h
    engines/adl/hires1.cpp
    engines/adl/hires2.cpp
    engines/adl/hires6.cpp
    engines/adl/hires6.h
    engines/adl/module.mk
    engines/cine/cine.cpp
    engines/draci/draci.cpp
    engines/dreamweb/dreamweb.cpp
    engines/fullpipe/behavior.cpp
    engines/fullpipe/fullpipe.cpp
    engines/fullpipe/fullpipe.h
    engines/fullpipe/gameloader.cpp
    engines/fullpipe/gfx.cpp
    engines/fullpipe/interaction.cpp
    engines/fullpipe/inventory.cpp
    engines/fullpipe/lift.cpp
    engines/fullpipe/messagehandlers.cpp
    engines/fullpipe/messages.cpp
    engines/fullpipe/messages.h
    engines/fullpipe/module.mk
    engines/fullpipe/motion.cpp
    engines/fullpipe/motion.h
    engines/fullpipe/ngiarchive.cpp
    engines/fullpipe/scene.cpp
    engines/fullpipe/scenes.cpp
    engines/fullpipe/scenes.h
    engines/fullpipe/scenes/scene04.cpp
    engines/fullpipe/scenes/scene11.cpp
    engines/fullpipe/scenes/scene22.cpp
    engines/fullpipe/scenes/scene27.cpp
    engines/fullpipe/scenes/scene29.cpp
    engines/fullpipe/sound.cpp
    engines/fullpipe/stateloader.cpp
    engines/fullpipe/statics.cpp
    engines/fullpipe/utils.cpp
    engines/gnap/gnap.cpp
    engines/gnap/scenes/group4.cpp
    engines/gob/gob.cpp
    engines/groovie/groovie.cpp
    engines/kyra/staticres.cpp
    engines/mads/mads.cpp
    engines/mads/screen.cpp
    engines/mohawk/console.cpp
    engines/mohawk/cstime.cpp
    engines/mohawk/cstime.h
    engines/mohawk/dialogs.cpp
    engines/mohawk/dialogs.h
    engines/mohawk/livingbooks.cpp
    engines/mohawk/livingbooks.h
    engines/mohawk/module.mk
    engines/mohawk/mohawk.cpp
    engines/mohawk/mohawk.h
    engines/mohawk/myst.cpp
    engines/mohawk/myst.h
    engines/mohawk/riven.cpp
    engines/mohawk/riven.h
    engines/mohawk/riven_external.cpp
    engines/mohawk/riven_graphics.cpp
    engines/mohawk/riven_scripts.cpp
    engines/mohawk/sound.cpp
    engines/mohawk/sound.h
    engines/mortevielle/mortevielle.cpp
    engines/sci/console.cpp
    engines/sci/detection.cpp
    engines/sci/detection_tables.h
    engines/sci/engine/features.cpp
    engines/sci/engine/features.h
    engines/sci/engine/file.cpp
    engines/sci/engine/gc.cpp
    engines/sci/engine/kernel.cpp
    engines/sci/engine/kernel.h
    engines/sci/engine/kernel_tables.h
    engines/sci/engine/kevent.cpp
    engines/sci/engine/kfile.cpp
    engines/sci/engine/kgraphics.cpp
    engines/sci/engine/kgraphics32.cpp
    engines/sci/engine/klists.cpp
    engines/sci/engine/kmisc.cpp
    engines/sci/engine/kvideo.cpp
    engines/sci/engine/savegame.cpp
    engines/sci/engine/savegame.h
    engines/sci/engine/seg_manager.cpp
    engines/sci/engine/seg_manager.h
    engines/sci/engine/segment.cpp
    engines/sci/engine/segment.h
    engines/sci/engine/state.cpp
    engines/sci/engine/state.h
    engines/sci/engine/vm.cpp
    engines/sci/engine/workarounds.cpp
    engines/sci/engine/workarounds.h
    engines/sci/event.cpp
    engines/sci/graphics/cache.cpp
    engines/sci/graphics/celobj32.cpp
    engines/sci/graphics/celobj32.h
    engines/sci/graphics/compare.cpp
    engines/sci/graphics/compare.h
    engines/sci/graphics/controls32.cpp
    engines/sci/graphics/controls32.h
    engines/sci/graphics/coordadjuster.cpp
    engines/sci/graphics/coordadjuster.h
    engines/sci/graphics/cursor.cpp
    engines/sci/graphics/cursor.h
    engines/sci/graphics/frameout.cpp
    engines/sci/graphics/frameout.h
    engines/sci/graphics/helpers.h
    engines/sci/graphics/paint16.cpp
    engines/sci/graphics/paint16.h
    engines/sci/graphics/paint32.cpp
    engines/sci/graphics/paint32.h
    engines/sci/graphics/palette32.cpp
    engines/sci/graphics/picture.cpp
    engines/sci/graphics/picture.h
    engines/sci/graphics/plane32.cpp
    engines/sci/graphics/plane32.h
    engines/sci/graphics/remap32.h
    engines/sci/graphics/screen.cpp
    engines/sci/graphics/screen_item32.cpp
    engines/sci/graphics/screen_item32.h
    engines/sci/graphics/text16.cpp
    engines/sci/graphics/text32.cpp
    engines/sci/graphics/text32.h
    engines/sci/graphics/video32.cpp
    engines/sci/graphics/video32.h
    engines/sci/graphics/view.cpp
    engines/sci/graphics/view.h
    engines/sci/module.mk
    engines/sci/resource.cpp
    engines/sci/resource.h
    engines/sci/resource_audio.cpp
    engines/sci/resource_intern.h
    engines/sci/sci.cpp
    engines/sci/sci.h
    engines/sci/sound/audio32.cpp
    engines/sci/sound/audio32.h
    engines/sci/sound/decoders/sol.cpp
    engines/sci/video/robot_decoder.cpp
    engines/sci/video/robot_decoder.h
    engines/scumm/scumm-md5.h
    engines/sherlock/screen.cpp
    engines/sherlock/sherlock.cpp
    engines/sherlock/surface.cpp
    engines/sherlock/surface.h
    engines/tinsel/tinsel.cpp
    engines/wage/design.cpp
    engines/wage/design.h
    engines/wage/detection.cpp
    engines/wage/dialog.cpp
    engines/wage/entities.cpp
    engines/wage/entities.h
    engines/wage/gui-console.cpp
    engines/wage/gui.cpp
    engines/wage/gui.h
    engines/wage/module.mk
    engines/wage/wage.cpp
    engines/wage/wage.h
    engines/wage/world.cpp
    engines/wage/world.h
    engines/wintermute/base/base_game.cpp
    engines/wintermute/base/base_game.h
    engines/wintermute/base/base_script_holder.cpp
    engines/wintermute/base/scriptables/script.cpp
    engines/wintermute/base/scriptables/script_engine.cpp
    engines/wintermute/debugger.h
    graphics/module.mk
    graphics/nine_patch.cpp
    graphics/nine_patch.h
    graphics/primitives.cpp
    image/tga.h
    ports.mk
    test/module.mk
    video/avi_decoder.cpp
    video/avi_decoder.h





Commit: 552f0cce8e5af656568b4cac2a2fd665f2e8809d
    https://github.com/scummvm/scummvm/commit/552f0cce8e5af656568b4cac2a2fd665f2e8809d
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2016-08-27T15:19:25-04:00

Commit Message:
XEEN: Move game cutscene methods into their own classes

Changed paths:
  A engines/xeen/worldofxeen/clouds_cutscenes.cpp
  A engines/xeen/worldofxeen/clouds_cutscenes.h
  A engines/xeen/worldofxeen/darkside_cutscenes.cpp
  A engines/xeen/worldofxeen/darkside_cutscenes.h
  A engines/xeen/worldofxeen/worldofxeen.cpp
  A engines/xeen/worldofxeen/worldofxeen.h
  R engines/xeen/worldofxeen/clouds_ending.cpp
  R engines/xeen/worldofxeen/clouds_ending.h
  R engines/xeen/worldofxeen/clouds_intro.cpp
  R engines/xeen/worldofxeen/clouds_intro.h
  R engines/xeen/worldofxeen/darkside_ending.cpp
  R engines/xeen/worldofxeen/darkside_ending.h
  R engines/xeen/worldofxeen/darkside_intro.cpp
  R engines/xeen/worldofxeen/darkside_intro.h
  R engines/xeen/worldofxeen/worldofxeen_game.cpp
  R engines/xeen/worldofxeen/worldofxeen_game.h
    engines/xeen/detection.cpp
    engines/xeen/module.mk



diff --git a/engines/xeen/detection.cpp b/engines/xeen/detection.cpp
index 64b28bf..e5b137c 100644
--- a/engines/xeen/detection.cpp
+++ b/engines/xeen/detection.cpp
@@ -21,7 +21,7 @@
  */
 
 #include "xeen/xeen.h"
-#include "xeen/worldofxeen/worldofxeen_game.h"
+#include "xeen/worldofxeen/worldofxeen.h"
 
 #include "base/plugins.h"
 #include "common/savefile.h"
diff --git a/engines/xeen/module.mk b/engines/xeen/module.mk
index 58a2f1a..de4df4a 100644
--- a/engines/xeen/module.mk
+++ b/engines/xeen/module.mk
@@ -1,11 +1,9 @@
 MODULE := engines/xeen
 
 MODULE_OBJS := \
-	worldofxeen/clouds_ending.o \
-	worldofxeen/clouds_intro.o \
-	worldofxeen/darkside_ending.o \
-	worldofxeen/darkside_intro.o \
-	worldofxeen/worldofxeen_game.o \
+	worldofxeen/clouds_cutscenes.o \
+	worldofxeen/darkside_cutscenes.o \
+	worldofxeen/worldofxeen.o \
 	character.o \
 	combat.o \
 	debugger.o \
diff --git a/engines/xeen/worldofxeen/clouds_cutscenes.cpp b/engines/xeen/worldofxeen/clouds_cutscenes.cpp
new file mode 100644
index 0000000..1d578bd
--- /dev/null
+++ b/engines/xeen/worldofxeen/clouds_cutscenes.cpp
@@ -0,0 +1,43 @@
+/* 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 "xeen/worldofxeen/clouds_cutscenes.h"
+#include "xeen/sound.h"
+
+namespace Xeen {
+
+bool CloudsCutscenes::showCloudsTitle() {
+	// TODO
+	return true;
+}
+
+bool CloudsCutscenes::showCloudsIntro() {
+	// TODO
+	return true;
+}
+
+bool CloudsCutscenes::showCloudsEnding() {
+	// TODO
+	return true;
+}
+
+} // End of namespace Xeen
diff --git a/engines/xeen/worldofxeen/clouds_cutscenes.h b/engines/xeen/worldofxeen/clouds_cutscenes.h
new file mode 100644
index 0000000..2c2ed60
--- /dev/null
+++ b/engines/xeen/worldofxeen/clouds_cutscenes.h
@@ -0,0 +1,55 @@
+/* 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_WORLDOFXEEN_CLOUDS_CUTSCENES_H
+#define XEEN_WORLDOFXEEN_CLOUDS_CUTSCENES_H
+
+#include "xeen/xeen.h"
+
+namespace Xeen {
+
+class XeenEngine;
+
+class CloudsCutscenes {
+private:
+	XeenEngine *_vm;
+public:
+	CloudsCutscenes(XeenEngine *vm) : _vm(vm) {}
+
+	/**
+	 * Shows the Clouds of Xeen title screen
+	 */
+	bool showCloudsTitle();
+
+	/**
+	 * Shows the Clouds of Xeen intro sequence
+	 */
+	bool showCloudsIntro();
+
+	/**
+	 * Shows the Clouds of Xeen ending sequence
+	 */
+	bool showCloudsEnding();
+};
+} // End of namespace Xeen
+
+#endif /* XEEN_WORLDOFXEEN_CLOUDS_CUTSCENES_H */
diff --git a/engines/xeen/worldofxeen/clouds_ending.cpp b/engines/xeen/worldofxeen/clouds_ending.cpp
deleted file mode 100644
index 75c8755..0000000
--- a/engines/xeen/worldofxeen/clouds_ending.cpp
+++ /dev/null
@@ -1,36 +0,0 @@
-/* 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 "xeen/worldofxeen/clouds_ending.h"
-#include "xeen/sound.h"
-
-namespace Xeen {
-
-bool showCloudsEnding(XeenEngine &vm) {
-	EventsManager &events = *vm._events;
-	Screen &screen = *vm._screen;
-	SoundManager &sound = *vm._sound;
-
-	return true;
-}
-
-} // End of namespace Xeen
diff --git a/engines/xeen/worldofxeen/clouds_ending.h b/engines/xeen/worldofxeen/clouds_ending.h
deleted file mode 100644
index fc7945f..0000000
--- a/engines/xeen/worldofxeen/clouds_ending.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/* 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_CLOUDS_ENDING_H
-#define XEEN_CLOUDS_ENDING_H
-
-#include "xeen/xeen.h"
-
-namespace Xeen {
-
-bool showCloudsEnding(XeenEngine &vm);
-
-} // End of namespace Xeen
-
-#endif /* XEEN_CLOUDS_ENDING_H */
diff --git a/engines/xeen/worldofxeen/clouds_intro.cpp b/engines/xeen/worldofxeen/clouds_intro.cpp
deleted file mode 100644
index 1ea6765..0000000
--- a/engines/xeen/worldofxeen/clouds_intro.cpp
+++ /dev/null
@@ -1,36 +0,0 @@
-/* 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 "xeen/worldofxeen/clouds_intro.h"
-#include "xeen/sound.h"
-
-namespace Xeen {
-
-bool showCloudsTitle(XeenEngine &vm) {
-	return true;
-}
-
-bool showCloudsIntro(XeenEngine &vm) {
-	return true;
-}
-
-} // End of namespace Xeen
diff --git a/engines/xeen/worldofxeen/clouds_intro.h b/engines/xeen/worldofxeen/clouds_intro.h
deleted file mode 100644
index 0bd5633..0000000
--- a/engines/xeen/worldofxeen/clouds_intro.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/* 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_CLOUDS_INTRO_H
-#define XEEN_CLOUDS_INTRO_H
-
-#include "xeen/xeen.h"
-
-namespace Xeen {
-
-bool showCloudsTitle(XeenEngine &vm);
-
-bool showCloudsIntro(XeenEngine &vm);
-
-} // End of namespace Xeen
-
-#endif /* XEEN_CLOUDS_INTRO_H */
diff --git a/engines/xeen/worldofxeen/darkside_cutscenes.cpp b/engines/xeen/worldofxeen/darkside_cutscenes.cpp
new file mode 100644
index 0000000..90efef1
--- /dev/null
+++ b/engines/xeen/worldofxeen/darkside_cutscenes.cpp
@@ -0,0 +1,241 @@
+/* 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 "xeen/worldofxeen/darkside_cutscenes.h"
+#include "xeen/worldofxeen/worldofxeen.h"
+#include "xeen/sound.h"
+#include "xeen/xeen.h"
+
+namespace Xeen {
+
+bool DarkSideCutscenes::showDarkSideTitle() {
+	EventsManager &events = *_vm->_events;
+	Screen &screen = *_vm->_screen;
+	SoundManager &sound = *_vm->_sound;
+	
+	// TODO: Starting method, and sound
+	//sub_28F40
+	screen.loadPalette("dark.pal");
+	SpriteResource nwc[4] = {
+		SpriteResource("nwc1.int"), SpriteResource("nwc2.int"),
+		SpriteResource("nwc3.int"), SpriteResource("nwc4.int")
+	};
+	VOC voc[3];
+	voc[0].open("dragon1.voc");
+	voc[1].open("dragon2.voc");
+	voc[2].open("dragon3.voc");
+
+	// Load backgrounds
+	screen.loadBackground("nwc1.raw");
+	screen.loadPage(0);
+	screen.loadBackground("nwc2.raw");
+	screen.loadPage(1);
+
+	// Draw the screen and fade it in
+	screen.horizMerge(0);
+	screen.draw();
+	screen.fadeIn(4);
+
+	// Initial loop for dragon roaring
+	int nwcIndex = 0, nwcFrame = 0;
+	for (int idx = 0; idx < 55 && !_vm->shouldQuit(); ++idx) {
+		// Render the next frame
+		events.updateGameCounter();
+		screen.vertMerge(0);
+		nwc[nwcIndex].draw(screen, nwcFrame);
+		screen.draw();
+
+		switch (idx) {
+		case 17:
+			sound.playSound(voc[0]);
+			break;
+		case 34:
+		case 44:
+			++nwcIndex;
+			nwcFrame = 0;
+			break;
+		case 35:
+			sound.playSound(voc[1]);
+			break;
+		default:
+			++nwcFrame;
+		}
+
+		if (events.wait(2, true))
+			return false;
+	}
+
+	// Loop for dragon using flyspray
+	for (int idx = 0; idx < 42 && !_vm->shouldQuit(); ++idx) {
+		events.updateGameCounter();
+		screen.vertMerge(SCREEN_HEIGHT);
+		nwc[3].draw(screen, idx);
+		screen.draw();
+
+		switch (idx) {
+		case 3:
+			sound.startMusic(40);
+			break;
+		case 11:
+			sound.startMusic(0);
+		case 27:
+		case 30:
+			sound.startMusic(3);
+			break;
+		case 31:
+			sound.proc2(voc[2]);
+			break;
+		case 33:
+			sound.startMusic(2);
+			break;
+		default:
+			break;
+		}
+
+		if (events.wait(2, true))
+			return false;
+	}
+
+	// Pause for a bit
+	if (events.wait(10, true))
+		return false;
+
+	voc[0].stop();
+	voc[1].stop();
+	voc[2].stop();
+	sound.stopMusic(95);
+
+	screen.loadBackground("jvc.raw");
+	screen.fadeOut(8);
+	screen.draw();
+	screen.fadeIn(4);
+
+	events.updateGameCounter();
+	events.wait(60, true);
+	return true;
+}
+
+bool DarkSideCutscenes::showDarkSideIntro() {
+	EventsManager &events = *_vm->_events;
+	Screen &screen = *_vm->_screen;
+	SoundManager &sound = *_vm->_sound;
+	const int XLIST1[] = {
+		0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 58, 60, 62
+	};
+	const int YLIST1[] = {
+		0, 5, 10, 15, 20, 25, 30, 35, 40, 40, 39, 37, 35, 33, 31
+	};
+	const int XLIST2[] = {
+		160, 155, 150, 145, 140, 135, 130, 125, 120, 115, 110, 105, 98, 90, 82
+	};
+
+	screen.fadeOut(8);
+	screen.loadBackground("pyramid2.raw");
+	screen.loadPage(0);
+	screen.loadPage(1);
+	screen.loadBackground("pyramid3.raw");
+	screen.saveBackground(1);
+
+	SpriteResource sprites[3] = {
+		SpriteResource("title.int"), SpriteResource("pyratop.int"), SpriteResource("pyramid.int")
+	};
+	Common::File voc[2];
+	voc[0].open("pharoh1a.voc");
+	voc[1].open("pharoh1b.voc");
+
+	screen.vertMerge(SCREEN_HEIGHT);
+	screen.loadPage(0);
+	screen.loadPage(1);
+
+	// Show Might and Magic Darkside of Xeen title, and gradualy scroll
+	// the background vertically down to show the Pharoah's base
+	int yp = 0;
+	int frameNum = 0;
+	int idx1 = 0;
+	bool skipElapsed = false;
+	uint32 timeExpired = 0;
+	bool fadeFlag = true;
+
+	for (int yCtr = SCREEN_HEIGHT; yCtr > 0; ) {
+		events.updateGameCounter();
+		screen.vertMerge(yp);
+
+		sprites[0].draw(screen, 0);
+		if (frameNum)
+			sprites[0].draw(screen, frameNum);
+
+		idx1 = (idx1 + 1) % 4;
+		if (!idx1)
+			frameNum = (frameNum + 1) % 10;
+
+		screen.draw();
+		if (!skipElapsed) {
+			timeExpired = MAX((int)events.timeElapsed() - 1, 1);
+			skipElapsed = true;
+		}
+
+		yCtr -= timeExpired;
+		yp = MIN(yp + timeExpired, (uint)200);
+		 
+		if (events.wait(1, true))
+			return false;
+
+		if (fadeFlag) {
+			screen.fadeIn(4);
+			fadeFlag = false;
+		}
+	}
+
+	screen.vertMerge(SCREEN_HEIGHT);
+	screen.saveBackground(1);
+	screen.draw();
+	screen.freePages();
+
+	events.updateGameCounter();
+	events.wait(30, true);
+
+	// Zoom into the Pharoah's base closeup view
+	for (int idx = 14; idx >= 0; --idx) {
+		events.updateGameCounter();
+		sprites[1].draw(screen, 0, Common::Point(XLIST1[idx], YLIST1[idx]));
+		sprites[1].draw(screen, 1, Common::Point(XLIST2[idx], YLIST1[idx]));
+		screen.draw();
+
+		if (idx == 2)
+			sound.stopMusic(48);
+		if (events.wait(2, true))
+			return false;
+	}
+
+	// TODO: More
+	sound.playSong(voc[0]);
+	sound.playSong(voc[1]);
+
+	return true;
+}
+
+bool DarkSideCutscenes::showDarkSideEnding() {
+	// TODO
+	return true;
+}
+
+} // End of namespace Xeen
diff --git a/engines/xeen/worldofxeen/darkside_cutscenes.h b/engines/xeen/worldofxeen/darkside_cutscenes.h
new file mode 100644
index 0000000..1b78e3e
--- /dev/null
+++ b/engines/xeen/worldofxeen/darkside_cutscenes.h
@@ -0,0 +1,54 @@
+/* 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_WORLDOFXEEN_DARKSIDE_CUTSCENES_H
+#define XEEN_WORLDOFXEEN_DARKSIDE_CUTSCENES_H
+
+namespace Xeen {
+
+class XeenEngine;
+
+class DarkSideCutscenes {
+private:
+	XeenEngine *_vm;
+public:
+	DarkSideCutscenes(XeenEngine *vm) : _vm(vm) {}
+
+	/**
+	 * Shows the Dark Side of Xeen title screen
+	 */
+	bool showDarkSideTitle();
+
+	/**
+	 * Shows the Dark Side of Xeen intro sequence
+	 */
+	bool showDarkSideIntro();
+
+	/**
+	 * Shows the Dark Side of Xeen ending sequence
+	 */
+	bool showDarkSideEnding();
+};
+
+} // End of namespace Xeen
+
+#endif /* XEEN_WORLDOFXEEN_DARKSIDE_CUTSCENES_H */
diff --git a/engines/xeen/worldofxeen/darkside_ending.cpp b/engines/xeen/worldofxeen/darkside_ending.cpp
deleted file mode 100644
index 0a8211f..0000000
--- a/engines/xeen/worldofxeen/darkside_ending.cpp
+++ /dev/null
@@ -1,32 +0,0 @@
-/* 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 "xeen/worldofxeen/darkside_ending.h"
-#include "xeen/sound.h"
-
-namespace Xeen {
-
-bool showDarkSideEnding(XeenEngine &vm) {
-	return true;
-}
-
-} // End of namespace Xeen
diff --git a/engines/xeen/worldofxeen/darkside_ending.h b/engines/xeen/worldofxeen/darkside_ending.h
deleted file mode 100644
index 49dcf2d..0000000
--- a/engines/xeen/worldofxeen/darkside_ending.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/* 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_DARKSIDE_ENDING_H
-#define XEEN_DARKSIDE_ENDING_H
-
-#include "xeen/xeen.h"
-
-namespace Xeen {
-
-bool showDarkSideEnding(XeenEngine &vm);
-
-} // End of namespace Xeen
-
-#endif /* XEEN_DARKSIDE_ENDING_H */
diff --git a/engines/xeen/worldofxeen/darkside_intro.cpp b/engines/xeen/worldofxeen/darkside_intro.cpp
deleted file mode 100644
index 7ea0328..0000000
--- a/engines/xeen/worldofxeen/darkside_intro.cpp
+++ /dev/null
@@ -1,234 +0,0 @@
-/* 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 "xeen/worldofxeen/darkside_intro.h"
-#include "xeen/sound.h"
-
-namespace Xeen {
-
-bool showDarkSideTitle(XeenEngine &vm) {
-	EventsManager &events = *vm._events;
-	Screen &screen = *vm._screen;
-	SoundManager &sound = *vm._sound;
-	
-	// TODO: Starting method, and sound
-	//sub_28F40
-	screen.loadPalette("dark.pal");
-	SpriteResource nwc[4] = {
-		SpriteResource("nwc1.int"), SpriteResource("nwc2.int"),
-		SpriteResource("nwc3.int"), SpriteResource("nwc4.int")
-	};
-	VOC voc[3];
-	voc[0].open("dragon1.voc");
-	voc[1].open("dragon2.voc");
-	voc[2].open("dragon3.voc");
-
-	// Load backgrounds
-	screen.loadBackground("nwc1.raw");
-	screen.loadPage(0);
-	screen.loadBackground("nwc2.raw");
-	screen.loadPage(1);
-
-	// Draw the screen and fade it in
-	screen.horizMerge(0);
-	screen.draw();
-	screen.fadeIn(4);
-
-	// Initial loop for dragon roaring
-	int nwcIndex = 0, nwcFrame = 0;
-	for (int idx = 0; idx < 55 && !vm.shouldQuit(); ++idx) {
-		// Render the next frame
-		events.updateGameCounter();
-		screen.vertMerge(0);
-		nwc[nwcIndex].draw(screen, nwcFrame);
-		screen.draw();
-
-		switch (idx) {
-		case 17:
-			sound.playSound(voc[0]);
-			break;
-		case 34:
-		case 44:
-			++nwcIndex;
-			nwcFrame = 0;
-			break;
-		case 35:
-			sound.playSound(voc[1]);
-			break;
-		default:
-			++nwcFrame;
-		}
-
-		if (events.wait(2, true))
-			return false;
-	}
-
-	// Loop for dragon using flyspray
-	for (int idx = 0; idx < 42 && !vm.shouldQuit(); ++idx) {
-		events.updateGameCounter();
-		screen.vertMerge(SCREEN_HEIGHT);
-		nwc[3].draw(screen, idx);
-		screen.draw();
-
-		switch (idx) {
-		case 3:
-			sound.startMusic(40);
-			break;
-		case 11:
-			sound.startMusic(0);
-		case 27:
-		case 30:
-			sound.startMusic(3);
-			break;
-		case 31:
-			sound.proc2(voc[2]);
-			break;
-		case 33:
-			sound.startMusic(2);
-			break;
-		default:
-			break;
-		}
-
-		if (events.wait(2, true))
-			return false;
-	}
-
-	// Pause for a bit
-	if (events.wait(10, true))
-		return false;
-
-	voc[0].stop();
-	voc[1].stop();
-	voc[2].stop();
-	sound.stopMusic(95);
-
-	screen.loadBackground("jvc.raw");
-	screen.fadeOut(8);
-	screen.draw();
-	screen.fadeIn(4);
-
-	events.updateGameCounter();
-	events.wait(60, true);
-	return true;
-}
-
-bool showDarkSideIntro(XeenEngine &vm) {
-	EventsManager &events = *vm._events;
-	Screen &screen = *vm._screen;
-	SoundManager &sound = *vm._sound;
-	const int XLIST1[] = {
-		0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 58, 60, 62
-	};
-	const int YLIST1[] = {
-		0, 5, 10, 15, 20, 25, 30, 35, 40, 40, 39, 37, 35, 33, 31
-	};
-	const int XLIST2[] = {
-		160, 155, 150, 145, 140, 135, 130, 125, 120, 115, 110, 105, 98, 90, 82
-	};
-
-	screen.fadeOut(8);
-	screen.loadBackground("pyramid2.raw");
-	screen.loadPage(0);
-	screen.loadPage(1);
-	screen.loadBackground("pyramid3.raw");
-	screen.saveBackground(1);
-
-	SpriteResource sprites[3] = {
-		SpriteResource("title.int"), SpriteResource("pyratop.int"), SpriteResource("pyramid.int")
-	};
-	Common::File voc[2];
-	voc[0].open("pharoh1a.voc");
-	voc[1].open("pharoh1b.voc");
-
-	screen.vertMerge(SCREEN_HEIGHT);
-	screen.loadPage(0);
-	screen.loadPage(1);
-
-	// Show Might and Magic Darkside of Xeen title, and gradualy scroll
-	// the background vertically down to show the Pharoah's base
-	int yp = 0;
-	int frameNum = 0;
-	int idx1 = 0;
-	bool skipElapsed = false;
-	uint32 timeExpired = 0;
-	bool fadeFlag = true;
-
-	for (int yCtr = SCREEN_HEIGHT; yCtr > 0; ) {
-		events.updateGameCounter();
-		screen.vertMerge(yp);
-
-		sprites[0].draw(screen, 0);
-		if (frameNum)
-			sprites[0].draw(screen, frameNum);
-
-		idx1 = (idx1 + 1) % 4;
-		if (!idx1)
-			frameNum = (frameNum + 1) % 10;
-
-		screen.draw();
-		if (!skipElapsed) {
-			timeExpired = MAX((int)events.timeElapsed() - 1, 1);
-			skipElapsed = true;
-		}
-
-		yCtr -= timeExpired;
-		yp = MIN(yp + timeExpired, (uint)200);
-		 
-		if (events.wait(1, true))
-			return false;
-
-		if (fadeFlag) {
-			screen.fadeIn(4);
-			fadeFlag = false;
-		}
-	}
-
-	screen.vertMerge(SCREEN_HEIGHT);
-	screen.saveBackground(1);
-	screen.draw();
-	screen.freePages();
-
-	events.updateGameCounter();
-	events.wait(30, true);
-
-	// Zoom into the Pharoah's base closeup view
-	for (int idx = 14; idx >= 0; --idx) {
-		events.updateGameCounter();
-		sprites[1].draw(screen, 0, Common::Point(XLIST1[idx], YLIST1[idx]));
-		sprites[1].draw(screen, 1, Common::Point(XLIST2[idx], YLIST1[idx]));
-		screen.draw();
-
-		if (idx == 2)
-			sound.stopMusic(48);
-		if (events.wait(2, true))
-			return false;
-	}
-
-	// TODO: More
-	sound.playSong(voc[0]);
-	sound.playSong(voc[1]);
-
-	return true;
-}
-
-} // End of namespace Xeen
diff --git a/engines/xeen/worldofxeen/darkside_intro.h b/engines/xeen/worldofxeen/darkside_intro.h
deleted file mode 100644
index e37f095..0000000
--- a/engines/xeen/worldofxeen/darkside_intro.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/* 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_DARKSIDE_INTRO_H
-#define XEEN_DARKSIDE_INTRO_H
-
-#include "xeen/xeen.h"
-
-namespace Xeen {
-
-bool showDarkSideTitle(XeenEngine &vm);
-
-bool showDarkSideIntro(XeenEngine &vm);
-
-} // End of namespace Xeen
-
-#endif /* XEEN_DARKSIDE_INTRO_H */
diff --git a/engines/xeen/worldofxeen/worldofxeen.cpp b/engines/xeen/worldofxeen/worldofxeen.cpp
new file mode 100644
index 0000000..86a6ee3
--- /dev/null
+++ b/engines/xeen/worldofxeen/worldofxeen.cpp
@@ -0,0 +1,46 @@
+/* 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 "xeen/worldofxeen/worldofxeen.h"
+#include "xeen/worldofxeen/darkside_cutscenes.h"
+#include "xeen/worldofxeen/clouds_cutscenes.h"
+#include "xeen/sound.h"
+
+namespace Xeen {
+
+WorldOfXeenEngine::WorldOfXeenEngine(OSystem *syst, const XeenGameDescription *gameDesc)
+		: XeenEngine(syst, gameDesc), CloudsCutscenes(this), 
+		DarkSideCutscenes(this) {
+	_seenDarkSideIntro = false;
+}
+
+void WorldOfXeenEngine::showIntro() {
+	// **DEBUG**
+	if (gDebugLevel == 0)
+		return;
+
+	bool completed = showDarkSideTitle();
+	if (!_seenDarkSideIntro && completed)
+		showDarkSideIntro();
+}
+
+} // End of namespace Xeen
diff --git a/engines/xeen/worldofxeen/worldofxeen.h b/engines/xeen/worldofxeen/worldofxeen.h
new file mode 100644
index 0000000..68a83bb
--- /dev/null
+++ b/engines/xeen/worldofxeen/worldofxeen.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_WORLDOFXEEN_WORLDOFXEEN_H
+#define XEEN_WORLDOFXEEN_WORLDOFXEEN_H
+
+#include "xeen/xeen.h"
+#include "xeen/worldofxeen/clouds_cutscenes.h"
+#include "xeen/worldofxeen/darkside_cutscenes.h"
+
+namespace Xeen {
+
+/**
+ * Implements a descendant of the base Xeen engine to handle 
+ * Clouds of Xeen, Dark Side of Xeen, and Worlds of Xeen specific
+ * game code
+ */
+class WorldOfXeenEngine: public XeenEngine, public CloudsCutscenes, 
+		public DarkSideCutscenes {
+protected:
+	virtual void showIntro();
+public:
+	bool _seenDarkSideIntro;
+public:
+	WorldOfXeenEngine(OSystem *syst, const XeenGameDescription *gameDesc);
+	virtual ~WorldOfXeenEngine() {}
+};
+
+} // End of namespace Xeen
+
+#endif /* XEEN_WORLDOFXEEN_WORLDOFXEEN_H */
diff --git a/engines/xeen/worldofxeen/worldofxeen_game.cpp b/engines/xeen/worldofxeen/worldofxeen_game.cpp
deleted file mode 100644
index f7c9336..0000000
--- a/engines/xeen/worldofxeen/worldofxeen_game.cpp
+++ /dev/null
@@ -1,44 +0,0 @@
-/* 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 "xeen/worldofxeen/worldofxeen_game.h"
-#include "xeen/worldofxeen/darkside_intro.h"
-#include "xeen/sound.h"
-
-namespace Xeen {
-
-WorldOfXeenEngine::WorldOfXeenEngine(OSystem *syst, const XeenGameDescription *gameDesc)
-		: XeenEngine(syst, gameDesc) {
-	_seenDarkSideIntro = false;
-}
-
-void WorldOfXeenEngine::showIntro() {
-	// **DEBUG**
-	if (gDebugLevel == 0)
-		return;
-
-	bool completed = showDarkSideTitle(*this);
-	if (!_seenDarkSideIntro && completed)
-		showDarkSideIntro(*this);
-}
-
-} // End of namespace Xeen
diff --git a/engines/xeen/worldofxeen/worldofxeen_game.h b/engines/xeen/worldofxeen/worldofxeen_game.h
deleted file mode 100644
index 97a8754..0000000
--- a/engines/xeen/worldofxeen/worldofxeen_game.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/* 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_WORLDOFXEEN_GAME_H
-#define XEEN_WORLDOFXEEN_GAME_H
-
-#include "xeen/xeen.h"
-
-namespace Xeen {
-
-/**
- * Implements a descendant of the base Xeen engine to handle 
- * Clouds of Xeen, Dark Side of Xeen, and Worlds of Xeen specific
- * game code
- */
-class WorldOfXeenEngine: public XeenEngine {
-protected:
-	virtual void showIntro();
-public:
-	bool _seenDarkSideIntro;
-public:
-	WorldOfXeenEngine(OSystem *syst, const XeenGameDescription *gameDesc);
-	virtual ~WorldOfXeenEngine() {}
-};
-
-} // End of namespace Xeen
-
-#endif /* XEEN_WORLDOFXEEN_GAME_H */


Commit: 0c199f079bc1ed62e6c13f292d569fc52eac546c
    https://github.com/scummvm/scummvm/commit/0c199f079bc1ed62e6c13f292d569fc52eac546c
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2016-08-27T16:33:32-04:00

Commit Message:
XEEN: Beginnings of sound effects support

Changed paths:
    engines/xeen/dialogs_info.cpp
    engines/xeen/dialogs_input.cpp
    engines/xeen/sound.cpp
    engines/xeen/sound.h
    engines/xeen/worldofxeen/darkside_cutscenes.cpp
    engines/xeen/xeen.cpp



diff --git a/engines/xeen/dialogs_info.cpp b/engines/xeen/dialogs_info.cpp
index 7ccaa7f..5675563 100644
--- a/engines/xeen/dialogs_info.cpp
+++ b/engines/xeen/dialogs_info.cpp
@@ -81,7 +81,7 @@ void InfoDialog::execute() {
 
 void InfoDialog::protectionText() {
 	Party &party = *_vm->_party;
-	Common::StringArray _lines;
+//	Common::StringArray _lines;
 	const char *const AA_L024 = "\x3l\n\x9""024";
 	const char *const AA_R124 = "\x3r\x9""124";
 
diff --git a/engines/xeen/dialogs_input.cpp b/engines/xeen/dialogs_input.cpp
index 8b754ab..eec6088 100644
--- a/engines/xeen/dialogs_input.cpp
+++ b/engines/xeen/dialogs_input.cpp
@@ -263,6 +263,8 @@ int Choose123::execute(int numOptions) {
 
 	_vm->_mode = oldMode;
 	intf.mainIconsPrint();
+
+	return result;
 }
 
 void Choose123::loadButtons(int numOptions) {
diff --git a/engines/xeen/sound.cpp b/engines/xeen/sound.cpp
index 00b9247..ec8b8c6 100644
--- a/engines/xeen/sound.cpp
+++ b/engines/xeen/sound.cpp
@@ -20,27 +20,51 @@
  *
  */
 
+#include "audio/decoders/voc.h"
 #include "xeen/sound.h"
+#include "xeen/xeen.h"
 
 namespace Xeen {
 
+SoundManager *VOC::_sound;
+
+void VOC::init(XeenEngine *vm) {
+	_sound = vm->_sound;
+}
+
+void VOC::play() {
+	_sound->playSound(this, _soundHandle);
+}
+
 void VOC::stop() {
-	warning("TODO: VOC::stop");
+	_sound->stopSound(_soundHandle);
 }
 
-SoundManager::SoundManager(XeenEngine *vm): _vm(vm) {
+/*------------------------------------------------------------------------*/
+
+SoundManager::SoundManager(XeenEngine *vm, Audio::Mixer *mixer): _vm(vm), _mixer(mixer) {
 }
 
 void SoundManager::proc2(Common::SeekableReadStream &f) {
-
+	// TODO
 }
 
 void SoundManager::startMusic(int v1) {
-
+	// TODO
 }
 
 void SoundManager::stopMusic(int id) {
+	// TODO
 }
 
+void SoundManager::playSound(Common::SeekableReadStream *s, Audio::SoundHandle &soundHandle) {
+	Audio::SeekableAudioStream *stream = Audio::makeVOCStream(s, 0);
+	_mixer->playStream(Audio::Mixer::kPlainSoundType, &soundHandle, stream);
+		
+}
+
+void SoundManager::stopSound(Audio::SoundHandle &soundHandle) {
+	_mixer->stopHandle(soundHandle);
+}
 
 } // End of namespace Xeen
diff --git a/engines/xeen/sound.h b/engines/xeen/sound.h
index 5c123d7..172ef9e 100644
--- a/engines/xeen/sound.h
+++ b/engines/xeen/sound.h
@@ -23,6 +23,8 @@
 #ifndef XEEN_SOUND_H
 #define XEEN_SOUND_H
 
+#include "audio/mixer.h"
+#include "audio/audiostream.h"
 #include "common/scummsys.h"
 #include "common/system.h"
 #include "xeen/files.h"
@@ -32,12 +34,18 @@ namespace Xeen {
 class SoundManager;
 
 class VOC: public Common::File {
-	friend class SoundManager;
 private:
-	SoundManager *_sound;
+	static SoundManager *_sound;
+	Audio::SoundHandle _soundHandle;
 public:
-	VOC() : _sound(nullptr) {}
+	VOC() {}
 	virtual ~VOC() { stop(); }
+	static void init(XeenEngine *vm);
+
+	/**
+	 * Start playing the sound
+	 */
+	void play();
 
 	/**
 	 * Stop playing the sound
@@ -48,8 +56,9 @@ public:
 class SoundManager {
 private:
 	XeenEngine *_vm;
+	Audio::Mixer *_mixer;
 public:
-	SoundManager(XeenEngine *vm);
+	SoundManager(XeenEngine *vm, Audio::Mixer *mixer);
 
 	void proc2(Common::SeekableReadStream &f);
 
@@ -61,7 +70,15 @@ public:
 
 	void playSong(Common::SeekableReadStream &f) {}
 
-	void playSound(VOC &voc) {}
+	/**
+	 * Play a given sound
+	 */
+	void playSound(Common::SeekableReadStream *s, Audio::SoundHandle &soundHandle);
+
+	/**
+	 * Stop playing a sound
+	 */
+	void stopSound(Audio::SoundHandle &soundHandle);
 
 	void playSample(const Common::SeekableReadStream *stream, int v2 = 1) {}
 
diff --git a/engines/xeen/worldofxeen/darkside_cutscenes.cpp b/engines/xeen/worldofxeen/darkside_cutscenes.cpp
index 90efef1..6226b52 100644
--- a/engines/xeen/worldofxeen/darkside_cutscenes.cpp
+++ b/engines/xeen/worldofxeen/darkside_cutscenes.cpp
@@ -66,7 +66,7 @@ bool DarkSideCutscenes::showDarkSideTitle() {
 
 		switch (idx) {
 		case 17:
-			sound.playSound(voc[0]);
+			voc[0].play();
 			break;
 		case 34:
 		case 44:
@@ -74,7 +74,7 @@ bool DarkSideCutscenes::showDarkSideTitle() {
 			nwcFrame = 0;
 			break;
 		case 35:
-			sound.playSound(voc[1]);
+			voc[1].play();
 			break;
 		default:
 			++nwcFrame;
diff --git a/engines/xeen/xeen.cpp b/engines/xeen/xeen.cpp
index 9034985..3b317f5 100644
--- a/engines/xeen/xeen.cpp
+++ b/engines/xeen/xeen.cpp
@@ -95,9 +95,10 @@ void XeenEngine::initialize() {
 	_screen = new Screen(this);
 	_scripts = new Scripts(this);
 	_screen->setupWindows();
-	_sound = new SoundManager(this);
+	_sound = new SoundManager(this, _mixer);
 	_spells = new Spells(this);
 	_town = new Town(this);
+	VOC::init(this);
 
 	File f("029.obj");
 	_eventData = f.readStream(f.size());


Commit: ef6253fb19822b9a2e9a1ba00418f1d33afff65f
    https://github.com/scummvm/scummvm/commit/ef6253fb19822b9a2e9a1ba00418f1d33afff65f
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2016-08-28T15:46:10-04:00

Commit Message:
XEEN: gcc compilation fixes

Changed paths:
    engines/xeen/character.cpp
    engines/xeen/character.h
    engines/xeen/combat.cpp
    engines/xeen/dialogs_items.cpp
    engines/xeen/dialogs_party.cpp
    engines/xeen/interface.cpp
    engines/xeen/party.cpp
    engines/xeen/sound.cpp
    engines/xeen/sound.h
    engines/xeen/sprites.cpp
    engines/xeen/town.cpp
    engines/xeen/xsurface.cpp
    engines/xeen/xsurface.h



diff --git a/engines/xeen/character.cpp b/engines/xeen/character.cpp
index ca224ab..bb7877c 100644
--- a/engines/xeen/character.cpp
+++ b/engines/xeen/character.cpp
@@ -202,7 +202,7 @@ void InventoryItems::removeItem(int itemIndex) {
 		item._frame = 0;
 }
 
-XeenEngine *InventoryItems::vm() {
+XeenEngine *InventoryItems::getVm() {
 	return Party::_vm;
 }
 
@@ -297,7 +297,7 @@ void WeaponItems::equipItem(int itemIndex) {
  */
 Common::String WeaponItems::getFullDescription(int itemIndex, int displayNum) {
 	XeenItem &i = operator[](itemIndex);
-	Resources &res = *vm()->_resources;
+	Resources &res = *getVm()->_resources;
 
 	return Common::String::format("\f%02u%s%s%s\f%02u%s%s%s", displayNum,
 		!i._bonusFlags ? res._maeNames[i._material].c_str() : "",
@@ -311,7 +311,7 @@ Common::String WeaponItems::getFullDescription(int itemIndex, int displayNum) {
 }
 
 void WeaponItems::enchantItem(int itemIndex, int amount) {
-	SoundManager &sound = *vm()->_sound;
+	SoundManager &sound = *getVm()->_sound;
 	XeenItem &item = operator[](itemIndex);
 	Character tempCharacter;
 
@@ -463,12 +463,13 @@ void ArmorItems::equipItem(int itemIndex) {
  */
 Common::String ArmorItems::getFullDescription(int itemIndex, int displayNum) {
 	XeenItem &i = operator[](itemIndex);
-	Resources &res = *vm()->_resources;
+	Resources &res = *getVm()->_resources;
 
 	return Common::String::format("\f%02u%s%s%s\f%02u%s%s", displayNum,
 		!i._bonusFlags ? "" : res._maeNames[i._material].c_str(),
 		(i._bonusFlags & ITEMFLAG_BROKEN) ? ITEM_BROKEN : "",
 		(i._bonusFlags & ITEMFLAG_CURSED) ? ITEM_CURSED : "",
+		displayNum,
 		ARMOR_NAMES[i._id],
 		(i._bonusFlags & (ITEMFLAG_BROKEN | ITEMFLAG_CURSED)) ||
 			!i._bonusFlags ? "\b " : ""
@@ -476,7 +477,7 @@ Common::String ArmorItems::getFullDescription(int itemIndex, int displayNum) {
 }
 
 void ArmorItems::enchantItem(int itemIndex, int amount) {
-	SoundManager &sound = *vm()->_sound;
+	SoundManager &sound = *getVm()->_sound;
 	XeenItem &item = operator[](itemIndex);
 	Character tempCharacter;
 
@@ -586,7 +587,7 @@ void AccessoryItems::equipItem(int itemIndex) {
  */
 Common::String AccessoryItems::getFullDescription(int itemIndex, int displayNum) {
 	XeenItem &i = operator[](itemIndex);
-	Resources &res = *vm()->_resources;
+	Resources &res = *getVm()->_resources;
 
 	return Common::String::format("\f%02u%s%s%s\f%02u%s%s", displayNum,
 		!i._bonusFlags ? "" : res._maeNames[i._material].c_str(),
@@ -635,7 +636,7 @@ Common::String AccessoryItems::getAttributes(XeenItem &item, const Common::Strin
  */
 Common::String MiscItems::getFullDescription(int itemIndex, int displayNum) {
 	XeenItem &i = operator[](itemIndex);
-	Resources &res = *vm()->_resources;
+	Resources &res = *getVm()->_resources;
 
 	return Common::String::format("\f%02u%s%s%s\f%02u%s%s", displayNum,
 		!i._bonusFlags ? "" : res._maeNames[i._material].c_str(),
@@ -653,7 +654,7 @@ Common::String MiscItems::getFullDescription(int itemIndex, int displayNum) {
 */
 Common::String MiscItems::getAttributes(XeenItem &item, const Common::String &classes) {
 	Common::String specialPower = FIELD_NONE;
-	Spells &spells = *vm()->_spells;
+	Spells &spells = *getVm()->_spells;
 
 	if (item._id) {
 		specialPower = spells._spellNames[MISC_SPELL_INDEX[item._id]];
@@ -1814,6 +1815,9 @@ int Character::makeItem(int p1, int itemIndex, int p3) {
 		newItem._id = miscId;
 		newItem._bonusFlags = miscBonus;
 		break;
+
+	default:
+		break;
 	}
 
 	return category;
diff --git a/engines/xeen/character.h b/engines/xeen/character.h
index f1243f1..83198a1 100644
--- a/engines/xeen/character.h
+++ b/engines/xeen/character.h
@@ -50,8 +50,7 @@ enum Race { HUMAN = 0, ELF = 1, DWARF = 2, GNOME = 3, HALF_ORC = 4 };
 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, TOTAL_CLASSES = 10,
-	CLASS_12 = 12, CLASS_15 = 15, CLASS_16 = 16
+	CLASS_DRUID = 8, CLASS_RANGER = 9, TOTAL_CLASSES = 10, CLASS_12 = 12, CLASS_15 = 15, CLASS_16 = 16
 };
 
 enum Attribute {
@@ -114,13 +113,14 @@ protected:
 	ItemCategory _category;
 	const char *const *_names;
 
-	XeenEngine *vm();
+	XeenEngine *getVm();
 	void equipError(int itemIndex1, ItemCategory category1, int itemIndex2,
 		ItemCategory category2);
 
 	virtual Common::String getAttributes(XeenItem &item, const Common::String &classes) = 0;
 public:
 	InventoryItems(Character *character, ItemCategory category);
+	virtual ~InventoryItems() {}
 
 	void clear();
 
@@ -150,6 +150,7 @@ protected:
 	virtual Common::String getAttributes(XeenItem &item, const Common::String &classes);
 public:
 	WeaponItems(Character *character) : InventoryItems(character, CATEGORY_WEAPON) {}
+	virtual ~WeaponItems() {}
 
 	virtual void equipItem(int itemIndex);
 
@@ -163,6 +164,7 @@ protected:
 	virtual Common::String getAttributes(XeenItem &item, const Common::String &classes);
 public:
 	ArmorItems(Character *character) : InventoryItems(character, CATEGORY_ARMOR) {}
+	virtual ~ArmorItems() {}
 
 	virtual void equipItem(int itemIndex);
 
@@ -187,6 +189,7 @@ protected:
 	virtual Common::String getAttributes(XeenItem &item, const Common::String &classes);
 public:
 	MiscItems(Character *character) : InventoryItems(character, CATEGORY_MISC) {}
+	virtual ~MiscItems() {}
 
 	virtual Common::String getFullDescription(int itemIndex, int displayNum);
 };
diff --git a/engines/xeen/combat.cpp b/engines/xeen/combat.cpp
index 1d03a51..13efe91 100644
--- a/engines/xeen/combat.cpp
+++ b/engines/xeen/combat.cpp
@@ -422,6 +422,9 @@ void Combat::doCharDamage(Character &c, int charNum, int monsterDataIndex) {
 			if (c._currentHp > 0)
 				c._currentHp = 0;
 			break;
+
+		default:
+			break;
 		}
 
 		c.subtractHitPoints(damage);
@@ -823,7 +826,7 @@ void Combat::doMonsterTurn(int monsterId) {
 				if (cond >= PARALYZED && cond <= ERADICATED)
 					continue;
 
-				bool isHated = false;
+				isHated = false;
 				switch (monsterData._hatesClass) {
 				case CLASS_KNIGHT:
 				case CLASS_PALADIN:
@@ -1277,10 +1280,10 @@ void Combat::attack(Character &c, RangeType rangeType) {
 			damage = 0;
 
 			for (uint charIndex = 0; charIndex < party._activeParty.size(); ++charIndex) {
-				Character &c = party._activeParty[charIndex];
+				Character &ch = party._activeParty[charIndex];
 
 				if (_shooting[charIndex] && !_missedShot[charIndex]) {
-					if (!hitMonster(c, rangeType)) {
+					if (!hitMonster(ch, rangeType)) {
 						++_missedShot[charIndex];
 					} else {
 						damage = _monsterDamage ? _monsterDamage : _weaponDamage;
@@ -1337,6 +1340,8 @@ void Combat::attack(Character &c, RangeType rangeType) {
 		case CLASS_SORCERER:
 			divisor = 8;
 			break;
+		default:
+			break;
 		}
 
 		int numberOfAttacks = c.getCurrentLevel() / divisor + 1;
@@ -1651,6 +1656,8 @@ bool Combat::hitMonster(Character &c, RangeType rangeType) {
 	case CLASS_SORCERER:
 		divisor = 4;
 		break;
+	default:
+		break;
 	}
 
 	chance += c.getCurrentLevel() / divisor;
diff --git a/engines/xeen/dialogs_items.cpp b/engines/xeen/dialogs_items.cpp
index bdcdffa..147f934 100644
--- a/engines/xeen/dialogs_items.cpp
+++ b/engines/xeen/dialogs_items.cpp
@@ -913,8 +913,8 @@ int ItemsDialog::doItemOptions(Character &c, int actionIndex, int itemIndex, Ite
 			break;
 
 		case ITEMMODE_BLACKSMITH: {
-			InventoryItems &items = _oldCharacter->_items[category];
-			if (items[INV_ITEMS_TOTAL - 1]._id) {
+			InventoryItems &invItems = _oldCharacter->_items[category];
+			if (invItems[INV_ITEMS_TOTAL - 1]._id) {
 				// If the last slot is in use, it means the list is full
 				ErrorScroll::show(_vm, Common::String::format(BACKPACK_IS_FULL,
 					_oldCharacter->_name.c_str()));
@@ -1021,13 +1021,13 @@ int ItemsDialog::doItemOptions(Character &c, int actionIndex, int itemIndex, Ite
 			if (Confirm::show(_vm, msg) && party.subtract(0, cost, 0)) {
 				Common::String details = c._items[category].getIdentifiedDetails(itemIndex);
 				Common::String desc = c._items[category].getFullDescription(itemIndex);
-				Common::String msg = Common::String::format(IDENTIFY_ITEM_MSG,
+				Common::String str = Common::String::format(IDENTIFY_ITEM_MSG,
 					desc.c_str(), details.c_str());
 
-				Window &w = screen._windows[14];
-				w.open();
-				w.writeString(msg);
-				w.update();
+				Window &win = screen._windows[14];
+				win.open();
+				win.writeString(str);
+				win.update();
 
 				saveButtons();
 				clearButtons();
@@ -1037,7 +1037,7 @@ int ItemsDialog::doItemOptions(Character &c, int actionIndex, int itemIndex, Ite
 				events.clearEvents();
 
 				restoreButtons();
-				w.close();
+				win.close();
 			}
 			break;
 		}
diff --git a/engines/xeen/dialogs_party.cpp b/engines/xeen/dialogs_party.cpp
index 544c110..69761bb 100644
--- a/engines/xeen/dialogs_party.cpp
+++ b/engines/xeen/dialogs_party.cpp
@@ -240,8 +240,8 @@ void PartyDialog::execute() {
 								// Rebuild the character list
 								_charList.clear();
 								for (int idx = 0; idx < XEEN_TOTAL_CHARACTERS; ++idx) {
-									Character &c = party._roster[idx];
-									if (!c._name.empty() && c._savedMazeId == party._priorMazeId) {
+									Character &ch = party._roster[idx];
+									if (!ch._name.empty() && ch._savedMazeId == party._priorMazeId) {
 										_charList.push_back(idx);
 									}
 								}
@@ -339,7 +339,7 @@ void PartyDialog::setupFaces(int firstDisplayChar, bool updateFlag) {
 	drawParty(updateFlag);
 
 	// Set up the sprite set to use for each face
-	for (int posIndex = 0; posIndex < 4; ++posIndex) {
+	for (posIndex = 0; posIndex < 4; ++posIndex) {
 		if ((firstDisplayChar + posIndex) >= (int)_charList.size())
 			_faceDrawStructs[posIndex]._sprites = nullptr;
 		else
diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp
index d1a1478..f9f1eeb 100644
--- a/engines/xeen/interface.cpp
+++ b/engines/xeen/interface.cpp
@@ -1006,7 +1006,7 @@ bool Interface::checkMoveDirection(int key) {
 			break;
 		}
 	} else {
-		int surfaceId = map.getCell(2);
+		surfaceId = map.getCell(2);
 		if (surfaceId >= map.mazeData()._difficulties._wallNoPass) {
 			party._mazeDirection = dir;
 			sound.playFX(46);
diff --git a/engines/xeen/party.cpp b/engines/xeen/party.cpp
index 9f56b98..1db4a14 100644
--- a/engines/xeen/party.cpp
+++ b/engines/xeen/party.cpp
@@ -638,9 +638,9 @@ void Party::giveTreasure() {
 
 				// Fall back on checking the entire conscious party
 				for (charIndex = 0; charIndex < (int)_activeParty.size(); ++charIndex) {
-					Character &c = _activeParty[charIndex];
-					if (!c._items[(ItemCategory)categoryNum].isFull() && !c.isDisabledOrDead()) {
-						giveTreasureToCharacter(c, (ItemCategory)categoryNum, itemNum);
+					Character &ch = _activeParty[charIndex];
+					if (!ch._items[(ItemCategory)categoryNum].isFull() && !ch.isDisabledOrDead()) {
+						giveTreasureToCharacter(ch, (ItemCategory)categoryNum, itemNum);
 						break;
 					}
 				}
diff --git a/engines/xeen/sound.cpp b/engines/xeen/sound.cpp
index ec8b8c6..c0a49ae 100644
--- a/engines/xeen/sound.cpp
+++ b/engines/xeen/sound.cpp
@@ -28,6 +28,11 @@ namespace Xeen {
 
 SoundManager *VOC::_sound;
 
+VOC::VOC(const Common::String &name) {
+	if (!open(name))
+		error("Could not open - %s", name.c_str());
+}
+
 void VOC::init(XeenEngine *vm) {
 	_sound = vm->_sound;
 }
diff --git a/engines/xeen/sound.h b/engines/xeen/sound.h
index 172ef9e..bcee6f2 100644
--- a/engines/xeen/sound.h
+++ b/engines/xeen/sound.h
@@ -39,6 +39,7 @@ private:
 	Audio::SoundHandle _soundHandle;
 public:
 	VOC() {}
+	VOC(const Common::String &name);
 	virtual ~VOC() { stop(); }
 	static void init(XeenEngine *vm);
 
diff --git a/engines/xeen/sprites.cpp b/engines/xeen/sprites.cpp
index 3491f6f..b29fb2d 100644
--- a/engines/xeen/sprites.cpp
+++ b/engines/xeen/sprites.cpp
@@ -185,7 +185,7 @@ void SpriteResource::drawOffset(XSurface &dest, uint16 offset, const Common::Poi
 			destPos.y++;
 		} else {
 			scaleMaskX = scaleMaskXCopy;
-			int xOffset = f.readByte();
+			xOffset = f.readByte();
 			
 			// Initialize the array to hold the temporary data for the line. We do this to make it simpler
 			// to handle both deciding which pixels to draw in a scaled image, as well as when images
diff --git a/engines/xeen/town.cpp b/engines/xeen/town.cpp
index 9b4bfa3..221f5d9 100644
--- a/engines/xeen/town.cpp
+++ b/engines/xeen/town.cpp
@@ -704,7 +704,7 @@ Character *Town::doTavernOptions(Character *c) {
 
 	case Common::KEYCODE_s: {
 		// Sign In
-		int idx = isDarkCc ? (party._mazeId - 29) >> 1 : party._mazeId - 28;
+		idx = isDarkCc ? (party._mazeId - 29) >> 1 : party._mazeId - 28;
 		assert(idx >= 0);
 		party._mazePosition.x = TAVERN_EXIT_LIST[isDarkCc ? 1 : 0][_townActionId][idx][0];
 		party._mazePosition.y = TAVERN_EXIT_LIST[isDarkCc ? 1 : 0][_townActionId][idx][1];
@@ -717,7 +717,7 @@ Character *Town::doTavernOptions(Character *c) {
 			party._mazeDirection = DIR_SOUTH;
 
 		party._priorMazeId = party._mazeId;
-		for (uint idx = 0; idx < party._activeParty.size(); ++idx) {
+		for (idx = 0; idx < (int)party._activeParty.size(); ++idx) {
 			party._activeParty[idx]._savedMazeId = party._mazeId;
 			party._activeParty[idx]._xeenSide = map._loadDarkSide;
 		}
@@ -825,8 +825,8 @@ Character *Town::doTempleOptions(Character *c) {
 
 				intf.drawParty(true);
 				sound.playSample(nullptr, 0);
-				File f("ahh.voc");
-				sound.playSample(&f, 1);
+				VOC voc("ahh.voc");
+				voc.play();
 				_flag1 = true;
 				_donation = 0;
 			}
@@ -1030,7 +1030,6 @@ void Town::depositWithdrawl(int choice) {
 				}
 			}
 
-			uint gold, gems;
 			if (choice) {
 				gold = party._bankGold;
 				gems = party._bankGems;
diff --git a/engines/xeen/xsurface.cpp b/engines/xeen/xsurface.cpp
index 04a264a..00d333d 100644
--- a/engines/xeen/xsurface.cpp
+++ b/engines/xeen/xsurface.cpp
@@ -40,8 +40,8 @@ XSurface::~XSurface() {
 		free();
 }
 
-void XSurface::create(uint16 w, uint16 h) {
-	Graphics::Surface::create(w, h, Graphics::PixelFormat::createFormatCLUT8());
+void XSurface::create(uint16 w_, uint16 h_) {
+	Graphics::Surface::create(w_, h_, Graphics::PixelFormat::createFormatCLUT8());
 	_freeFlag = true;
 }
 
diff --git a/engines/xeen/xsurface.h b/engines/xeen/xsurface.h
index d8747d4..299cc51 100644
--- a/engines/xeen/xsurface.h
+++ b/engines/xeen/xsurface.h
@@ -40,7 +40,7 @@ public:
 	XSurface(int w, int h);
 	virtual ~XSurface();
 
-	void create(uint16 w, uint16 h);
+	void create(uint16 w_, uint16 h_);
 
 	void create(XSurface *s, const Common::Rect &bounds);
 


Commit: dffa696b7beea02782579a004862f4aa86e8f3e6
    https://github.com/scummvm/scummvm/commit/dffa696b7beea02782579a004862f4aa86e8f3e6
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2016-08-28T16:14:38-04:00

Commit Message:
XEEN: gcc compilation fixes

Changed paths:
    engines/xeen/character.cpp
    engines/xeen/combat.cpp



diff --git a/engines/xeen/character.cpp b/engines/xeen/character.cpp
index bb7877c..51f288c 100644
--- a/engines/xeen/character.cpp
+++ b/engines/xeen/character.cpp
@@ -303,6 +303,7 @@ Common::String WeaponItems::getFullDescription(int itemIndex, int displayNum) {
 		!i._bonusFlags ? res._maeNames[i._material].c_str() : "",
 		(i._bonusFlags & ITEMFLAG_BROKEN) ? ITEM_BROKEN : "",
 		(i._bonusFlags & ITEMFLAG_CURSED) ? ITEM_CURSED : "",
+		displayNum,
 		WEAPON_NAMES[i._id],
 		!i._bonusFlags ? "" : BONUS_NAMES[i._bonusFlags & ITEMFLAG_BONUS_MASK],
 		(i._bonusFlags & (ITEMFLAG_BROKEN | ITEMFLAG_CURSED)) || 
@@ -593,6 +594,7 @@ Common::String AccessoryItems::getFullDescription(int itemIndex, int displayNum)
 		!i._bonusFlags ? "" : res._maeNames[i._material].c_str(),
 		(i._bonusFlags & ITEMFLAG_BROKEN) ? ITEM_BROKEN : "",
 		(i._bonusFlags & ITEMFLAG_CURSED) ? ITEM_CURSED : "",
+		displayNum,
 		ARMOR_NAMES[i._id],
 		(i._bonusFlags & (ITEMFLAG_BROKEN | ITEMFLAG_CURSED)) ||
 			!i._bonusFlags ? "\b " : ""
@@ -642,6 +644,7 @@ Common::String MiscItems::getFullDescription(int itemIndex, int displayNum) {
 		!i._bonusFlags ? "" : res._maeNames[i._material].c_str(),
 		(i._bonusFlags & ITEMFLAG_BROKEN) ? ITEM_BROKEN : "",
 		(i._bonusFlags & ITEMFLAG_CURSED) ? ITEM_CURSED : "",
+		displayNum,
 		ARMOR_NAMES[i._id],
 		(i._bonusFlags & (ITEMFLAG_BROKEN | ITEMFLAG_CURSED)) ||
 			!i._id ? "\b " : ""
@@ -1722,6 +1725,9 @@ int Character::makeItem(int p1, int itemIndex, int p3) {
 	case CATEGORY_MISC:
 		v8 = 4;
 		break;
+
+	default:
+		break;
 	}
 
 	if (p1 != 1 || category == CATEGORY_MISC) {
diff --git a/engines/xeen/combat.cpp b/engines/xeen/combat.cpp
index 13efe91..c8cece7 100644
--- a/engines/xeen/combat.cpp
+++ b/engines/xeen/combat.cpp
@@ -496,11 +496,12 @@ void Combat::moveMonsters() {
 									if (monsterCanMove(pt, MONSTER_GRID_BITMASK[MONSTER_GRID_BITINDEX2[arrIndex]],
 										arrIndex >= 21 && arrIndex <= 27 ? MONSTER_GRID3[arrIndex] : 0,
 										arrIndex >= 21 && arrIndex <= 27 ? 0 : MONSTER_GRID3[arrIndex],
-										idx))
-									if (arrIndex >= 21 && arrIndex <= 27) {
-										moveMonster(idx, Common::Point(MONSTER_GRID3[arrIndex], 0));
-									} else {
-										moveMonster(idx, Common::Point(0, MONSTER_GRID3[arrIndex]));
+										idx)) {
+										if (arrIndex >= 21 && arrIndex <= 27) {
+											moveMonster(idx, Common::Point(MONSTER_GRID3[arrIndex], 0));
+										} else {
+											moveMonster(idx, Common::Point(0, MONSTER_GRID3[arrIndex]));
+										}
 									}
 								}
 								break;
@@ -520,6 +521,9 @@ void Combat::moveMonsters() {
 										MONSTER_GRID_X[arrIndex], MONSTER_GRID_Y[arrIndex], idx)) {
 									moveMonster(idx, Common::Point(MONSTER_GRID_X[arrIndex], MONSTER_GRID_Y[arrIndex]));
 								}
+
+							default:
+								break;
 							}
 						}
 					}


Commit: fd2d4622966d36299129b3f1654484b49ee0c996
    https://github.com/scummvm/scummvm/commit/fd2d4622966d36299129b3f1654484b49ee0c996
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2016-08-28T17:52:56-04:00

Commit Message:
XEEN: Moved method comments from CPP to header files

Changed paths:
    engines/xeen/character.cpp
    engines/xeen/character.h
    engines/xeen/combat.cpp
    engines/xeen/combat.h
    engines/xeen/dialogs.cpp
    engines/xeen/dialogs.h
    engines/xeen/dialogs_char_info.cpp
    engines/xeen/dialogs_char_info.h
    engines/xeen/dialogs_input.cpp
    engines/xeen/dialogs_input.h
    engines/xeen/dialogs_items.cpp
    engines/xeen/dialogs_items.h
    engines/xeen/dialogs_party.cpp
    engines/xeen/dialogs_party.h
    engines/xeen/events.cpp
    engines/xeen/events.h
    engines/xeen/files.cpp
    engines/xeen/files.h
    engines/xeen/font.cpp
    engines/xeen/font.h
    engines/xeen/interface.cpp
    engines/xeen/interface.h
    engines/xeen/interface_map.cpp
    engines/xeen/interface_map.h
    engines/xeen/map.cpp
    engines/xeen/map.h
    engines/xeen/module.mk
    engines/xeen/party.cpp
    engines/xeen/party.h
    engines/xeen/saves.cpp
    engines/xeen/saves.h
    engines/xeen/screen.cpp
    engines/xeen/screen.h
    engines/xeen/scripts.cpp
    engines/xeen/scripts.h
    engines/xeen/spells.cpp
    engines/xeen/spells.h
    engines/xeen/sprites.cpp
    engines/xeen/sprites.h
    engines/xeen/town.cpp
    engines/xeen/town.h
    engines/xeen/xeen.cpp
    engines/xeen/xeen.h



diff --git a/engines/xeen/character.cpp b/engines/xeen/character.cpp
index 51f288c..2ab5329 100644
--- a/engines/xeen/character.cpp
+++ b/engines/xeen/character.cpp
@@ -78,9 +78,6 @@ void InventoryItems::clear() {
 		operator[](idx).clear();
 }
 
-/**
-* Return whether a given item passes class-based usage restrictions
-*/
 bool InventoryItems::passRestrictions(int itemId, bool showError) const {
 	CharacterClass charClass = _character->_class;
 
@@ -117,9 +114,6 @@ bool InventoryItems::passRestrictions(int itemId, bool showError) const {
 	return false;
 }
 
-/**
- * Return the bare name of a given inventory item
- */
 Common::String InventoryItems::getName(int itemIndex) {
 	int id = operator[](itemIndex)._id;
 	return _names[id];
@@ -143,9 +137,6 @@ Common::String InventoryItems::getIdentifiedDetails(int itemIndex) {
 	return getAttributes(item, classes);
 }
 
-/**
- * Discard an item from the inventory
- */
 bool InventoryItems::discardItem(int itemIndex) {
 	XeenItem &item = operator[](itemIndex);
 	XeenEngine *vm = Party::_vm;
@@ -167,9 +158,6 @@ bool InventoryItems::discardItem(int itemIndex) {
 	return true;
 }
 
-/**
- * Sorts the items list, removing any empty item slots to the end of the array
- */
 void InventoryItems::sort() {
 	for (uint idx = 0; idx < size(); ++idx) {
 		if (operator[](idx)._id == 0) {
@@ -189,9 +177,6 @@ void InventoryItems::sort() {
 	}
 }
 
-/**
- * Un-equips the given item
- */
 void InventoryItems::removeItem(int itemIndex) {
 	XeenItem &item = operator[](itemIndex);
 	XeenEngine *vm = Party::_vm;
@@ -228,19 +213,12 @@ void InventoryItems::enchantItem(int itemIndex, int amount) {
 	ErrorScroll::show(vm, Common::String::format(NOT_ENCHANTABLE, SPELL_FAILED));
 }
 
-/**
- * Return if the given inventory items list is full
- */
 bool InventoryItems::isFull() const {
 	return operator[](size() - 1)._id != 0;
 }
 
-
 /*------------------------------------------------------------------------*/
 
-/**
- * Equip a given weapon
- */
 void WeaponItems::equipItem(int itemIndex) {
 	XeenItem &item = operator[](itemIndex);
 
@@ -291,10 +269,6 @@ void WeaponItems::equipItem(int itemIndex) {
 	}
 }
 
-/**
- * Assembles a full lines description for a specified item for use in
- * the Items dialog
- */
 Common::String WeaponItems::getFullDescription(int itemIndex, int displayNum) {
 	XeenItem &i = operator[](itemIndex);
 	Resources &res = *getVm()->_resources;
@@ -377,9 +351,6 @@ Common::String WeaponItems::getAttributes(XeenItem &item, const Common::String &
 
 /*------------------------------------------------------------------------*/
 
-/**
- * Equip a given piece of armor
- */
 void ArmorItems::equipItem(int itemIndex) {
 	XeenItem &item = operator[](itemIndex);
 
@@ -458,10 +429,6 @@ void ArmorItems::equipItem(int itemIndex) {
 	}
 }
 
-/**
- * Assembles a full lines description for a specified item for use in
- * the Items dialog
- */
 Common::String ArmorItems::getFullDescription(int itemIndex, int displayNum) {
 	XeenItem &i = operator[](itemIndex);
 	Resources &res = *getVm()->_resources;
@@ -531,9 +498,6 @@ Common::String ArmorItems::getAttributes(XeenItem &item, const Common::String &c
 
 /*------------------------------------------------------------------------*/
 
-/**
- * Equip a given accessory
- */
 void AccessoryItems::equipItem(int itemIndex) {
 	XeenItem &item = operator[](itemIndex);
 
@@ -582,10 +546,6 @@ void AccessoryItems::equipItem(int itemIndex) {
 	}
 }
 
-/**
- * Assembles a full lines description for a specified item for use in
- * the Items dialog
- */
 Common::String AccessoryItems::getFullDescription(int itemIndex, int displayNum) {
 	XeenItem &i = operator[](itemIndex);
 	Resources &res = *getVm()->_resources;
@@ -632,10 +592,6 @@ Common::String AccessoryItems::getAttributes(XeenItem &item, const Common::Strin
 
 /*------------------------------------------------------------------------*/
 
-/**
- * Assembles a full lines description for a specified item for use in
- * the Items dialog
- */
 Common::String MiscItems::getFullDescription(int itemIndex, int displayNum) {
 	XeenItem &i = operator[](itemIndex);
 	Resources &res = *getVm()->_resources;
@@ -681,9 +637,6 @@ InventoryItems &InventoryItemsGroup::operator[](ItemCategory category) {
 	return *_itemSets[category];
 }
 
-/**
- * Breaks all the items in a given character's inventory
- */
 void InventoryItemsGroup::breakAllItems() {
 	for (int idx = 0; idx < INV_ITEMS_TOTAL; ++idx) {
 		if ((*_itemSets[0])[idx]._id != 34) {
@@ -848,9 +801,6 @@ void Character::synchronize(Common::Serializer &s) {
 	s.syncAsByte(_currentCombatSpell);
 }
 
-/**
- * Returns the worst condition the character is suffering from
- */
 Condition Character::worstCondition() const {
 	for (int cond = ERADICATED; cond >= CURSED; --cond) {
 		if (_conditions[cond])
@@ -860,9 +810,6 @@ Condition Character::worstCondition() const {
 	return NO_CONDITION;
 }
 
-/**
- * Returns whether the given character has a disabling condition, but still alive
- */
 bool Character::isDisabled() const {
 	Condition condition = worstCondition();
 
@@ -870,27 +817,18 @@ bool Character::isDisabled() const {
 		|| condition == STONED || condition == ERADICATED;
 }
 
-/**
-* Returns whether the given character has a disabling condition, or is dead
-*/
 bool Character::isDisabledOrDead() const {
 	Condition condition = worstCondition();
 
 	return condition == ASLEEP || (condition >= PARALYZED && condition <= ERADICATED);
 }
 
-/**
- * Returns whether the given character has a dead condition
- */
 bool Character::isDead() const {
 	Condition condition = worstCondition();
 
 	return condition >= DEAD && condition <= ERADICATED;
 }
 
-/**
- * Get the character's age
- */
 int Character::getAge(bool ignoreTemp) const {
 	int year = MIN(Party::_vm->_party->_year - _birthYear, (uint)254);
 
@@ -967,9 +905,6 @@ int Character::getMaxSP() const {
 	return result;
 }
 
-/**
- * Get the effective value of a given stat for the character
- */
 uint Character::getStat(Attribute attrib, bool baseOnly) const {
 	AttributePair attr;
 	int mode = 0;
@@ -1024,10 +959,6 @@ uint Character::getStat(Attribute attrib, bool baseOnly) const {
 	return MAX(attr._permanent, (uint)0);
 }
 
-/**
- * Return the color number to use for a given stat value in the character
- * info or quick reference dialogs
- */
 int Character::statColor(int amount, int threshold) {
 	if (amount < 1)
 		return 6;
@@ -1136,9 +1067,6 @@ int Character::getArmorClass(bool baseOnly) const {
 	return MAX(result, 0);
 }
 
-/**
- * Returns the thievery skill level, adjusted by class and race
- */
 int Character::getThievery() const {
 	int result = getCurrentLevel() * 2;
 
@@ -1258,9 +1186,6 @@ int Character::itemScan(int itemId) const {
 	return result;
 }
 
-/**
- * Modifies a passed attribute value based on player's condition
- */
 int Character::conditionMod(Attribute attrib) const {
 	if (_conditions[DEAD] || _conditions[STONED] || _conditions[ERADICATED])
 		return 0;
@@ -1829,9 +1754,6 @@ int Character::makeItem(int p1, int itemIndex, int p3) {
 	return category;
 }
 
-/**
- * Add hit points to a character
- */
 void Character::addHitPoints(int amount) {
 	Interface &intf = *Party::_vm->_interface;
 	Common::fill(&intf._charFX[0], &intf._charFX[MAX_ACTIVE_PARTY], 0);
@@ -1852,9 +1774,6 @@ void Character::addHitPoints(int amount) {
 	Common::fill(&intf._charFX[0], &intf._charFX[MAX_ACTIVE_PARTY], 0);
 }
 
-/**
- * Remove hit points fromo the character
- */
 void Character::subtractHitPoints(int amount) {
 	SoundManager &sound = *Party::_vm->_sound;
 	_currentHp -= amount;
diff --git a/engines/xeen/character.h b/engines/xeen/character.h
index 83198a1..903d8fa 100644
--- a/engines/xeen/character.h
+++ b/engines/xeen/character.h
@@ -124,24 +124,42 @@ public:
 
 	void clear();
 
+	/**
+	 * Return whether a given item passes class-based usage restrictions
+	 */
 	bool passRestrictions(int itemId, bool showError) const;
 
+	/**
+	 * Return the bare name of a given inventory item
+	 */
 	Common::String getName(int itemIndex);
 
 	virtual Common::String getFullDescription(int itemIndex, int displayNum = 15) = 0;
 
 	Common::String getIdentifiedDetails(int itemIndex);
 
+	/**
+	 * Discard an item from the inventory
+	 */
 	bool discardItem(int itemIndex);
 
 	virtual void equipItem(int itemIndex) {}
 
+	/**
+	 * Un-equips the given item
+	 */
 	void removeItem(int itemIndex);
 
+	/**
+	 * Sorts the items list, removing any empty item slots to the end of the array
+	 */
 	void sort();
 
 	virtual void enchantItem(int itemIndex, int amount);
 
+	/**
+	 * Return if the given inventory items list is full
+	 */
 	bool isFull() const;
 };
 
@@ -152,8 +170,15 @@ public:
 	WeaponItems(Character *character) : InventoryItems(character, CATEGORY_WEAPON) {}
 	virtual ~WeaponItems() {}
 
+	/**
+	 * Equip a given weapon
+	 */
 	virtual void equipItem(int itemIndex);
 
+	/**
+	 * Assembles a full lines description for a specified item for use in
+	 * the Items dialog
+	 */
 	virtual Common::String getFullDescription(int itemIndex, int displayNum);
 
 	virtual void enchantItem(int itemIndex, int amount);
@@ -166,8 +191,15 @@ public:
 	ArmorItems(Character *character) : InventoryItems(character, CATEGORY_ARMOR) {}
 	virtual ~ArmorItems() {}
 
+	/**
+	 * Equip a given piece of armor
+	 */
 	virtual void equipItem(int itemIndex);
 
+	/**
+	 * Assembles a full lines description for a specified item for use in
+	 * the Items dialog
+	 */
 	virtual Common::String getFullDescription(int itemIndex, int displayNum);
 
 	virtual void enchantItem(int itemIndex, int amount);
@@ -179,8 +211,15 @@ protected:
 public:
 	AccessoryItems(Character *character) : InventoryItems(character, CATEGORY_ACCESSORY) {}
 
+	/**
+	 * Equip a given accessory
+	 */
 	virtual void equipItem(int itemIndex);
 
+	/**
+	 * Assembles a full lines description for a specified item for use in
+	 * the Items dialog
+	 */
 	virtual Common::String getFullDescription(int itemIndex, int displayNum);
 };
 
@@ -191,6 +230,10 @@ public:
 	MiscItems(Character *character) : InventoryItems(character, CATEGORY_MISC) {}
 	virtual ~MiscItems() {}
 
+	/**
+	 * Assembles a full lines description for a specified item for use in
+	 * the Items dialog
+	 */
 	virtual Common::String getFullDescription(int itemIndex, int displayNum);
 };
 
@@ -203,6 +246,9 @@ public:
 
 	InventoryItems &operator[](ItemCategory category);
 
+	/**
+	 * Breaks all the items in a given character's inventory
+	 */
 	void breakAllItems();
 };
 
@@ -218,6 +264,9 @@ public:
 
 class Character {
 private:
+	/**
+	 * Modifies a passed attribute value based on player's condition
+	 */
 	int conditionMod(Attribute attrib) const;
 public:
 	Common::String _name;
@@ -275,22 +324,44 @@ public:
 
 	void synchronize(Common::Serializer &s);
 
+	/**
+	 * Returns the worst condition the character is suffering from
+	 */
 	Condition worstCondition() const;
 
+	/**
+	 * Returns whether the given character has a disabling condition, but still alive
+	 */
 	bool isDisabled() const;
 
+	/**
+	 * Returns whether the given character has a disabling condition, or is dead
+	 */
 	bool isDisabledOrDead() const;
 
+	/**
+	 * Returns whether the given character has a dead condition
+	 */
 	bool isDead() const;
 
+	/**
+	 * Get the character's age
+	 */
 	int getAge(bool ignoreTemp = false) const;
 
 	int getMaxHP() const;
 
 	int getMaxSP() const;
 
+	/**
+	 * Get the effective value of a given stat for the character
+	 */
 	uint getStat(Attribute attrib, bool baseOnly = false) const;
 
+	/**
+	 * Return the color number to use for a given stat value in the character
+	 * info or quick reference dialogs
+	 */
 	static int statColor(int amount, int threshold);
 
 	int statBonus(uint statValue) const;
@@ -305,6 +376,9 @@ public:
 
 	int getArmorClass(bool baseOnly = false) const;
 
+	/**
+	 * Returns the thievery skill level, adjusted by class and race
+	 */
 	int getThievery() const;
 
 	uint getCurrentLevel() const;
@@ -327,8 +401,14 @@ public:
 
 	int makeItem(int p1, int itemIndex, int p3);
 
+	/**
+	 * Add hit points to a character
+	 */
 	void addHitPoints(int amount);
 
+	/**
+	 * Remove hit points fromo the character
+	 */
 	void subtractHitPoints(int amount);
 
 	bool hasSpecialItem() const;
diff --git a/engines/xeen/combat.cpp b/engines/xeen/combat.cpp
index c8cece7..3faff3d 100644
--- a/engines/xeen/combat.cpp
+++ b/engines/xeen/combat.cpp
@@ -256,9 +256,6 @@ loop:
 	}
 }
 
-/**
- * Do damage to a specific character
- */
 void Combat::doCharDamage(Character &c, int charNum, int monsterDataIndex) {
 	EventsManager &events = *_vm->_events;
 	Interface &intf = *_vm->_interface;
@@ -664,9 +661,6 @@ void Combat::setupMonsterAttack(int monsterDataIndex, const Common::Point &pt) {
 	}
 }
 
-/**
- * Determines whether a given monster can move
- */
 bool Combat::monsterCanMove(const Common::Point &pt, int wallShift,
 		int xDiff, int yDiff, int monsterId) {
 	Map &map = *_vm->_map;
@@ -709,9 +703,6 @@ bool Combat::monsterCanMove(const Common::Point &pt, int wallShift,
 	}
 }
 
-/**
- * Moves a monster by a given delta amount if it's a valid move
- */
 void Combat::moveMonster(int monsterId, const Common::Point &moveDelta) {
 	Map &map = *_vm->_map;
 	MazeMonster &monster = map._mobData._monsters[monsterId];
@@ -1062,9 +1053,6 @@ int Combat::stopAttack(const Common::Point &diffPt) {
 	}
 }
 
-/**
- * Setup the combat party with a copy of the currently active party
- */
 void Combat::setupCombatParty() {
 	Party &party = *_vm->_party;
 
@@ -1123,9 +1111,6 @@ void Combat::setSpeedTable() {
 	}
 }
 
-/**
- * Returns true if all participants in the combat are disabled
- */
 bool Combat::allHaveGone() const {
 	for (uint idx = 0; idx < _charsGone.size(); ++idx) {
 		if (!_charsGone[idx]) {
@@ -1142,9 +1127,6 @@ bool Combat::allHaveGone() const {
 	return true;
 }
 
-/**
- * Returns true if all the characters of the party are disabled
- */
 bool Combat::charsCantAct() const {
 	for (uint idx = 0; idx < _combatParty.size(); ++idx) {
 		if (!_combatParty[idx]->isDisabledOrDead())
@@ -1154,9 +1136,6 @@ bool Combat::charsCantAct() const {
 	return true;
 }
 
-/**
- * Return a description of the monsters being faced
- */
 Common::String Combat::getMonsterDescriptions() {
 	Map &map = *_vm->_map;
 	Common::String lines[3];
@@ -1583,16 +1562,10 @@ void Combat::attack2(int damage, RangeType rangeType) {
 	}
 }
 
-/**
- * Flag the currently active character as blocking/defending
- */
 void Combat::block() {
 	_charsBlocked[_whosTurn] = true;
 }
 
-/**
- * Perform whatever the current combat character's quick action is
- */
 void Combat::quickFight() {
 	Spells &spells = *_vm->_spells;
 	Character *c = _combatParty[_whosTurn];
@@ -1617,9 +1590,6 @@ void Combat::quickFight() {
 	}
 }
 
-/**
- * Current selected character is trying to run away
- */
 void Combat::run() {
 	Map &map = *_vm->_map;
 	SoundManager &sound = *_vm->_sound;
@@ -1803,9 +1773,6 @@ int Combat::getMonsterResistence(RangeType rangeType) {
 	return damage;
 }
 
-/**
- * Distribute experience between active party members
- */
 void Combat::giveExperience(int experience) {
 	Party &party = *_vm->_party;
 	bool inCombat = _vm->_mode == MODE_COMBAT;
@@ -2089,9 +2056,6 @@ done:
 	party.giveTreasure();
 }
 
-/**
- * Fires off a ranged attack at all oncoming monsters
- */
 void Combat::shootRangedWeapon() {
 	_rangeType = RT_ALL;
 	_damageType = DT_PHYSICAL;
diff --git a/engines/xeen/combat.h b/engines/xeen/combat.h
index 33309b2..1a1fc3a 100644
--- a/engines/xeen/combat.h
+++ b/engines/xeen/combat.h
@@ -88,6 +88,9 @@ private:
 
 	int getMonsterResistence(RangeType rangeType);
 
+	/**
+	 * Distribute experience between active party members
+	 */
 	void giveExperience(int experience);
 public:
 	Common::Array<Character *> _combatParty;
@@ -136,35 +139,65 @@ public:
 
 	void giveCharDamage(int damage, DamageType attackType, int charIndex);
 
+	/**
+	 * Do damage to a specific character
+	 */
 	void doCharDamage(Character &c, int charNum, int monsterDataIndex);
 
 	void moveMonsters();
 
+	/**
+	 * Setup the combat party with a copy of the currently active party
+	 */
 	void setupCombatParty();
 
 	void setSpeedTable();
 
+	/**
+	 * Returns true if all participants in the combat are disabled
+	 */
 	bool allHaveGone() const;
 
+	/**
+	 * Returns true if all the characters of the party are disabled
+	 */
 	bool charsCantAct() const;
 
+	/**
+	 * Return a description of the monsters being faced
+	 */
 	Common::String getMonsterDescriptions();
 
 	void attack(Character &c, RangeType rangeType);
 
+	/**
+	 * Flag the currently active character as blocking/defending
+	 */
 	void block();
 
+	/**
+	 * Perform whatever the current combat character's quick action is
+	 */
 	void quickFight();
 
+	/**
+	 * Current selected character is trying to run away
+	 */
 	void run();
 
 	void monstersAttack();
 
 	void setupMonsterAttack(int monsterDataIndex, const Common::Point &pt);
 
+	/**
+	 * Determines whether a given monster can move
+	 */
 	bool monsterCanMove(const Common::Point &pt, int wallShift,
 		int v1, int v2, int monsterId);
 
+	/**
+	 * Moves a monster by a given delta amount if it's a valid move
+	 */
 	void moveMonster(int monsterId, const Common::Point &moveDelta);
 
 	void doMonsterTurn(int monsterId);
@@ -177,6 +210,9 @@ public:
 
 	void multiAttack(int powNum);
 
+	/**
+	 * Fires off a ranged attack at all oncoming monsters
+	 */
 	void shootRangedWeapon();
 };
 
diff --git a/engines/xeen/dialogs.cpp b/engines/xeen/dialogs.cpp
index 77cdd92..4ecd1c7 100644
--- a/engines/xeen/dialogs.cpp
+++ b/engines/xeen/dialogs.cpp
@@ -29,9 +29,6 @@
 
 namespace Xeen {
 
-/**
- * Saves the current list of buttons
- */
 void ButtonContainer::saveButtons() {
 	_savedButtons.push(_buttons);
 	clearButtons();
@@ -100,10 +97,6 @@ bool ButtonContainer::checkEvents(XeenEngine *vm) {
 	return false;
 }
 
-
-/**
-* Draws the scroll in the background
-*/
 void ButtonContainer::doScroll(XeenEngine *vm, bool drawFlag, bool doFade) {
 	Screen &screen = *vm->_screen;
 	EventsManager &events = *vm->_events;
@@ -205,9 +198,6 @@ void ButtonContainer::doScroll(XeenEngine *vm, bool drawFlag, bool doFade) {
 		delete hand[i];
 }
 
-/**
- * Draws the buttons onto the passed surface
- */
 void ButtonContainer::drawButtons(XSurface *surface) {
 	for (uint btnIndex = 0; btnIndex < _buttons.size(); ++btnIndex) {
 		UIButton &btn = _buttons[btnIndex];
diff --git a/engines/xeen/dialogs.h b/engines/xeen/dialogs.h
index 6e809ba..51eafa5 100644
--- a/engines/xeen/dialogs.h
+++ b/engines/xeen/dialogs.h
@@ -53,12 +53,18 @@ protected:
 	Common::Array<UIButton> _buttons;
 	int _buttonValue;
 
+	/**
+	 * Draws the scroll in the background
+	 */
 	void doScroll(XeenEngine *vm, bool drawFlag, bool doFade);
 
 	bool checkEvents(XeenEngine *vm);
 public:
 	ButtonContainer() : _buttonValue(0) {}
 
+	/**
+	 * Saves the current list of buttons
+	 */
 	void saveButtons();
 
 	void clearButtons();
@@ -71,6 +77,9 @@ public:
 
 	void addPartyButtons(XeenEngine *vm);
 
+	/**
+	 * Draws the buttons onto the passed surface
+	 */
 	void drawButtons(XSurface *surface);
 };
 
diff --git a/engines/xeen/dialogs_char_info.cpp b/engines/xeen/dialogs_char_info.cpp
index c00916c..0494c22 100644
--- a/engines/xeen/dialogs_char_info.cpp
+++ b/engines/xeen/dialogs_char_info.cpp
@@ -213,9 +213,6 @@ exit:
 	_vm->_combat->_itemFlag = false;
 }
 
-/**
- * Load the draw structure list with frame numbers and positions
- */
 void CharacterInfo::loadDrawStructs() {
 	_drawList[0] = DrawStruct(0, 2, 16);
 	_drawList[1] = DrawStruct(2, 2, 39);
@@ -247,9 +244,6 @@ void CharacterInfo::loadDrawStructs() {
 		_drawList[idx]._sprites = &_iconSprites;
 }
 
-/**
- * Set up the button list for the dialog
- */
 void CharacterInfo::addButtons() {
 	addButton(Common::Rect(10, 24, 34, 44), 1001, &_iconSprites);
 	addButton(Common::Rect(10, 47, 34, 67), 1002, &_iconSprites);
@@ -278,9 +272,6 @@ void CharacterInfo::addButtons() {
 	addPartyButtons(_vm);
 }
 
-/**
- * Return a string containing the details of the character
- */
 Common::String CharacterInfo::loadCharacterDetails(const Character &c) {
 	Condition condition = c.worstCondition();
 	Party &party = *_vm->_party;
@@ -324,9 +315,6 @@ Common::String CharacterInfo::loadCharacterDetails(const Character &c) {
 	);
 }
 
-/**
- * Cursor display handling
- */
 void CharacterInfo::showCursor(bool flag) {
 	Screen &screen = *_vm->_screen;
 	const int CURSOR_X[5] = { 9, 60, 111, 176, 0 };
diff --git a/engines/xeen/dialogs_char_info.h b/engines/xeen/dialogs_char_info.h
index 5a20ff2..90b35a9 100644
--- a/engines/xeen/dialogs_char_info.h
+++ b/engines/xeen/dialogs_char_info.h
@@ -40,12 +40,24 @@ private:
 
 	void execute(int charIndex);
 
+	/**
+	 * Load the draw structure list with frame numbers and positions
+	 */
 	void loadDrawStructs();
 
+	/**
+	 * Set up the button list for the dialog
+	 */
 	void addButtons();
 
+	/**
+	 * Return a string containing the details of the character
+	 */
 	Common::String loadCharacterDetails(const Character &c);
 
+	/**
+	 * Cursor display handling
+	 */
 	void showCursor(bool flag);
 
 	bool expandStat(int attrib, const Character &c);
diff --git a/engines/xeen/dialogs_input.cpp b/engines/xeen/dialogs_input.cpp
index eec6088..5833733 100644
--- a/engines/xeen/dialogs_input.cpp
+++ b/engines/xeen/dialogs_input.cpp
@@ -35,9 +35,6 @@ int Input::show(XeenEngine *vm, Window *window, Common::String &line,
 	return result;
 }
 
-/**
- * Allows the user to enter a string
- */
 int Input::getString(Common::String &line, uint maxLen, int maxWidth, bool isNumeric) {
 	_vm->_noDirectionSense = true;
 	Common::String msg = Common::String::format("\x3""l\t000\x4%03d\x0""c", maxWidth);
@@ -75,9 +72,6 @@ int Input::getString(Common::String &line, uint maxLen, int maxWidth, bool isNum
 	return line.size();
 }
 
-/**
- * Draws the cursor and waits until the user presses a key
- */
 Common::KeyCode Input::doCursor(const Common::String &msg) {
 	EventsManager &events = *_vm->_events;
 	Interface &intf = *_vm->_interface;
diff --git a/engines/xeen/dialogs_input.h b/engines/xeen/dialogs_input.h
index 2f30b73..e824d17 100644
--- a/engines/xeen/dialogs_input.h
+++ b/engines/xeen/dialogs_input.h
@@ -31,11 +31,17 @@ namespace Xeen {
 
 class Input : public ButtonContainer {
 private:
+	/**
+	 * Draws the cursor and waits until the user presses a key
+	 */
 	Common::KeyCode doCursor(const Common::String &msg);
 protected:
 	XeenEngine *_vm;
 	Window *_window;
 
+	/**
+	 * Allows the user to enter a string
+	 */
 	int getString(Common::String &line, uint maxLen, int maxWidth, bool isNumeric);
 
 	Input(XeenEngine *vm, Window *window) : _vm(vm), _window(window) {}
diff --git a/engines/xeen/dialogs_items.cpp b/engines/xeen/dialogs_items.cpp
index 147f934..4ad9e24 100644
--- a/engines/xeen/dialogs_items.cpp
+++ b/engines/xeen/dialogs_items.cpp
@@ -513,9 +513,6 @@ Character *ItemsDialog::execute(Character *c, ItemsMode mode) {
 	return c;
 }
 
-/**
- * Load the buttons for the dialog
- */
 void ItemsDialog::loadButtons(ItemsMode mode, Character *&c) {
 	_iconSprites.load(Common::String::format("%s.icn",
 		(mode == ITEMMODE_CHAR_INFO) ? "items" : "buy"));
@@ -580,11 +577,6 @@ void ItemsDialog::loadButtons(ItemsMode mode, Character *&c) {
 	}
 }
 
-/**
- * Loads the temporary _itemsCharacter character with the item set
- * the given blacksmith has available, so the user can "view" the
- * set as if it were a standard character's inventory
- */
 void ItemsDialog::blackData2CharData() {
 	Party &party = *_vm->_party;
 	bool isDarkCc = _vm->_files->_isDarkCc;
@@ -602,10 +594,6 @@ void ItemsDialog::blackData2CharData() {
 	}
 }
 
-/**
-* Saves the inventory from the temporary _itemsCharacter character back into the
-* blacksmith storage, so changes in blacksmith inventory remain persistent
-*/
 void ItemsDialog::charData2BlackData() {
 	Party &party = *_vm->_party;
 	bool isDarkCc = _vm->_files->_isDarkCc;
@@ -623,9 +611,6 @@ void ItemsDialog::charData2BlackData() {
 	}
 }
 
-/**
- * Sets the equipment icon to use for each item for display
- */
 void ItemsDialog::setEquipmentIcons() {
 	for (int typeIndex = 0; typeIndex < 4; ++typeIndex) {
 		for (int idx = 0; idx < INV_ITEMS_TOTAL; ++idx) {
@@ -676,9 +661,6 @@ void ItemsDialog::setEquipmentIcons() {
 	}
 }
 
-/**
- * Calculate the cost of an item
- */
 int ItemsDialog::calcItemCost(Character *c, int itemIndex, ItemsMode mode,
 		int skillLevel, ItemCategory category) {
 	int amount1 = 0, amount2 = 0, amount3 = 0, amount4 = 0;
diff --git a/engines/xeen/dialogs_items.h b/engines/xeen/dialogs_items.h
index bc995c5..6069ca8 100644
--- a/engines/xeen/dialogs_items.h
+++ b/engines/xeen/dialogs_items.h
@@ -49,14 +49,32 @@ private:
 
 	Character *execute(Character *c, ItemsMode mode);
 
+	/**
+	 * Load the buttons for the dialog
+	 */
 	void loadButtons(ItemsMode mode, Character *&c);
 
+	/**
+	 * Loads the temporary _itemsCharacter character with the item set
+	 * the given blacksmith has available, so the user can "view" the
+	 * set as if it were a standard character's inventory
+	 */
 	void blackData2CharData();
 
+	/**
+	 * Saves the inventory from the temporary _itemsCharacter character back into the
+	 * blacksmith storage, so changes in blacksmith inventory remain persistent
+	 */
 	void charData2BlackData();
 
+	/**
+	 * Sets the equipment icon to use for each item for display
+	 */
 	void setEquipmentIcons();
 
+	/**
+	 * Calculate the cost of an item
+	 */
 	int calcItemCost(Character *c, int itemIndex, ItemsMode mode, int skillLevel, 
 		ItemCategory category);
 
diff --git a/engines/xeen/dialogs_party.cpp b/engines/xeen/dialogs_party.cpp
index 69761bb..18f5f3a 100644
--- a/engines/xeen/dialogs_party.cpp
+++ b/engines/xeen/dialogs_party.cpp
@@ -295,9 +295,6 @@ void PartyDialog::setupBackground() {
 	_vm->_interface->assembleBorder();
 }
 
-/**
- * Sets up the faces from the avaialble roster for display in the party dialog
- */
 void PartyDialog::setupFaces(int firstDisplayChar, bool updateFlag) {
 	Party &party = *_vm->_party;
 	Common::String charNames[4];
@@ -765,10 +762,6 @@ int PartyDialog::selectCharacter(bool isDelete, int firstDisplayChar) {
 	return result == -1 ? 0 : result;
 }
 
-/**
- * Roll up some random values for the attributes, and return both them as
- * well as a list of classes that the attributes meet the requirements for
- */
 void PartyDialog::throwDice(uint attribs[TOTAL_ATTRIBUTES], bool allowedClasses[TOTAL_CLASSES]) {
 	bool repeat = true;
 	do {
@@ -793,10 +786,6 @@ void PartyDialog::throwDice(uint attribs[TOTAL_ATTRIBUTES], bool allowedClasses[
 	} while (repeat);
 }
 
-/**
- * Set a list of flags for which classes the passed attribute set meet the
- * minimum requirements of
- */
 void PartyDialog::checkClass(const uint attribs[TOTAL_ATTRIBUTES], bool allowedClasses[TOTAL_CLASSES]) {
 	allowedClasses[CLASS_KNIGHT] = attribs[MIGHT] >= 15;
 	allowedClasses[CLASS_PALADIN] = attribs[MIGHT] >= 13
@@ -812,9 +801,6 @@ void PartyDialog::checkClass(const uint attribs[TOTAL_ATTRIBUTES], bool allowedC
 		&& attribs[ENDURANCE] >= 12 && attribs[SPEED] >= 12;
 }
 
-/**
- * Return details of the generated character
- */
 int PartyDialog::newCharDetails(const uint attribs[TOTAL_ATTRIBUTES],
 		bool allowedClasses[TOTAL_CLASSES], Race race, Sex sex, int classId, 
 		int selectedClass, Common::String &msg) {
@@ -863,9 +849,6 @@ int PartyDialog::newCharDetails(const uint attribs[TOTAL_ATTRIBUTES],
 	return classId == -1 ? foundClass : selectedClass;
 }
 
-/**
- * Print the selection arrow to indicate the selected class
- */
 void PartyDialog::printSelectionArrow(SpriteResource &icons, int selectedClass) {
 	Window &w = _vm->_screen->_windows[0];
 	icons.draw(w, 61, Common::Point(220, 19));
@@ -873,9 +856,6 @@ void PartyDialog::printSelectionArrow(SpriteResource &icons, int selectedClass)
 	w.update();
 }
 
-/**
- * Print the dice animation
- */
 void PartyDialog::drawDice(SpriteResource &dice) {
 	EventsManager &events = *_vm->_events;
 	Window &w = _vm->_screen->_windows[32];
@@ -911,9 +891,6 @@ void PartyDialog::drawDice(SpriteResource &dice) {
 	checkEvents(_vm);
 }
 
-/**
- * Exchanging two attributes for the character being rolled
- */
 int PartyDialog::exchangeAttribute(int srcAttr) {
 	EventsManager &events = *_vm->_events;
 	Screen &screen = *_vm->_screen;
@@ -989,9 +966,6 @@ int PartyDialog::exchangeAttribute(int srcAttr) {
 	return result;
 }
 
-/**
- * Saves the rolled character into the roster
- */
 bool PartyDialog::saveCharacter(Character &c, CharacterClass classId,
 		Race race, Sex sex, uint attribs[TOTAL_ATTRIBUTES]) {
 	if (classId == -1) {
diff --git a/engines/xeen/dialogs_party.h b/engines/xeen/dialogs_party.h
index db2a3df..2ad2dae 100644
--- a/engines/xeen/dialogs_party.h
+++ b/engines/xeen/dialogs_party.h
@@ -52,6 +52,9 @@ private:
 
 	void setupBackground();
 
+	/**
+	 * Sets up the faces from the avaialble roster for display in the party dialog
+	 */
 	void setupFaces(int firstDisplayChar, bool updateFlag);
 
 	void startingCharChanged(int firstDisplayChar);
@@ -60,20 +63,43 @@ private:
 
 	int selectCharacter(bool isDelete, int firstDisplayChar);
 
+	/**
+	 * Roll up some random values for the attributes, and return both them as
+	 * well as a list of classes that the attributes meet the requirements for
+	 */
 	void throwDice(uint attribs[TOTAL_ATTRIBUTES], bool allowedClasses[TOTAL_CLASSES]);
 
+	/**
+	 * Set a list of flags for which classes the passed attribute set meet the
+	 * minimum requirements of
+	 */
 	void checkClass(const uint attribs[TOTAL_ATTRIBUTES], bool allowedClasses[TOTAL_CLASSES]);
 
+	/**
+	 * Return details of the generated character
+	 */
 	int newCharDetails(const uint attribs[TOTAL_ATTRIBUTES], 
 		bool allowedClasses[TOTAL_CLASSES], Race race, Sex sex, int classId,
 		int selectedClass, Common::String &msg);
 
+	/**
+	 * Print the selection arrow to indicate the selected class
+	 */
 	void printSelectionArrow(SpriteResource &icons, int selectedClass);
 
+	/**
+	 * Print the dice animation
+	 */
 	void drawDice(SpriteResource &dice);
 
+	/**
+	 * Exchanging two attributes for the character being rolled
+	 */
 	int exchangeAttribute(int srcAttr);
 
+	/**
+	 * Saves the rolled character into the roster
+	 */
 	bool saveCharacter(Character &c, CharacterClass classId, Race race,
 		Sex sex, uint attribs[TOTAL_ATTRIBUTES]);
 public:
diff --git a/engines/xeen/events.cpp b/engines/xeen/events.cpp
index 92dc8b4..0c0a32b 100644
--- a/engines/xeen/events.cpp
+++ b/engines/xeen/events.cpp
@@ -31,9 +31,6 @@
 
 namespace Xeen {
 
-/**
- * Constructor
- */
 EventsManager::EventsManager(XeenEngine *vm) : _vm(vm),
 		_frameCounter(0), _priorFrameCounterTime(0), _gameCounter(0),
 		_priorGameCounterTime(0), _keyCode(Common::KEYCODE_INVALID),
@@ -42,15 +39,9 @@ EventsManager::EventsManager(XeenEngine *vm) : _vm(vm),
 	Common::fill(&_gameCounters[0], &_gameCounters[6], 0);
 }
 
-/**
- * Destructor
- */
 EventsManager::~EventsManager() {
 }
 
-/*
- * Set the cursor
- */
 void EventsManager::setCursor(int cursorId) {
 	XSurface cursor;
 	_sprites.draw(cursor, cursorId);
@@ -59,23 +50,14 @@ void EventsManager::setCursor(int cursorId) {
 	showCursor();
 }
 
-/**
- * Show the mouse cursor
- */
 void EventsManager::showCursor() {
 	CursorMan.showMouse(true);
 }
 
-/**
- * Hide the mouse cursor
- */
 void EventsManager::hideCursor() {
 	CursorMan.showMouse(false);
 }
 
-/**
- * Returns if the mouse cursor is visible
- */
 bool EventsManager::isCursorVisible() {
 	return CursorMan.isVisible();
 }
@@ -154,9 +136,6 @@ bool EventsManager::isKeyPending() const {
 	return _keyCode != Common::KEYCODE_INVALID;
 }
 
-/**
- * Returns true if a key or mouse press is pending
- */
 bool EventsManager::isKeyMousePressed() {
 	bool result = _leftButton || _rightButton || isKeyPending();
 	debounceMouse();
@@ -183,9 +162,6 @@ void EventsManager::ipause(uint amount) {
 	} while (!_vm->shouldQuit() && timeElapsed() < amount);
 }
 
-/**
- * Handles moving to the next game frame
- */
 void EventsManager::nextFrame() {
 	++_frameCounter;
 
diff --git a/engines/xeen/events.h b/engines/xeen/events.h
index cce3155..6ebe46e 100644
--- a/engines/xeen/events.h
+++ b/engines/xeen/events.h
@@ -44,6 +44,9 @@ private:
 	Common::KeyCode _keyCode;
 	SpriteResource _sprites;
 
+	/**
+	 * Handles moving to the next game frame
+	 */
 	void nextFrame();
 public:
 	bool _leftButton, _rightButton;
@@ -53,12 +56,24 @@ public:
 
 	~EventsManager();
 
+	/*
+	 * Set the cursor
+	 */
 	void setCursor(int cursorId);
 
+	/**
+	 * Show the mouse cursor
+	 */
 	void showCursor();
 
+	/**
+	 * Hide the mouse cursor
+	 */
 	void hideCursor();
 
+	/**
+	 * Returns if the mouse cursor is visible
+	 */
 	bool isCursorVisible();
 
 	void pollEvents();
@@ -73,6 +88,9 @@ public:
 
 	bool isKeyPending() const;
 
+	/**
+	 * Returns true if a key or mouse press is pending
+	 */
 	bool isKeyMousePressed();
 
 	void updateGameCounter() { _gameCounter = _frameCounter; }
diff --git a/engines/xeen/files.cpp b/engines/xeen/files.cpp
index 50949b7..bcee6bf 100644
--- a/engines/xeen/files.cpp
+++ b/engines/xeen/files.cpp
@@ -29,9 +29,6 @@
 
 namespace Xeen {
 
-/**
-* Hash a given filename to produce the Id that represents it
-*/
 uint16 BaseCCArchive::convertNameToId(const Common::String &resourceName) {
 	if (resourceName.empty())
 		return 0xffff;
@@ -57,9 +54,6 @@ uint16 BaseCCArchive::convertNameToId(const Common::String &resourceName) {
 	return total;
 }
 
-/**
-* Load the index of a given CC file
-*/
 void BaseCCArchive::loadIndex(Common::SeekableReadStream *stream) {
 	int count = stream->readUint16LE();
 
@@ -95,10 +89,6 @@ bool BaseCCArchive::hasFile(const Common::String &name) const {
 	return getHeaderEntry(name, ccEntry);
 }
 
-/**
-* Given a resource name, returns whether an entry exists, and returns
-* the header index data for that entry
-*/
 bool BaseCCArchive::getHeaderEntry(const Common::String &resourceName, CCEntry &ccEntry) const {
 	uint16 id = convertNameToId(resourceName);
 
@@ -193,9 +183,6 @@ Common::SeekableReadStream *CCArchive::createReadStreamForMember(const Common::S
 
 /*------------------------------------------------------------------------*/
 
-/**
- * Instantiates the resource manager
- */
 FileManager::FileManager(XeenEngine *vm) {
 	Common::File f;
 	int sideNum = 0;
@@ -219,9 +206,6 @@ FileManager::FileManager(XeenEngine *vm) {
 
 /*------------------------------------------------------------------------*/
 
-/**
- * Opens the given file, throwing an error if it can't be opened
- */
 void File::openFile(const Common::String &filename) {
 	if (!Common::File::open(filename))
 		error("Could not open file - %s", filename.c_str());
diff --git a/engines/xeen/files.h b/engines/xeen/files.h
index f0c92d1..fc75031 100644
--- a/engines/xeen/files.h
+++ b/engines/xeen/files.h
@@ -56,6 +56,9 @@ public:
 	bool _isDarkCc;
 	CCArchive *_sideArchives[2];
 public:
+	/**
+	 * Instantiates the resource manager
+	 */
 	FileManager(XeenEngine *vm);
 
 	void setGameCc(bool isDarkCc) { _isDarkCc = isDarkCc; }
@@ -73,7 +76,14 @@ public:
 	}
 	virtual ~File() {}
 
+	/**
+	 * Opens the given file, throwing an error if it can't be opened
+	 */
 	void openFile(const Common::String &filename);
+
+	/**
+	 * Opens the given file, throwing an error if it can't be opened
+	 */
 	void openFile(const Common::String &filename, Common::Archive &archive);
 
 	Common::String readString();
@@ -112,10 +122,20 @@ class BaseCCArchive : public Common::Archive {
 protected:
 	Common::Array<CCEntry> _index;
 
+	/**
+	 * Load the index of a given CC file
+	 */
 	void loadIndex(Common::SeekableReadStream *stream);
 
+	/**
+	 * Given a resource name, returns whether an entry exists, and returns
+	 * the header index data for that entry
+	 */
 	virtual bool getHeaderEntry(const Common::String &resourceName, CCEntry &ccEntry) const;
 public:
+	/**
+	 * Hash a given filename to produce the Id that represents it
+	 */
 	static uint16 convertNameToId(const Common::String &resourceName);
 public:
 	BaseCCArchive() {}
diff --git a/engines/xeen/font.cpp b/engines/xeen/font.cpp
index bfdc4bd..87e16b5 100644
--- a/engines/xeen/font.cpp
+++ b/engines/xeen/font.cpp
@@ -37,10 +37,6 @@ FontSurface::FontSurface(int wv, int hv) : XSurface(wv, hv), _fontData(nullptr),
 	setTextColor(0);
 }
 
-/**
- * Draws a symbol to the surface.
- * @param symbolId	Symbol number from 0 to 19
- */
 void FontSurface::writeSymbol(int symbolId) {
 	const byte *srcP = &SYMBOLS[symbolId][0];
 
@@ -57,14 +53,6 @@ void FontSurface::writeSymbol(int symbolId) {
 	_writePos.x += 8;
 }
 
-/**
- * Write a string to the surface
- * @param s			String to display
- * @param clipRect	Window bounds to display string within
- * @returns			Any string remainder that couldn't be displayed
- * @remarks		Note that bounds is just used for wrapping purposes. Unless
- *		justification is set, the message will be written at _writePos
- */
 const char *FontSurface::writeString(const Common::String &s, const Common::Rect &bounds) {
 	_displayString = s.c_str();
 	assert(_fontData);
@@ -253,16 +241,10 @@ const char *FontSurface::writeString(const Common::String &s, const Common::Rect
 	return _displayString;
 }
 
-/**
- * Return the next pending character to display
- */
 char FontSurface::getNextChar() {
 	return  *_displayString++ & 0x7f;
 }
 
-/**
-* Return the width of a given character
-*/
 bool FontSurface::getNextCharWidth(int &total) {
 	char c = getNextChar();
 
@@ -292,9 +274,6 @@ bool FontSurface::getNextCharWidth(int &total) {
 	}
 }
 
-/**
- * Handles moving to the next line of the given bounded area
- */
 bool FontSurface::newLine(const Common::Rect &bounds) {
 	// Move past any spaces currently being pointed to
 	while ((*_displayString & 0x7f) == ' ')
@@ -309,9 +288,6 @@ bool FontSurface::newLine(const Common::Rect &bounds) {
 	return ((_writePos.y + hv - 1) > bounds.bottom);
 }
 
-/**
- * Extract a number of a given maximum length from the string
- */
 int FontSurface::fontAtoi(int len) {
 	int total = 0;
 	for (int i = 0; i < len; ++i) {
@@ -329,17 +305,11 @@ int FontSurface::fontAtoi(int len) {
 	return total;
 }
 
-/**
- * Set the text colors based on the specified index in the master text colors list
- */
 void FontSurface::setTextColor(int idx) {
 	const byte *colP = &TEXT_COLORS[idx][0];
 	Common::copy(colP, colP + 4, &_textColors[0]);
 }
 
-/**
- * Wrie a character to the surface
- */
 void FontSurface::writeChar(char c, const Common::Rect &clipRect) {
 	// Get y position, handling kerning
 	int y = _writePos.y;
diff --git a/engines/xeen/font.h b/engines/xeen/font.h
index caaa03c..021205d 100644
--- a/engines/xeen/font.h
+++ b/engines/xeen/font.h
@@ -38,16 +38,34 @@ private:
 	const char *_displayString;
 	bool _msgWraps;
 
+	/**
+	 * Return the next pending character to display
+	 */
 	char getNextChar();
 
+	/**
+	 * Return the width of a given character
+	 */
 	bool getNextCharWidth(int &total);
 
+	/**
+	 * Handles moving to the next line of the given bounded area
+	 */
 	bool newLine(const Common::Rect &bounds);
 
+	/**
+	 * Extract a number of a given maximum length from the string
+	 */
 	int fontAtoi(int len = 3);
 
+	/**
+	 * Set the text colors based on the specified index in the master text colors list
+	 */
 	void setTextColor(int idx);
 
+	/**
+	 * Wrie a character to the surface
+	 */
 	void writeChar(char c, const Common::Rect &clipRect);
 public:
 	const byte *_fontData;
@@ -61,8 +79,20 @@ public:
 	FontSurface(int wv, int hv);
 	virtual ~FontSurface() {}
 
+	/**
+	 * Draws a symbol to the surface.
+	 * @param symbolId	Symbol number from 0 to 19
+	 */
 	void writeSymbol(int symbolId);
 
+	/**
+	 * Write a string to the surface
+	 * @param s			String to display
+	 * @param clipRect	Window bounds to display string within
+	 * @returns			Any string remainder that couldn't be displayed
+	 * @remarks		Note that bounds is just used for wrapping purposes. Unless
+	 *		justification is set, the message will be written at _writePos
+	 */
 	const char *writeString(const Common::String &s, const Common::Rect &clipRect);
 };
 
diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp
index f9f1eeb..3225831 100644
--- a/engines/xeen/interface.cpp
+++ b/engines/xeen/interface.cpp
@@ -259,10 +259,6 @@ void Interface::setMainButtons(bool combatMode) {
 	}
 }
 
-/**
- * Waits for a keypress or click, whilst still allowing the game scene to
- * be animated.
- */
 void Interface::perform() {
 	Combat &combat = *_vm->_combat;
 	EventsManager &events = *_vm->_events;
@@ -621,9 +617,6 @@ void Interface::chargeStep() {
 	}
 }
 
-/**
- * Handles incrementing game time
- */
 void Interface::stepTime() {
 	Party &party = *_vm->_party;
 	SoundManager &sound = *_vm->_sound;
@@ -714,9 +707,6 @@ void Interface::doStepCode() {
 	}
 }
 
-/**
- * Start the party falling
- */
 void Interface::startFalling(bool flag) {
 	Combat &combat = *_vm->_combat;
 	Map &map = *_vm->_map;
@@ -931,9 +921,6 @@ void Interface::startFalling(bool flag) {
 	_flipGround ^= 1;
 }
 
-/**
- * Check movement in the given direction
- */
 bool Interface::checkMoveDirection(int key) {
 	Map &map = *_vm->_map;
 	Party &party = *_vm->_party;
@@ -1316,9 +1303,6 @@ void Interface::draw3d(bool updateFlag, bool skipDelay) {
 		events.wait(2);
 }
 
-/**
- * Handle doing the falling
- */
 void Interface::handleFalling() {
 	Party &party = *_vm->_party;
 	Screen &screen = *_vm->_screen;
@@ -1375,19 +1359,13 @@ void Interface::saveFall() {
 }
 
 void Interface::fall(int v) {
-
+	// TODO
 }
 
-/**
- * Shake the screen
- */
 void Interface::shake(int time) {
-
+	// TODO
 }
 
-/**
- * Draw the minimap
- */
 void Interface::drawMiniMap() {
 	Map &map = *_vm->_map;
 	Party &party = *_vm->_party;
@@ -1765,9 +1743,6 @@ void Interface::drawMiniMap() {
 	party._wizardEyeActive = eyeActive;
 }
 
-/**
- * Draw the display borders
- */
 void Interface::assembleBorder() {
 	Combat &combat = *_vm->_combat;
 	Resources &res = *_vm->_resources;
@@ -2186,9 +2161,6 @@ void Interface::doCombat() {
 	combat._combatMode = COMBATMODE_1;
 }
 
-/**
- * Select next character or monster to be attacking
- */
 void Interface::nextChar() {
 	Combat &combat = *_vm->_combat;
 	Party &party = *_vm->_party;
diff --git a/engines/xeen/interface.h b/engines/xeen/interface.h
index 24edf9d..074d7fd 100644
--- a/engines/xeen/interface.h
+++ b/engines/xeen/interface.h
@@ -90,22 +90,40 @@ private:
 
 	void chargeStep();
 
+	/**
+	 * Handles incrementing game time
+	 */
 	void stepTime();
 
 	void doStepCode();
 
+	/**
+	 * Check movement in the given direction
+	 */
 	bool checkMoveDirection(int key);
 
+	/**
+	 * Handle doing the falling
+	 */
 	void handleFalling();
 
 	void saveFall();
 
 	void fall(int v);
 
+	/**
+	 * Shake the screen
+	 */
 	void shake(int time);
 
+	/**
+	 * Draw the minimap
+	 */
 	void drawMiniMap();
 
+	/**
+	 * Select next character or monster to be attacking
+	 */
 	void nextChar();
 public:
 	int _intrIndex1;
@@ -133,8 +151,15 @@ public:
 
 	void mainIconsPrint();
 
+	/**
+	 * Start the party falling
+	 */
 	void startFalling(bool v);
 
+	/**
+	 * Waits for a keypress or click, whilst still allowing the game scene to
+	 * be animated.
+	 */
 	void perform();
 
 	void rest();
@@ -143,6 +168,9 @@ public:
 
 	void draw3d(bool updateFlag, bool skipDelay = false);
 
+	/**
+	 * Draw the display borders
+	 */
 	void assembleBorder();
 
 	void doCombat();
diff --git a/engines/xeen/interface_map.cpp b/engines/xeen/interface_map.cpp
index a08ce80..f5bf2af 100644
--- a/engines/xeen/interface_map.cpp
+++ b/engines/xeen/interface_map.cpp
@@ -690,10 +690,6 @@ void InterfaceMap::drawMap() {
 	animate3d();
 }
 
-/**
- * Handles animation of monsters, wall items, and combat within the 3d
- * view by cycling the appropriate frame numbers
- */
 void InterfaceMap::animate3d() {
 	Combat &combat = *_vm->_combat;
 	Map &map = *_vm->_map;
@@ -2304,9 +2300,6 @@ void InterfaceMap::setMazeBits() {
 	}
 }
 
-/**
- * Set up draw structures for displaying on-screen monsters
- */
 void InterfaceMap::setIndoorsMonsters() {
 	Combat &combat = *_vm->_combat;
 	Map &map = *_vm->_map;
@@ -2616,10 +2609,6 @@ void InterfaceMap::setIndoorsMonsters() {
 	}
 }
 
-/**
- * Helper method for setIndoorsMonsters to set a draw structure
- * with the deatils for a given monster
- */
 void InterfaceMap::setMonsterSprite(DrawStruct &drawStruct, MazeMonster &monster, SpriteResource *sprites, 
 		int frame, int defaultY) {
 	MonsterStruct &monsterData = *monster._monsterData;
@@ -2641,9 +2630,6 @@ void InterfaceMap::setMonsterSprite(DrawStruct &drawStruct, MazeMonster &monster
 		drawStruct._flags = MONSTER_EFFECT_FLAGS[monster._effect2][monster._effect3];
 }
 
-/**
- * Set up draw structures for displaying on-screen objects
- */
 void InterfaceMap::setIndoorsObjects() {
 	Common::Point mazePos = _vm->_party->_mazePosition;
 	Direction dir = _vm->_party->_mazeDirection;
@@ -2869,9 +2855,6 @@ void InterfaceMap::setIndoorsObjects() {
 	}
 }
 
-/**
- * Set up draw structures for displaying on-screen wall items
- */
 void InterfaceMap::setIndoorsWallPics() {
 	Map &map = *_vm->_map;
 	const Common::Point &mazePos = _vm->_party->_mazePosition;
@@ -3098,9 +3081,6 @@ void InterfaceMap::setIndoorsWallPics() {
 	}
 }
 
-/**
- * Set up the draw structures for displaying monsters on outdoor maps
- */
 void InterfaceMap::setOutdoorsMonsters() {
 	Combat &combat = *_vm->_combat;
 	Map &map = *_vm->_map;
@@ -3354,9 +3334,6 @@ void InterfaceMap::setOutdoorsMonsters() {
 	// TODO
 }
 
-/**
- * Set up the draw structures for displaying objects on outdoor maps
- */
 void InterfaceMap::setOutdoorsObjects() {
 	Map &map = *_vm->_map;
 	Party &party = *_vm->_party;
@@ -3544,9 +3521,6 @@ void InterfaceMap::setOutdoorsObjects() {
 	}
 }
 
-/**
- * Draw the contents of the current 3d view of an indoor map
- */
 void InterfaceMap::drawIndoors() {
 	Map &map = *_vm->_map;
 	int surfaceId;
@@ -4393,9 +4367,6 @@ void InterfaceMap::drawIndoors() {
 	_charsShooting = _isAttacking;
 }
 
-/**
- * Draw the contents of the current 3d view of an outdoor map
- */
 void InterfaceMap::drawOutdoors() {
 	Map &map = *_vm->_map;
 	Party &party = *_vm->_party;
diff --git a/engines/xeen/interface_map.h b/engines/xeen/interface_map.h
index a37bf34..2189aac 100644
--- a/engines/xeen/interface_map.h
+++ b/engines/xeen/interface_map.h
@@ -95,6 +95,10 @@ private:
 
 	void initDrawStructs();
 
+	/**
+	 * Helper method for setIndoorsMonsters to set a draw structure
+	 * with the deatils for a given monster
+	 */
 	void setMonsterSprite(DrawStruct &drawStruct, MazeMonster &monster, 
 		SpriteResource *sprites, int frame, int defaultY);
 protected:
@@ -109,6 +113,10 @@ protected:
 
 	void setMazeBits();
 
+	/**
+	 * Handles animation of monsters, wall items, and combat within the 3d
+	 * view by cycling the appropriate frame numbers
+	 */
 	void animate3d();
 
 	void drawMap();
@@ -126,18 +134,39 @@ public:
 
 	virtual ~InterfaceMap() {}
 
+	/**
+	 * Set up draw structures for displaying on-screen monsters
+	 */
 	void setIndoorsMonsters();
 
+	/**
+	 * Set up draw structures for displaying on-screen objects
+	 */
 	void setIndoorsObjects();
 
+	/**
+	 * Set up draw structures for displaying on-screen wall items
+	 */
 	void setIndoorsWallPics();
 
+	/**
+	 * Draw the contents of the current 3d view of an indoor map
+	 */
 	void drawIndoors();
 
+	/**
+	 * Set up the draw structures for displaying monsters on outdoor maps
+	 */
 	void setOutdoorsMonsters();
 
+	/**
+	 * Set up the draw structures for displaying objects on outdoor maps
+	 */
 	void setOutdoorsObjects();
 
+	/**
+	 * Draw the contents of the current 3d view of an outdoor map
+	 */
 	void drawOutdoors();
 };
 
diff --git a/engines/xeen/map.cpp b/engines/xeen/map.cpp
index ff79387..6816423 100644
--- a/engines/xeen/map.cpp
+++ b/engines/xeen/map.cpp
@@ -603,9 +603,6 @@ void MazeData::synchronize(Common::SeekableReadStream &s) {
 		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);
@@ -663,10 +660,6 @@ MazeMonster::MazeMonster() {
 	_monsterData = nullptr;
 }
 
-/**
- * Return the text color to use when displaying the monster's name in combat
- * to indicate how damaged they are
- */
 int MazeMonster::getTextColor() const {
 	if (_hp == _monsterData->_hp)
 		return 15;
@@ -843,9 +836,6 @@ void HeadData::synchronize(Common::SeekableReadStream &s) {
 
 /*------------------------------------------------------------------------*/
 
-/**
- * Synchronize data for an animation entry
- */
 void AnimationEntry::synchronize(Common::SeekableReadStream &s) {
 	for (int i = 0; i < 4; ++i)
 		_frame1._frames[i] = s.readByte();
@@ -855,9 +845,6 @@ void AnimationEntry::synchronize(Common::SeekableReadStream &s) {
 		_frame2._frames[i] = s.readByte();
 }
 
-/**
- * Synchronize data for object animations within the game
- */
 void AnimationInfo::synchronize(Common::SeekableReadStream &s) {
 	AnimationEntry entry;
 
@@ -868,9 +855,6 @@ void AnimationInfo::synchronize(Common::SeekableReadStream &s) {
 	}
 }
 
-/**
- * Load the animation info objects in the game
- */
 void AnimationInfo::load(const Common::String &name) {
 	File f(name);
 	synchronize(f);
@@ -1301,9 +1285,6 @@ int Map::mazeLookup(const Common::Point &pt, int layerShift, int wallMask) {
 	}
 }
 
-/**
- * Load the events for a new map
- */
 void Map::loadEvents(int mapId) {
 	// Load events
 	Common::String filename = Common::String::format("maze%c%03d.evt",
diff --git a/engines/xeen/map.h b/engines/xeen/map.h
index a7e88c1..2c02e6e 100644
--- a/engines/xeen/map.h
+++ b/engines/xeen/map.h
@@ -210,6 +210,9 @@ public:
 
 	void synchronize(Common::SeekableReadStream &s);
 
+	/**
+	 * Flags all tiles for the map as having been stepped on
+	 */
 	void setAllTilesStepped();
 
 	void clearCellSurfaces();
@@ -257,6 +260,10 @@ struct MazeMonster {
 
 	MazeMonster();
 
+	/**
+	 * Return the text color to use when displaying the monster's name in combat
+	 * to indicate how damaged they are
+	 */
 	int getTextColor() const;
 };
 
@@ -341,13 +348,22 @@ struct AnimationEntry {
 		int _frames[4];
 	} _frame2;
 
+	/**
+	 * Synchronize data for an animation entry
+	 */
 	void synchronize(Common::SeekableReadStream &s);
 };
 
 class AnimationInfo : public Common::Array<AnimationEntry> {
 public:
+	/**
+	 * Synchronize data for object animations within the game
+	 */
 	void synchronize(Common::SeekableReadStream &s);
 
+	/**
+	 * Load the animation info objects in the game
+	 */
 	void load(const Common::String &name);
 };
 
@@ -361,6 +377,9 @@ private:
 	int _sideMonsters;
 	int _mazeDataIndex;
 
+	/**
+	 * Load the events for a new map
+	 */
 	void loadEvents(int mapId);
 public:
 	Common::String _mazeName;
diff --git a/engines/xeen/module.mk b/engines/xeen/module.mk
index de4df4a..b18f44f 100644
--- a/engines/xeen/module.mk
+++ b/engines/xeen/module.mk
@@ -9,7 +9,6 @@ MODULE_OBJS := \
 	debugger.o \
 	detection.o \
 	dialogs.o \
-	automap.o \
 	dialogs_automap.o \
 	dialogs_char_info.o \
 	dialogs_control_panel.o \
diff --git a/engines/xeen/party.cpp b/engines/xeen/party.cpp
index 1db4a14..35a8f00 100644
--- a/engines/xeen/party.cpp
+++ b/engines/xeen/party.cpp
@@ -264,19 +264,12 @@ bool Party::isInParty(int charId) {
 	return false;
 }
 
-/**
- * Copy the currently active party characters' data back to the roster
- */
 void Party::copyPartyToRoster() {
 	for (uint i = 0; i < _activeParty.size(); ++i) {
 		_roster[_activeParty[i]._rosterId] = _activeParty[i];
 	}
 }
 
-/**
- * Adds time to the party's playtime, taking into account the effect of any
- * stat modifier changes
- */
 void Party::changeTime(int numMinutes) {
 	bool killed = false;
 
@@ -557,16 +550,10 @@ void Party::checkPartyDead() {
 	_dead = true;
 }
 
-/**
- * Move party position to the run destination on the current map
- */
 void Party::moveToRunLocation() {
 	_mazePosition = _vm->_map->mazeData()._runPosition;
 }
 
-/**
- * Give treasure to the party
- */
 void Party::giveTreasure() {
 	Combat &combat = *_vm->_combat;
 	EventsManager &events = *_vm->_events;
@@ -691,9 +678,6 @@ void Party::giveTreasure() {
 	scripts._v2 = 1;
 }
 
-/**
- * Returns true if all the packs for all the characters are full
- */
 bool Party::arePacksFull() const {
 	uint total = 0;
 	for (uint idx = 0; idx < _activeParty.size(); ++idx) {
@@ -707,9 +691,6 @@ bool Party::arePacksFull() const {
 	return total == (_activeParty.size() * NUM_ITEM_CATEGORIES);
 }
 
-/**
- * Give a treasure item to the given character's inventory
- */
 void Party::giveTreasureToCharacter(Character &c, ItemCategory category, int itemIndex) {
 	EventsManager &events = *_vm->_events;
 	Screen &screen = *_vm->_screen;
diff --git a/engines/xeen/party.h b/engines/xeen/party.h
index df6864d..d753b75 100644
--- a/engines/xeen/party.h
+++ b/engines/xeen/party.h
@@ -78,6 +78,9 @@ class Party {
 private:
 	static XeenEngine *_vm;
 
+	/**
+	 * Give a treasure item to the given character's inventory
+	 */
 	void giveTreasureToCharacter(Character &c, ItemCategory category, int itemIndex);
 public:
 	// Dynamic data that's saved
@@ -153,8 +156,15 @@ public:
 
 	bool isInParty(int charId);
 
+	/**
+	 * Copy the currently active party characters' data back to the roster
+	 */
 	void copyPartyToRoster();
 
+	/**
+	 * Adds time to the party's playtime, taking into account the effect of any
+	 * stat modifier changes
+	 */
 	void changeTime(int numMinutes);
 
 	void addTime(int numMinutes);
@@ -169,10 +179,19 @@ public:
 
 	void checkPartyDead();
 
+	/**
+	 * Move party position to the run destination on the current map
+	 */
 	void moveToRunLocation();
 
+	/**
+	 * Give treasure to the party
+	 */
 	void giveTreasure();
 
+	/**
+	 * Returns true if all the packs for all the characters are full
+	 */
 	bool arePacksFull() const;
 
 	bool canShoot() const;
diff --git a/engines/xeen/saves.cpp b/engines/xeen/saves.cpp
index 61022a3..9fd2d19 100644
--- a/engines/xeen/saves.cpp
+++ b/engines/xeen/saves.cpp
@@ -57,9 +57,6 @@ SavesManager::~SavesManager() {
 	delete[] _data;
 }
 
-/**
- * Synchronizes a boolean array as a bitfield set
- */
 void SavesManager::syncBitFlags(Common::Serializer &s, bool *startP, bool *endP) {
 	byte data = 0;
 
@@ -122,9 +119,6 @@ void SavesManager::load(Common::SeekableReadStream *stream) {
 	delete pty;
 }
 
-/**
- * Sets up the dynamic data for the game for a new game
- */
 void SavesManager::reset() {
 	Common::String prefix = _vm->getGameID() != GType_DarkSide ? "xeen|" : "dark|";
 	Common::MemoryWriteStreamDynamic saveFile(DisposeAfterUse::YES);
diff --git a/engines/xeen/saves.h b/engines/xeen/saves.h
index 8f112f6..2571c46 100644
--- a/engines/xeen/saves.h
+++ b/engines/xeen/saves.h
@@ -64,6 +64,9 @@ private:
 
 	void load(Common::SeekableReadStream *stream);
 public:
+	/**
+	 * Synchronizes a boolean array as a bitfield set
+	 */
 	static void syncBitFlags(Common::Serializer &s, bool *startP, bool *endP);
 public:
 	bool _wonWorld;
@@ -73,6 +76,9 @@ public:
 
 	~SavesManager();
 
+	/**
+	 * Sets up the dynamic data for the game for a new game
+	 */
 	void reset();
 
 	void readCharFile();
diff --git a/engines/xeen/screen.cpp b/engines/xeen/screen.cpp
index 80f0149..a013b97 100644
--- a/engines/xeen/screen.cpp
+++ b/engines/xeen/screen.cpp
@@ -161,24 +161,15 @@ void Window::close() {
 	}
 }
 
-/**
- * Update the window
- */
 void Window::update() {
 	// Since all window drawing is done on the screen surface anyway,
 	// there's nothing that needs to be updated here
 }
 
-/**
- * Adds an area that requires redrawing on the next frame update
- */
 void Window::addDirtyRect(const Common::Rect &r) {
 	_vm->_screen->addDirtyRect(r);
 }
 
-/**
- * Fill the content area of a window with the current background color 
- */
 void Window::fill() {
 	fillRect(_innerBounds, _vm->_screen->_bgColor);
 }
@@ -202,9 +193,6 @@ void Window::drawList(DrawStruct *items, int count) {
 
 /*------------------------------------------------------------------------*/
 
-/**
- * Constructor
- */
 Screen::Screen(XeenEngine *vm) : _vm(vm) {
 	_fadeIn = false;
 	create(SCREEN_WIDTH, SCREEN_HEIGHT);
@@ -337,18 +325,12 @@ bool Screen::unionRectangle(Common::Rect &destRect, const Common::Rect &src1, co
 	return !destRect.isEmpty();
 }
 
-/**
- * Load a palette resource into the temporary palette
- */
 void Screen::loadPalette(const Common::String &name) {
 	File f(name);
 	for (int i = 0; i < PALETTE_SIZE; ++i)
 		_tempPalette[i] = f.readByte() << 2;
 }
 
-/**
- * Load a background resource into memory
- */
 void Screen::loadBackground(const Common::String &name) {
 	File f(name);
 
@@ -357,9 +339,6 @@ void Screen::loadBackground(const Common::String &name) {
 	addDirtyRect(Common::Rect(0, 0, this->w, this->h));
 }
 
-/**
- * Copy a loaded background into a display page
- */
 void Screen::loadPage(int pageNum) {
 	assert(pageNum == 0 || pageNum == 1);
 	if (_pages[0].empty()) {
@@ -375,9 +354,6 @@ void Screen::freePages() {
 	_pages[1].free();
 }
 
-/**
- * Merge the two pages along a horizontal split point
- */
 void Screen::horizMerge(int xp) {
 	if (_pages[0].empty())
 		return;
@@ -394,9 +370,6 @@ void Screen::horizMerge(int xp) {
 	}
 }
 
-/**
- * Merge the two pages along a vertical split point
- */
 void Screen::vertMerge(int yp) {
 	if (_pages[0].empty())
 		return;
@@ -420,9 +393,6 @@ void Screen::draw(void *data) {
 	drawScreen();
 }
 
-/**
- * Mark the entire screen for drawing
- */
 void Screen::drawScreen() {
 	addDirtyRect(Common::Rect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT));
 }
diff --git a/engines/xeen/screen.h b/engines/xeen/screen.h
index 21b7e89..4ab76d5 100644
--- a/engines/xeen/screen.h
+++ b/engines/xeen/screen.h
@@ -86,10 +86,16 @@ public:
 
 	void close();
 
+	/**
+	 * Update the window
+	 */
 	void update();
 
 	void frame();
 
+	/**
+	 * Fill the content area of a window with the current background color 
+	 */
 	void fill();
 
 	const char *writeString(const Common::String &s);
@@ -113,6 +119,9 @@ private:
 
 	bool unionRectangle(Common::Rect &destRect, const Common::Rect &src1, const Common::Rect &src2);
 
+	/**
+	 * Mark the entire screen for drawing
+	 */
 	void drawScreen();
 
 	void fadeInner(int step);
@@ -121,6 +130,9 @@ private:
 
 	void updatePalette(const byte *pal, int start, int count16);
 public:
+	/**
+	 * Adds an area that requires redrawing on the next frame update
+	 */
 	virtual void addDirtyRect(const Common::Rect &r);
 public:
 	Common::Array<Window> _windows;
@@ -137,16 +149,31 @@ public:
 
 	void update();
 
+	/**
+	 * Load a palette resource into the temporary palette
+	 */
 	void loadPalette(const Common::String &name);
 
+	/**
+	 * Load a background resource into memory
+	 */
 	void loadBackground(const Common::String &name);
 
+	/**
+	 * Copy a loaded background into a display page
+	 */
 	void loadPage(int pageNum);
 
 	void freePages();
 
+	/**
+	 * Merge the two pages along a horizontal split point
+	 */
 	void horizMerge(int xp);
 
+	/**
+	 * Merge the two pages along a vertical split point
+	 */
 	void vertMerge(int yp);
 
 	void draw(void *data = nullptr);
diff --git a/engines/xeen/scripts.cpp b/engines/xeen/scripts.cpp
index 175292f..177bb5d 100644
--- a/engines/xeen/scripts.cpp
+++ b/engines/xeen/scripts.cpp
@@ -316,9 +316,6 @@ void Scripts::openGrate(int wallVal, int action) {
 
 typedef void(Scripts::*ScriptMethodPtr)(Common::Array<byte> &);
 
-/**
- * Handles executing a given script command
- */
 void Scripts::doOpcode(MazeEvent &event) {
 	static const ScriptMethodPtr COMMAND_LIST[] = {
 		nullptr, &Scripts::cmdDisplay1, &Scripts::cmdDoorTextSml,
@@ -349,9 +346,6 @@ void Scripts::doOpcode(MazeEvent &event) {
 	(this->*COMMAND_LIST[event._opcode])(event._parameters);
 }
 
-/**
- * Display a msesage on-screen
- */
 void Scripts::cmdDisplay1(Common::Array<byte> &params) {
 	Screen &screen = *_vm->_screen;
 	Common::String paramText = _vm->_map->_events._text[_event->_parameters[0]];
@@ -366,9 +360,6 @@ void Scripts::cmdDisplay1(Common::Array<byte> &params) {
 	cmdNoAction(params);
 }
 
-/**
- * Displays a door text message using the small font
- */
 void Scripts::cmdDoorTextSml(Common::Array<byte> &params) {
 	Interface &intf = *_vm->_interface;
 
@@ -381,9 +372,6 @@ void Scripts::cmdDoorTextSml(Common::Array<byte> &params) {
 	cmdNoAction(params);
 }
 
-/**
- * Displays a door text message using the large font
- */
 void Scripts::cmdDoorTextLrg(Common::Array<byte> &params) {
 	Interface &intf = *_vm->_interface;
 
@@ -396,9 +384,6 @@ void Scripts::cmdDoorTextLrg(Common::Array<byte> &params) {
 	cmdNoAction(params);
 }
 
-/**
- * Show a sign text on-screen
- */
 void Scripts::cmdSignText(Common::Array<byte> &params) {
 	Interface &intf = *_vm->_interface;
 
@@ -421,9 +406,6 @@ void Scripts::cmdNPC(Common::Array<byte> &params) {
 	cmdNoAction(params);
 }
 
-/**
- * Play a sound FX
- */
 void Scripts::cmdPlayFX(Common::Array<byte> &params) {
 	_vm->_sound->playFX(params[0]);
 
@@ -496,9 +478,6 @@ void Scripts::cmdTeleport(Common::Array<byte> &params) {
 	}
 }
 
-/**
- * Do a conditional check
- */
 void Scripts::cmdIf(Common::Array<byte> &params) {
 	Party &party = *_vm->_party;
 	uint32 mask;
@@ -542,9 +521,6 @@ void Scripts::cmdIf(Common::Array<byte> &params) {
 	cmdNoAction(params);
 }
 
-/**
- * Moves the position of an object
- */
 void Scripts::cmdMoveObj(Common::Array<byte> &params) { 
 	MazeObject &mazeObj = _vm->_map->_mobData._objects[params[0]];
 
@@ -765,9 +741,6 @@ void Scripts::cmdTakeOrGive(Common::Array<byte> &params) {
 	cmdNoAction(params);
 }
 
-/**
- * Move to the next line of the script
- */
 void Scripts::cmdNoAction(Common::Array<byte> &params) {
 	// Move to next line
 	_lineNum = _vm->_party->_partyDead ? -1 : _lineNum + 1;
@@ -786,9 +759,6 @@ void Scripts::cmdRemove(Common::Array<byte> &params) {
 	cmdMakeNothingHere(params);
 }
 
-/**
- * Set the currently active character for other script operations
- */
 void Scripts::cmdSetChar(Common::Array<byte> &params) { 
 	if (params[0] != 7) {
 		_charIndex = WhoWill::show(_vm, 22, 3, false);
@@ -804,9 +774,6 @@ void Scripts::cmdSetChar(Common::Array<byte> &params) {
 	cmdNoAction(params);
 }
 
-/**
- * Spawn a monster
- */
 void Scripts::cmdSpawn(Common::Array<byte> &params) {
 	Map &map = *_vm->_map;
 	if (params[0] >= map._mobData._monsters.size())
@@ -833,16 +800,10 @@ void Scripts::cmdDoTownEvent(Common::Array<byte> &params) {
 	cmdExit(params);
 }
 
-/**
- * Stop executing the script
- */
 void Scripts::cmdExit(Common::Array<byte> &params) { 
 	_lineNum = -1;
 }
 
-/**
- * Changes the value for the wall on a given cell
- */
 void Scripts::cmdAlterMap(Common::Array<byte> &params) { 
 	Map &map = *_vm->_map;
 
@@ -970,9 +931,6 @@ void Scripts::cmdDamage(Common::Array<byte> &params) {
 	cmdNoAction(params);
 }
 
-/**
- * Jump if a random number matches a given value
- */
 void Scripts::cmdJumpRnd(Common::Array<byte> &params) {
 	int v = _vm->getRandomNumber(1, params[0]);
 	if (v == params[1])
@@ -981,9 +939,6 @@ void Scripts::cmdJumpRnd(Common::Array<byte> &params) {
 	cmdNoAction(params);
 }
 
-/**
- * Alter an existing event
- */
 void Scripts::cmdAlterEvent(Common::Array<byte> &params) {
 	Map &map = *_vm->_map;
 	Party &party = *_vm->_party;
@@ -1000,10 +955,6 @@ void Scripts::cmdAlterEvent(Common::Array<byte> &params) {
 	cmdNoAction(params);
 }
 
-/**
- * Stores the current location and line for later resuming, and set up to execute
- * a script at a given location
- */
 void Scripts::cmdCallEvent(Common::Array<byte> &params) { 
 	_stack.push(StackEntry(_currentPos, _lineNum));
 	_currentPos = Common::Point(params[0], params[1]);
@@ -1012,10 +963,6 @@ void Scripts::cmdCallEvent(Common::Array<byte> &params) {
 	cmdNoAction(params);
 }
 
-/**
- * Return from executing a script to the script location that previously 
- * called the script
- */
 void Scripts::cmdReturn(Common::Array<byte> &params) {
 	StackEntry &se = _stack.top();
 	_currentPos = se;
@@ -1245,9 +1192,6 @@ void Scripts::cmdItemType(Common::Array<byte> &params) {
 	cmdNoAction(params);
 }
 
-/**
- * Disable all the scripts at the party's current position
- */
 void Scripts::cmdMakeNothingHere(Common::Array<byte> &params) {
 	Map &map = *_vm->_map;
 	Party &party = *_vm->_party;
@@ -1270,10 +1214,6 @@ void Scripts::cmdCheckProtection(Common::Array<byte> &params) {
 		cmdExit(params);
 }
 
-/**
- * Given a number of options, and a list of line numbers associated with
- * those options, jumps to whichever line for the option the user selects
- */
 void Scripts::cmdChooseNumeric(Common::Array<byte> &params) {
 	int choice = Choose123::show(_vm, params[0]);
 	if (choice) {
@@ -1305,9 +1245,6 @@ void Scripts::cmdDisplayLarge(Common::Array<byte> &params) {
 	cmdNoAction(params);
 }
 
-/**
- * Exchange the positions of two objects in the maze
- */
 void Scripts::cmdExchObj(Common::Array<byte> &params) {
 	MazeObject &obj1 = _vm->_map->_mobData._objects[params[0]];
 	MazeObject &obj2 = _vm->_map->_mobData._objects[params[1]];
@@ -1335,11 +1272,6 @@ void Scripts::cmdDisplayMain(Common::Array<byte> &params) {
 	cmdNoAction(params);
 }
 
-/**
- * Jumps to a given line number if the surface at relative cell position 1 matches
- * a specified surface.
- * @remarks		This opcode is apparently never actually used
- */
 void Scripts::cmdGoto(Common::Array<byte> &params) { 
 	Map &map = *_vm->_map;
 	map.getCell(1);
@@ -1349,9 +1281,6 @@ void Scripts::cmdGoto(Common::Array<byte> &params) {
 	cmdNoAction(params);
 }
 
-/**
- * Pick a random value from the parameter list and jump to that line number
- */
 void Scripts::cmdGotoRandom(Common::Array<byte> &params) { 
 	_lineNum = params[_vm->getRandomNumber(1, params[0])] - 1;
 	cmdNoAction(params);
@@ -1414,9 +1343,6 @@ void Scripts::doEnding(const Common::String &endStr, int v2) {
 	warning("TODO: doEnding");
 }
 
-/**
- * This monstrosity handles doing the various types of If checks on various data
- */
 bool Scripts::ifProc(int action, uint32 mask, int mode, int charIndex) {
 	Party &party = *_vm->_party;
 	Character &ps = party._activeParty[charIndex];
diff --git a/engines/xeen/scripts.h b/engines/xeen/scripts.h
index 15550dd..f41be1b 100644
--- a/engines/xeen/scripts.h
+++ b/engines/xeen/scripts.h
@@ -155,30 +155,99 @@ private:
 	Common::String _message;
 	Common::String _displayMessage;
 
+	/**
+	 * Handles executing a given script command
+	 */
 	void doOpcode(MazeEvent &event);
+
+	/**
+	 * Display a msesage on-screen
+	 */
 	void cmdDisplay1(Common::Array<byte> &params);
+
+	/**
+	 * Displays a door text message using the small font
+	 */
 	void cmdDoorTextSml(Common::Array<byte> &params);
+
+	/**
+	 * Displays a door text message using the large font
+	 */
 	void cmdDoorTextLrg(Common::Array<byte> &params);
+	
+	/**
+	 * Show a sign text on-screen
+	 */
 	void cmdSignText(Common::Array<byte> &params);
 	void cmdNPC(Common::Array<byte> &params);
+
+	/**
+	 * Play a sound FX
+	 */
 	void cmdPlayFX(Common::Array<byte> &params);
 	void cmdTeleport(Common::Array<byte> &params);
+
+	/**
+	 * Do a conditional check
+	 */
 	void cmdIf(Common::Array<byte> &params);
+
+	/**
+	 * Moves the position of an object
+	 */
 	void cmdMoveObj(Common::Array<byte> &params);
 	void cmdTakeOrGive(Common::Array<byte> &params);
+
+	/**
+	 * Move to the next line of the script
+	 */
 	void cmdNoAction(Common::Array<byte> &params);
 	void cmdRemove(Common::Array<byte> &params);
+
+	/**
+	 * Set the currently active character for other script operations
+	 */
 	void cmdSetChar(Common::Array<byte> &params);
+
+	/**
+	 * Spawn a monster
+	 */
 	void cmdSpawn(Common::Array<byte> &params);
 	void cmdDoTownEvent(Common::Array<byte> &params);
+
+	/**
+	 * Stop executing the script
+	 */
 	void cmdExit(Common::Array<byte> &params);
+
+	/**
+	 * Changes the value for the wall on a given cell
+	 */
 	void cmdAlterMap(Common::Array<byte> &params);
 	void cmdGiveExtended(Common::Array<byte> &params);
 	void cmdConfirmWord(Common::Array<byte> &params);
 	void cmdDamage(Common::Array<byte> &params);
+
+	/**
+	 * Jump if a random number matches a given value
+	 */
 	void cmdJumpRnd(Common::Array<byte> &params);
+
+	/**
+	 * Alter an existing event
+	 */
 	void cmdAlterEvent(Common::Array<byte> &params);
+
+	/**
+	 * Stores the current location and line for later resuming, and set up to execute
+	 * a script at a given location
+	 */
 	void cmdCallEvent(Common::Array<byte> &params);
+
+	/**
+	 * Return from executing a script to the script location that previously
+	 * called the script
+	 */
 	void cmdReturn(Common::Array<byte> &params);
 	void cmdSetVar(Common::Array<byte> &params);
 	void cmdCutsceneEndClouds(Common::Array<byte> &params);
@@ -195,15 +264,38 @@ private:
 	void cmdSelRndChar(Common::Array<byte> &params);
 	void cmdGiveEnchanted(Common::Array<byte> &params);
 	void cmdItemType(Common::Array<byte> &params);
+
+	/**
+	 * Disable all the scripts at the party's current position
+	 */
 	void cmdMakeNothingHere(Common::Array<byte> &params);
 	void cmdCheckProtection(Common::Array<byte> &params);
+
+	/**
+	 * Given a number of options, and a list of line numbers associated with
+	 * those options, jumps to whichever line for the option the user selects
+	 */
 	void cmdChooseNumeric(Common::Array<byte> &params);
 	void cmdDisplayBottomTwoLines(Common::Array<byte> &params);
 	void cmdDisplayLarge(Common::Array<byte> &params);
+
+	/**
+	 * Exchange the positions of two objects in the maze
+	 */
 	void cmdExchObj(Common::Array<byte> &params);
 	void cmdFallToMap(Common::Array<byte> &params);
 	void cmdDisplayMain(Common::Array<byte> &params);
+
+	/**
+	 * Jumps to a given line number if the surface at relative cell position 1 matches
+	 * a specified surface.
+	 * @remarks		This opcode is apparently never actually used
+	 */
 	void cmdGoto(Common::Array<byte> &params);
+
+	/**
+	 * Pick a random value from the parameter list and jump to that line number
+	 */
 	void cmdGotoRandom(Common::Array<byte> &params);
 	void cmdCutsceneEndDarkside(Common::Array<byte> &params);
 	void cmdCutsceneEdWorld(Common::Array<byte> &params);
@@ -220,6 +312,9 @@ private:
 
 	void doEnding(const Common::String &endStr, int v2);
 
+	/**
+	 * This monstrosity handles doing the various types of If checks on various data
+	 */
 	bool ifProc(int action, uint32 mask, int mode, int charIndex);
 
 	bool copyProtectionCheck();
diff --git a/engines/xeen/spells.cpp b/engines/xeen/spells.cpp
index ba4e78b..ee3085d 100644
--- a/engines/xeen/spells.cpp
+++ b/engines/xeen/spells.cpp
@@ -88,16 +88,10 @@ void Spells::executeSpell(MagicSpell spellId) {
 	(this->*SPELL_LIST[spellId])();
 }
 
-/**
- * Spell being cast failed
- */
 void Spells::spellFailed() {
 	ErrorScroll::show(_vm, SPELL_FAILED, WT_NONFREEZED_WAIT);
 }
 
-/**
- * Cast a spell associated with an item
- */
 void Spells::castItemSpell(int itemSpellId) {
 	switch (itemSpellId) {
 	case 15:
@@ -170,9 +164,6 @@ void Spells::castItemSpell(int itemSpellId) {
 	executeSpell(spells[itemSpellId]);
 }
 
-/**
- * Cast a given spell
- */
 int Spells::castSpell(Character *c, MagicSpell spellId) {
 	Combat &combat = *_vm->_combat;
 	Interface &intf = *_vm->_interface;
@@ -217,10 +208,6 @@ int Spells::castSpell(Character *c, MagicSpell spellId) {
 	return result;
 }
 
-/**
- * Subtract the requirements for a given spell if available, returning
- * true if there was sufficient
- */
 int Spells::subSpellCost(Character &c, int spellId) {
 	Party &party = *_vm->_party;
 	int gemCost = SPELL_GEM_COST[spellId];
@@ -243,10 +230,6 @@ int Spells::subSpellCost(Character &c, int spellId) {
 	return 0;
 }
 
-/**
- * Add the SP and gem requirements for a given spell to the given 
- * character and party
- */
 void Spells::addSpellCost(Character &c, int spellId) {
 	Party &party = *_vm->_party;
 	int gemCost = SPELL_GEM_COST[spellId];
diff --git a/engines/xeen/spells.h b/engines/xeen/spells.h
index 1af4fb2..a05e81c 100644
--- a/engines/xeen/spells.h
+++ b/engines/xeen/spells.h
@@ -69,6 +69,9 @@ private:
 
 	void executeSpell(MagicSpell spellId);
 
+	/**
+	 * Spell being cast failed
+	 */
 	void spellFailed();
 
 	// Spell list
@@ -160,12 +163,26 @@ public:
 
 	int calcSpellPoints(int spellId, int expenseFactor) const;
 
+	/**
+	 * Cast a spell associated with an item
+	 */
 	void castItemSpell(int itemSpellId);
 
+	/**
+	 * Cast a given spell
+	 */
 	int castSpell(Character *c, MagicSpell spellId);
 
+	/**
+	 * Subtract the requirements for a given spell if available, returning
+	 * true if there was sufficient
+	 */
 	int subSpellCost(Character &c, int spellId);
 
+	/**
+	 * Add the SP and gem requirements for a given spell to the given
+	 * character and party
+	 */
 	void addSpellCost(Character &c, int spellId);
 };
 
diff --git a/engines/xeen/sprites.cpp b/engines/xeen/sprites.cpp
index b29fb2d..4804f0a 100644
--- a/engines/xeen/sprites.cpp
+++ b/engines/xeen/sprites.cpp
@@ -51,9 +51,6 @@ SpriteResource::~SpriteResource() {
 	clear();
 }
 
-/**
- * Copy operator for duplicating a sprite resource
- */
 SpriteResource &SpriteResource::operator=(const SpriteResource &src) {
 	delete[] _data;
 	_index.clear();
@@ -69,25 +66,16 @@ SpriteResource &SpriteResource::operator=(const SpriteResource &src) {
 	return *this;
 }
 
-/**
- * Load a sprite resource from a given file
- */
 void SpriteResource::load(const Common::String &filename) {
 	File f(filename);
 	load(f);
 }
 
-/**
- * Load a sprite resource from a given file and archive
- */
 void SpriteResource::load(const Common::String &filename, Common::Archive &archive) {
 	File f(filename, archive);
 	load(f);
 }
 
-/**
- * Load a sprite resource from a stream
- */
 void SpriteResource::load(Common::SeekableReadStream &f) {
 	// Read in a copy of the file
 	_filesize = f.size();
@@ -106,18 +94,12 @@ void SpriteResource::load(Common::SeekableReadStream &f) {
 	}
 }
 
-/**
- * Clears the sprite resource
- */
 void SpriteResource::clear() {
 	delete[] _data;
 	_data = nullptr;
 	_filesize = 0;
 }
 
-/**
- * Draws a frame using data at a specific offset in the sprite resource
- */
 void SpriteResource::drawOffset(XSurface &dest, uint16 offset, const Common::Point &pt, 
 		const Common::Rect &bounds, int flags, int scale) {
 	static const uint SCALE_TABLE[] = { 
diff --git a/engines/xeen/sprites.h b/engines/xeen/sprites.h
index 2a00eca..9a241c2 100644
--- a/engines/xeen/sprites.h
+++ b/engines/xeen/sprites.h
@@ -48,6 +48,9 @@ private:
 	bool _lineDist[320];
 	int _scaledWidth, _scaledHeight;
 
+	/**
+	 * Load a sprite resource from a stream
+	 */
 	void load(Common::SeekableReadStream &f);
 
 	/**
@@ -72,12 +75,24 @@ public:
 
 	virtual ~SpriteResource();
 
+	/**
+	 * Copy operator for duplicating a sprite resource
+	 */
 	SpriteResource &operator=(const SpriteResource &src);
 
+	/**
+	 * Load a sprite resource from a given file
+	 */
 	void load(const Common::String &filename);
 
+	/**
+	 * Load a sprite resource from a given file and archive
+	 */
 	void load(const Common::String &filename, Common::Archive &archive);
 
+	/**
+	 * Clears the sprite resource
+	 */
 	void clear();
 
 	void draw(XSurface &dest, int frame, const Common::Point &destPos, 
diff --git a/engines/xeen/town.cpp b/engines/xeen/town.cpp
index 221f5d9..52fa988 100644
--- a/engines/xeen/town.cpp
+++ b/engines/xeen/town.cpp
@@ -1184,9 +1184,6 @@ void Town::drawTownAnim(bool flag) {
 	screen._windows[3].update();
 }
 
-/**
- * Returns true if a town location (bank, blacksmith, etc.) is currently active
- */
 bool Town::isActive() const {
 	return _townSprites.size() > 0 && !_townSprites[0].empty();
 }
diff --git a/engines/xeen/town.h b/engines/xeen/town.h
index c64ef89..f56f24c 100644
--- a/engines/xeen/town.h
+++ b/engines/xeen/town.h
@@ -104,6 +104,9 @@ public:
 
 	void drawTownAnim(bool flag);
 
+	/**
+	 * Returns true if a town location (bank, blacksmith, etc.) is currently active
+	 */
 	bool isActive() const;
 
 	void clearSprites();
diff --git a/engines/xeen/xeen.cpp b/engines/xeen/xeen.cpp
index 3b317f5..da7810c 100644
--- a/engines/xeen/xeen.cpp
+++ b/engines/xeen/xeen.cpp
@@ -271,9 +271,6 @@ void XeenEngine::showMainMenu() {
 	//OptionsMenu::show(this);
 }
 
-/**
- * Main method for playing the game
- */
 void XeenEngine::playGame() {
 	_saves->reset();
 	play();
diff --git a/engines/xeen/xeen.h b/engines/xeen/xeen.h
index cd1b98b..389d73d 100644
--- a/engines/xeen/xeen.h
+++ b/engines/xeen/xeen.h
@@ -115,21 +115,21 @@ protected:
 	virtual void showIntro() = 0;
 
 	/**
-	* Play the game
-	*/
+	 * Play the game
+	 */
 	virtual void playGame();
 private:
 	void initialize();
 
 	/**
-	* Synchronize savegame data
-	*/
+	 * Synchronize savegame data
+	 */
 	void synchronize(Common::Serializer &s);
 
 	/**
-	* Support method that generates a savegame name
-	* @param slot		Slot number
-	*/
+	 * Support method that generates a savegame name
+	 * @param slot		Slot number
+	 */
 	Common::String generateSaveName(int slot);
 
 	// Engine APIs


Commit: 6dc1551d7db3356868cb9402bcc9e9b75648f52b
    https://github.com/scummvm/scummvm/commit/6dc1551d7db3356868cb9402bcc9e9b75648f52b
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2016-08-28T18:16:48-04:00

Commit Message:
XEEN: gcc compilation fixes

Changed paths:
    engines/xeen/dialogs_input.cpp
    engines/xeen/dialogs_options.cpp
    engines/xeen/dialogs_query.cpp
    engines/xeen/dialogs_spells.cpp
    engines/xeen/interface.cpp
    engines/xeen/interface_map.cpp
    engines/xeen/scripts.cpp



diff --git a/engines/xeen/dialogs_input.cpp b/engines/xeen/dialogs_input.cpp
index 5833733..40b8847 100644
--- a/engines/xeen/dialogs_input.cpp
+++ b/engines/xeen/dialogs_input.cpp
@@ -37,7 +37,7 @@ int Input::show(XeenEngine *vm, Window *window, Common::String &line,
 
 int Input::getString(Common::String &line, uint maxLen, int maxWidth, bool isNumeric) {
 	_vm->_noDirectionSense = true;
-	Common::String msg = Common::String::format("\x3""l\t000\x4%03d\x0""c", maxWidth);
+	Common::String msg = Common::String::format("\x3""l\t000\x4%03d\x3""c", maxWidth);
 	_window->writeString(msg);
 	_window->update();
 
diff --git a/engines/xeen/dialogs_options.cpp b/engines/xeen/dialogs_options.cpp
index 4b4974b..757634a 100644
--- a/engines/xeen/dialogs_options.cpp
+++ b/engines/xeen/dialogs_options.cpp
@@ -110,7 +110,7 @@ void OptionsMenu::showTitles1(SpriteResource &sprites) {
 	while (!_vm->shouldQuit() && !events.isKeyMousePressed()) {
 		events.updateGameCounter();
 
-		frameNum = ++frameNum % (_vm->getGameID() == GType_WorldOfXeen ? 5 : 10);
+		frameNum = (frameNum + 1) % (_vm->getGameID() == GType_WorldOfXeen ? 5 : 10);
 		screen.restoreBackground();
 		sprites.draw(screen, frameNum);
 
@@ -211,7 +211,7 @@ void WorldOptionsMenu::showContents(SpriteResource &title1, bool waitFlag) {
 	events.updateGameCounter();
 	
 	// Draw the background frame in a continous cycle
-	_bgFrame = ++_bgFrame % 5;
+	_bgFrame = (_bgFrame + 1) % 5;
 	title1.draw(screen._windows[0], _bgFrame);
 
 	// Draw the basic frame for the optitons menu and title text
diff --git a/engines/xeen/dialogs_query.cpp b/engines/xeen/dialogs_query.cpp
index c982b8a..abaddaf 100644
--- a/engines/xeen/dialogs_query.cpp
+++ b/engines/xeen/dialogs_query.cpp
@@ -105,7 +105,7 @@ bool YesNo::execute(bool type, bool townFlag) {
 	Screen &screen = *_vm->_screen;
 	Town &town = *_vm->_town;
 	SpriteResource confirmSprites;
-	int numFrames;
+	//int numFrames;
 	bool result = false;
 
 	Mode oldMode = _vm->_mode;
@@ -130,10 +130,10 @@ bool YesNo::execute(bool type, bool townFlag) {
 		
 		if (town.isActive()) {
 			town.drawTownAnim(townFlag);
-			numFrames = 3;
+			//numFrames = 3;
 		} else {
 			intf.draw3d(true);
-			numFrames = 1;
+			//numFrames = 1;
 		}
 
 		events.wait(3, true);
diff --git a/engines/xeen/dialogs_spells.cpp b/engines/xeen/dialogs_spells.cpp
index 7cde5f3..b175552 100644
--- a/engines/xeen/dialogs_spells.cpp
+++ b/engines/xeen/dialogs_spells.cpp
@@ -912,6 +912,8 @@ int Teleport::execute() {
 	case DIR_WEST:
 		pt.x -= numSquares;
 		break;
+	default:
+		break;
 	}
 
 	v = map.mazeLookup(pt, map._isOutdoors ? 0xF : 0xFFFF, 0);
diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp
index 3225831..9f9df19 100644
--- a/engines/xeen/interface.cpp
+++ b/engines/xeen/interface.cpp
@@ -513,6 +513,8 @@ void Interface::perform() {
 			case DIR_WEST:
 				--party._mazePosition.x;
 				break;
+			default:
+				break;
 			}
 			chargeStep();
 			stepTime();
@@ -1230,6 +1232,8 @@ void Interface::bash(const Common::Point &pt, Direction direction) {
 				case DIR_WEST:
 					map.setWall(Common::Point(pt.x - 1, pt.y), DIR_EAST, 3);
 					break;
+				default:
+					break;
 				}
 			}
 		}
diff --git a/engines/xeen/interface_map.cpp b/engines/xeen/interface_map.cpp
index f5bf2af..6dd98ef 100644
--- a/engines/xeen/interface_map.cpp
+++ b/engines/xeen/interface_map.cpp
@@ -27,8 +27,6 @@
 
 namespace Xeen {
 
-static bool debugFlag = false;
-
 OutdoorDrawList::OutdoorDrawList() : _sky1(_data[0]), _sky2(_data[1]), 
 	_groundSprite(_data[2]), _attackImgs1(&_data[124]), _attackImgs2(&_data[95]),
 	_attackImgs3(&_data[76]), _attackImgs4(&_data[53]), _groundTiles(&_data[3]) {
diff --git a/engines/xeen/scripts.cpp b/engines/xeen/scripts.cpp
index 177bb5d..03a24b4 100644
--- a/engines/xeen/scripts.cpp
+++ b/engines/xeen/scripts.cpp
@@ -304,6 +304,8 @@ void Scripts::openGrate(int wallVal, int action) {
 		case DIR_WEST:
 			pt.x--;
 			break;
+		default:
+			break;
 		}
 
 		map.setCellSurfaceFlags(pt, 0x80);
@@ -1084,7 +1086,7 @@ void Scripts::cmdSeatTextSml(Common::Array<byte> &params) {
 	Interface &intf = *_vm->_interface;
 
 	intf._screenText = Common::String::format("\x2\f08\x3""c\t116\v090%s\x3l\fd\x1",
-		_message);
+		_message.c_str());
 	intf._upDoorText = true;
 	intf.draw3d(true);
 
@@ -1227,7 +1229,9 @@ void Scripts::cmdDisplayBottomTwoLines(Common::Array<byte> &params) {
 	Map &map = *_vm->_map;
 	Window &w = _vm->_screen->_windows[12];
 
+	warning("TODO: cmdDisplayBottomTwoLines");
 	Common::String msg = Common::String::format("\r\x03c\t000\v007%s\n\n%s",
+		"",
 		map._events._text[params[1]].c_str());
 	w.close();
 	w.open();


Commit: 63a4201541df77afcf71fffb67516f40a8c169ba
    https://github.com/scummvm/scummvm/commit/63a4201541df77afcf71fffb67516f40a8c169ba
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2016-09-04T21:24:07-04:00

Commit Message:
XEEN: Change a strncpy use to Common::strlcpy

Changed paths:
    engines/xeen/character.cpp



diff --git a/engines/xeen/character.cpp b/engines/xeen/character.cpp
index 2ab5329..b0502d2 100644
--- a/engines/xeen/character.cpp
+++ b/engines/xeen/character.cpp
@@ -724,7 +724,7 @@ void Character::clear() {
 void Character::synchronize(Common::Serializer &s) {
 	char name[16];
 	Common::fill(&name[0], &name[16], '\0');
-	strncpy(name, _name.c_str(), 16);
+	Common::strlcpy(name, _name.c_str(), 16);
 	s.syncBytes((byte *)name, 16);
 
 	if (s.isLoading())


Commit: 0c948b6bd0fc87cb57ee8939228435921a504803
    https://github.com/scummvm/scummvm/commit/0c948b6bd0fc87cb57ee8939228435921a504803
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2016-09-04T21:24:37-04:00

Commit Message:
XEEN: Fix Travis identified warnings

Changed paths:
    engines/xeen/combat.h
    engines/xeen/dialogs_spells.cpp
    engines/xeen/events.cpp
    engines/xeen/events.h
    engines/xeen/interface_map.cpp
    engines/xeen/resources.cpp
    engines/xeen/scripts.cpp
    engines/xeen/sound.cpp
    engines/xeen/sound.h
    engines/xeen/xeen.cpp
    engines/xeen/xsurface.cpp
    engines/xeen/xsurface.h



diff --git a/engines/xeen/combat.h b/engines/xeen/combat.h
index 1a1fc3a..8a7c676 100644
--- a/engines/xeen/combat.h
+++ b/engines/xeen/combat.h
@@ -31,7 +31,7 @@
 namespace Xeen {
 
 #define MAX_NUM_MONSTERS 107
-#define PARTY_AND_MONSTERS 11
+#define PARTY_AND_MONSTERS 12
 
 enum DamageType {
 	DT_PHYSICAL = 0, DT_MAGICAL = 1, DT_FIRE = 2, DT_ELECTRICAL = 3,
diff --git a/engines/xeen/dialogs_spells.cpp b/engines/xeen/dialogs_spells.cpp
index b175552..a10dab6 100644
--- a/engines/xeen/dialogs_spells.cpp
+++ b/engines/xeen/dialogs_spells.cpp
@@ -191,8 +191,8 @@ Character *SpellsDialog::execute(ButtonContainer *priorDialog, Character *c, int
 		case Common::KEYCODE_7:
 		case Common::KEYCODE_8:
 		case Common::KEYCODE_9:
-			newSelection = topIndex + (_buttonValue == Common::KEYCODE_0) ? 9 :
-				(_buttonValue - Common::KEYCODE_1);
+			newSelection = topIndex + ((_buttonValue == Common::KEYCODE_0) ? 9 :
+				(_buttonValue - Common::KEYCODE_1));
 
 			if (newSelection < (int)_spells.size()) {
 				int expenseFactor = 0;
@@ -224,6 +224,7 @@ Character *SpellsDialog::execute(ButtonContainer *priorDialog, Character *c, int
 					break;
 				}
 
+				warning("TODO: category -> SPELLS_ALLOWED category value");
 				int spellId = _spells[newSelection]._spellId;
 				int spellIndex = _spells[newSelection]._spellIndex;
 				int spellCost = spells.calcSpellCost(spellId, expenseFactor);
@@ -233,7 +234,7 @@ Character *SpellsDialog::execute(ButtonContainer *priorDialog, Character *c, int
 					Common::String spellName = _spells[newSelection]._name;
 					Common::String msg = (castingCopy & 0x80) ?
 						Common::String::format(SPELLS_PRESS_A_KEY, msg.c_str()) :
-						Common::String::format(SPELLS_PURCHASE, msg.c_str(), spellCost);
+						Common::String::format(SPELLS_PURCHASE, spellName.c_str(), spellCost);
 
 					if (Confirm::show(_vm, msg, castingCopy + 1)) {
 						if (party.subtract(0, spellCost, 0, WT_FREEZE_WAIT)) {
diff --git a/engines/xeen/events.cpp b/engines/xeen/events.cpp
index 0c0a32b..e50d689 100644
--- a/engines/xeen/events.cpp
+++ b/engines/xeen/events.cpp
@@ -33,9 +33,8 @@ namespace Xeen {
 
 EventsManager::EventsManager(XeenEngine *vm) : _vm(vm),
 		_frameCounter(0), _priorFrameCounterTime(0), _gameCounter(0),
-		_priorGameCounterTime(0), _keyCode(Common::KEYCODE_INVALID),
-		_leftButton(false), _rightButton(false),
-		_sprites("mouse.icn") {
+		_leftButton(false), _rightButton(false), _sprites("mouse.icn"),
+		_keyCode(Common::KEYCODE_INVALID) {
 	Common::fill(&_gameCounters[0], &_gameCounters[6], 0);
 }
 
diff --git a/engines/xeen/events.h b/engines/xeen/events.h
index 6ebe46e..7847ecd 100644
--- a/engines/xeen/events.h
+++ b/engines/xeen/events.h
@@ -40,7 +40,6 @@ private:
 	uint32 _priorFrameCounterTime;
 	uint32 _gameCounter;
 	uint32 _gameCounters[6];
-	uint32 _priorGameCounterTime;
 	Common::KeyCode _keyCode;
 	SpriteResource _sprites;
 
diff --git a/engines/xeen/interface_map.cpp b/engines/xeen/interface_map.cpp
index 6dd98ef..af39f38 100644
--- a/engines/xeen/interface_map.cpp
+++ b/engines/xeen/interface_map.cpp
@@ -525,6 +525,8 @@ void InterfaceMap::drawMap() {
 			_outdoorList[116]._sprites = nullptr;
 			_outdoorList[117]._sprites = nullptr;
 			monsterIndex = 3;
+		} else {
+			monsterIndex = 0;
 		}
 
 		drawOutdoors();
@@ -1157,7 +1159,7 @@ void InterfaceMap::setMazeBits() {
 		++_wo[143];
 		break;
 	case 9:
-		++_wo[3033];
+		++_wo[303];
 		break;
 	case 10:
 		++_wo[243];
diff --git a/engines/xeen/resources.cpp b/engines/xeen/resources.cpp
index 0b30ce3..c171a17 100644
--- a/engines/xeen/resources.cpp
+++ b/engines/xeen/resources.cpp
@@ -1534,8 +1534,6 @@ const char *const X_FOUND_Y = "\v060\t000\x3""c%s found: %s";
 
 const char *const ON_WHO = "\x3""c\v009On Who?";
 
-const char *const WHICH_ELEMENT = "";
-
 const char *const WHICH_ELEMENT1 =
 	"\r\x3""c\x1Which Element?\x2\v034\t014\f15F\fdire\t044"
 	"\f15E\fdlec\t074\f15C\fdold\t104\f15A\fdcid\x1";
diff --git a/engines/xeen/scripts.cpp b/engines/xeen/scripts.cpp
index 03a24b4..0e75252 100644
--- a/engines/xeen/scripts.cpp
+++ b/engines/xeen/scripts.cpp
@@ -1172,7 +1172,7 @@ void Scripts::cmdGiveEnchanted(Common::Array<byte> &params) {
 			cmdNoAction(params);
 			return;
 		} else {
-			party._gameFlags[6 + params[0]]++;
+			party._gameFlags[6 + params[0]] = true;
 		}
 	}
 
@@ -1435,7 +1435,7 @@ bool Scripts::ifProc(int action, uint32 mask, int mode, int charIndex) {
 
 		// Check if the character class can cast the particular spell
 		for (int idx = 0; idx < 39; ++idx) {
-			if (SPELLS_ALLOWED[mode][idx] == mask) {
+			if (SPELLS_ALLOWED[category][idx] == mask) {
 				// Can cast it. Check if the player has it in their spellbook
 				if (ps._spells[idx])
 					v = mask;
diff --git a/engines/xeen/sound.cpp b/engines/xeen/sound.cpp
index c0a49ae..2aed7da 100644
--- a/engines/xeen/sound.cpp
+++ b/engines/xeen/sound.cpp
@@ -47,7 +47,7 @@ void VOC::stop() {
 
 /*------------------------------------------------------------------------*/
 
-SoundManager::SoundManager(XeenEngine *vm, Audio::Mixer *mixer): _vm(vm), _mixer(mixer) {
+SoundManager::SoundManager(XeenEngine *vm, Audio::Mixer *mixer): _mixer(mixer) {
 }
 
 void SoundManager::proc2(Common::SeekableReadStream &f) {
diff --git a/engines/xeen/sound.h b/engines/xeen/sound.h
index bcee6f2..96b02c4 100644
--- a/engines/xeen/sound.h
+++ b/engines/xeen/sound.h
@@ -56,7 +56,6 @@ public:
 
 class SoundManager {
 private:
-	XeenEngine *_vm;
 	Audio::Mixer *_mixer;
 public:
 	SoundManager(XeenEngine *vm, Audio::Mixer *mixer);
diff --git a/engines/xeen/xeen.cpp b/engines/xeen/xeen.cpp
index da7810c..066f238 100644
--- a/engines/xeen/xeen.cpp
+++ b/engines/xeen/xeen.cpp
@@ -335,8 +335,8 @@ void XeenEngine::gameLoop() {
 }
 
 Common::String XeenEngine::printMil(uint value) {
-	return (value >= 1000000) ? Common::String::format("%lu mil", value / 1000000) :
-		Common::String::format("%lu", value);
+	return (value >= 1000000) ? Common::String::format("%u mil", value / 1000000) :
+		Common::String::format("%u", value);
 }
 
 Common::String XeenEngine::printK(uint value) {
diff --git a/engines/xeen/xsurface.cpp b/engines/xeen/xsurface.cpp
index 00d333d..1793d76 100644
--- a/engines/xeen/xsurface.cpp
+++ b/engines/xeen/xsurface.cpp
@@ -31,7 +31,8 @@ namespace Xeen {
 XSurface::XSurface() : Graphics::Surface(), _freeFlag(false) {
 }
 
-XSurface::XSurface(int w, int h) : Graphics::Surface(), _freeFlag(false) {
+XSurface::XSurface(int width, int height) : Graphics::Surface(),
+		_freeFlag(false) {
 	create(w, h);
 }
 
@@ -40,8 +41,8 @@ XSurface::~XSurface() {
 		free();
 }
 
-void XSurface::create(uint16 w_, uint16 h_) {
-	Graphics::Surface::create(w_, h_, Graphics::PixelFormat::createFormatCLUT8());
+void XSurface::create(uint16 width, uint16 height) {
+	Graphics::Surface::create(width, height, Graphics::PixelFormat::createFormatCLUT8());
 	_freeFlag = true;
 }
 
diff --git a/engines/xeen/xsurface.h b/engines/xeen/xsurface.h
index 299cc51..f562112 100644
--- a/engines/xeen/xsurface.h
+++ b/engines/xeen/xsurface.h
@@ -37,10 +37,10 @@ public:
 	virtual void addDirtyRect(const Common::Rect &r) {}
 public:
 	XSurface();
-	XSurface(int w, int h);
+	XSurface(int width, int height);
 	virtual ~XSurface();
 
-	void create(uint16 w_, uint16 h_);
+	void create(uint16 width, uint16 height);
 
 	void create(XSurface *s, const Common::Rect &bounds);
 


Commit: 12d57ad5fe48568a8d67665ed285c9d591590d1a
    https://github.com/scummvm/scummvm/commit/12d57ad5fe48568a8d67665ed285c9d591590d1a
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2016-09-04T21:29:45-04:00

Commit Message:
XEEN: Beginnings of Darkside endgame and music

Changed paths:
    engines/xeen/sound.cpp
    engines/xeen/sound.h
    engines/xeen/town.cpp
    engines/xeen/worldofxeen/darkside_cutscenes.cpp
    engines/xeen/xeen.cpp



diff --git a/engines/xeen/sound.cpp b/engines/xeen/sound.cpp
index 2aed7da..f5cc402 100644
--- a/engines/xeen/sound.cpp
+++ b/engines/xeen/sound.cpp
@@ -26,22 +26,43 @@
 
 namespace Xeen {
 
-SoundManager *VOC::_sound;
+SoundManager *Voc::_sound;
 
-VOC::VOC(const Common::String &name) {
+Voc::Voc(const Common::String &name) {
 	if (!open(name))
 		error("Could not open - %s", name.c_str());
 }
 
-void VOC::init(XeenEngine *vm) {
+void Voc::init(XeenEngine *vm) {
 	_sound = vm->_sound;
 }
 
-void VOC::play() {
+void Voc::play() {
 	_sound->playSound(this, _soundHandle);
 }
 
-void VOC::stop() {
+void Voc::stop() {
+	_sound->stopSound(_soundHandle);
+}
+
+/*------------------------------------------------------------------------*/
+
+SoundManager *Music::_sound;
+
+Music::Music(const Common::String &name) {
+	if (!open(name))
+		error("Could not open - %s", name.c_str());
+}
+
+void Music::init(XeenEngine *vm) {
+	_sound = vm->_sound;
+}
+
+void Music::play() {
+	_sound->playMusic(this, _soundHandle);
+}
+
+void Music::stop() {
 	_sound->stopSound(_soundHandle);
 }
 
@@ -62,10 +83,14 @@ void SoundManager::stopMusic(int id) {
 	// TODO
 }
 
-void SoundManager::playSound(Common::SeekableReadStream *s, Audio::SoundHandle &soundHandle) {
+void SoundManager::playSound(Common::SeekableReadStream *s, Audio::SoundHandle &soundHandle,
+	Audio::Mixer::SoundType soundType) {
 	Audio::SeekableAudioStream *stream = Audio::makeVOCStream(s, 0);
-	_mixer->playStream(Audio::Mixer::kPlainSoundType, &soundHandle, stream);
-		
+	_mixer->playStream(soundType, &soundHandle, stream);		
+}
+
+void SoundManager::playMusic(Common::SeekableReadStream *s, Audio::SoundHandle &soundHandle) {
+	// TODO
 }
 
 void SoundManager::stopSound(Audio::SoundHandle &soundHandle) {
diff --git a/engines/xeen/sound.h b/engines/xeen/sound.h
index 96b02c4..954d324 100644
--- a/engines/xeen/sound.h
+++ b/engines/xeen/sound.h
@@ -33,14 +33,14 @@ namespace Xeen {
 
 class SoundManager;
 
-class VOC: public Common::File {
+class Voc: public Common::File {
 private:
 	static SoundManager *_sound;
 	Audio::SoundHandle _soundHandle;
 public:
-	VOC() {}
-	VOC(const Common::String &name);
-	virtual ~VOC() { stop(); }
+	Voc() {}
+	Voc(const Common::String &name);
+	virtual ~Voc() { stop(); }
 	static void init(XeenEngine *vm);
 
 	/**
@@ -54,6 +54,27 @@ public:
 	void stop();
 };
 
+class Music : public Common::File {
+private:
+	static SoundManager *_sound;
+	Audio::SoundHandle _soundHandle;
+public:
+	Music() {}
+	Music(const Common::String &name);
+	virtual ~Music() { stop(); }
+	static void init(XeenEngine *vm);
+
+	/**
+	* Start playing the sound
+	*/
+	void play();
+
+	/**
+	* Stop playing the sound
+	*/
+	void stop();
+};
+
 class SoundManager {
 private:
 	Audio::Mixer *_mixer;
@@ -73,7 +94,13 @@ public:
 	/**
 	 * Play a given sound
 	 */
-	void playSound(Common::SeekableReadStream *s, Audio::SoundHandle &soundHandle);
+	void playSound(Common::SeekableReadStream *s, Audio::SoundHandle &soundHandle,
+		Audio::Mixer::SoundType soundType = Audio::Mixer::kSFXSoundType);
+
+	/**
+	 * Play a given music
+	 */
+	void playMusic(Common::SeekableReadStream *s, Audio::SoundHandle &soundHandle);
 
 	/**
 	 * Stop playing a sound
diff --git a/engines/xeen/town.cpp b/engines/xeen/town.cpp
index 52fa988..cc83563 100644
--- a/engines/xeen/town.cpp
+++ b/engines/xeen/town.cpp
@@ -825,7 +825,7 @@ Character *Town::doTempleOptions(Character *c) {
 
 				intf.drawParty(true);
 				sound.playSample(nullptr, 0);
-				VOC voc("ahh.voc");
+				Voc voc("ahh.voc");
 				voc.play();
 				_flag1 = true;
 				_donation = 0;
diff --git a/engines/xeen/worldofxeen/darkside_cutscenes.cpp b/engines/xeen/worldofxeen/darkside_cutscenes.cpp
index 6226b52..a5de655 100644
--- a/engines/xeen/worldofxeen/darkside_cutscenes.cpp
+++ b/engines/xeen/worldofxeen/darkside_cutscenes.cpp
@@ -39,7 +39,7 @@ bool DarkSideCutscenes::showDarkSideTitle() {
 		SpriteResource("nwc1.int"), SpriteResource("nwc2.int"),
 		SpriteResource("nwc3.int"), SpriteResource("nwc4.int")
 	};
-	VOC voc[3];
+	Voc voc[3];
 	voc[0].open("dragon1.voc");
 	voc[1].open("dragon2.voc");
 	voc[2].open("dragon3.voc");
@@ -158,7 +158,7 @@ bool DarkSideCutscenes::showDarkSideIntro() {
 	SpriteResource sprites[3] = {
 		SpriteResource("title.int"), SpriteResource("pyratop.int"), SpriteResource("pyramid.int")
 	};
-	Common::File voc[2];
+	Voc voc[2];
 	voc[0].open("pharoh1a.voc");
 	voc[1].open("pharoh1b.voc");
 
@@ -234,7 +234,24 @@ bool DarkSideCutscenes::showDarkSideIntro() {
 }
 
 bool DarkSideCutscenes::showDarkSideEnding() {
+	EventsManager &events = *_vm->_events;
+	Screen &screen = *_vm->_screen;
+	SoundManager &sound = *_vm->_sound;
+
+	Voc voc("ido2.voc");
+	Music newBright("newbrigh.m");
+	SpriteResource box("box.vga");
+	
+	newBright.play();
+	screen.loadBackground("scene1.raw");
+	screen.loadPalette("endgame.pal");
+	screen.update();
+
+	screen.fadeIn(4);
+	events.updateGameCounter();
+
 	// TODO
+	events.wait(5000);
 	return true;
 }
 
diff --git a/engines/xeen/xeen.cpp b/engines/xeen/xeen.cpp
index 066f238..e549c8e 100644
--- a/engines/xeen/xeen.cpp
+++ b/engines/xeen/xeen.cpp
@@ -98,7 +98,8 @@ void XeenEngine::initialize() {
 	_sound = new SoundManager(this, _mixer);
 	_spells = new Spells(this);
 	_town = new Town(this);
-	VOC::init(this);
+	Voc::init(this);
+	Music::init(this);
 
 	File f("029.obj");
 	_eventData = f.readStream(f.size());


Commit: 94e1b960c416d1089a94539706cef858f80f9772
    https://github.com/scummvm/scummvm/commit/94e1b960c416d1089a94539706cef858f80f9772
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2016-09-04T21:30:05-04:00

Commit Message:
XEEN: Converted XSurface to derive from ManagedSurface

Changed paths:
    engines/xeen/screen.cpp
    engines/xeen/screen.h
    engines/xeen/xsurface.cpp
    engines/xeen/xsurface.h



diff --git a/engines/xeen/screen.cpp b/engines/xeen/screen.cpp
index a013b97..e1e7b50 100644
--- a/engines/xeen/screen.cpp
+++ b/engines/xeen/screen.cpp
@@ -33,12 +33,21 @@ Window::Window() : _vm(nullptr),  _enabled(false), _a(0), _border(0),
 	_xLo(0), _xHi(0), _ycL(0), _ycH(0) {
 }
 
+Window::Window(const Window &src) : _vm(src._vm), _enabled(src._enabled),
+		_a(src._a), _border(src._border), _xLo(src._xLo), _ycL(src._ycL),
+		_xHi(src._xHi), _ycH(src._ycH) {
+	if (src._vm) {
+		setBounds(src._bounds);
+		create(*_vm->_screen, Common::Rect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT));
+	}
+}
+
 Window::Window(XeenEngine *vm, const Common::Rect &bounds, int a, int border, 
 		int xLo, int ycL, int xHi, int ycH): 
 		_vm(vm), _enabled(false), _a(a), _border(border), 
 		_xLo(xLo), _ycL(ycL), _xHi(xHi), _ycH(ycH) {
 	setBounds(bounds);
-	create(_vm->_screen, Common::Rect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT));
+	create(*_vm->_screen, Common::Rect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT));
 }
 
 void Window::setBounds(const Common::Rect &r) {
@@ -346,7 +355,7 @@ void Screen::loadPage(int pageNum) {
 		_pages[1].create(SCREEN_WIDTH, SCREEN_HEIGHT);
 	}
 
-	blitTo(_pages[pageNum]);
+	_pages[pageNum].blitFrom(*this);
 }
 
 void Screen::freePages() {
@@ -447,7 +456,7 @@ void Screen::saveBackground(int slot) {
 void Screen::restoreBackground(int slot) {
 	assert(slot > 0 && slot < 10);
 
-	_savedScreens[slot - 1].blitTo(*this);
+	blitFrom(_savedScreens[slot - 1]);
 }
 
 void Screen::frameWindow(uint bgType) {
diff --git a/engines/xeen/screen.h b/engines/xeen/screen.h
index 4ab76d5..854a05a 100644
--- a/engines/xeen/screen.h
+++ b/engines/xeen/screen.h
@@ -74,7 +74,7 @@ public:
 	virtual void addDirtyRect(const Common::Rect &r);
 public:
 	Window();
-
+	Window(const Window &src);
 	Window(XeenEngine *vm, const Common::Rect &bounds, int a, int border,
 		int xLo, int ycL, int xHi, int ycH);
 
diff --git a/engines/xeen/xsurface.cpp b/engines/xeen/xsurface.cpp
index 1793d76..5f10a83 100644
--- a/engines/xeen/xsurface.cpp
+++ b/engines/xeen/xsurface.cpp
@@ -28,50 +28,4 @@
 
 namespace Xeen {
 
-XSurface::XSurface() : Graphics::Surface(), _freeFlag(false) {
-}
-
-XSurface::XSurface(int width, int height) : Graphics::Surface(),
-		_freeFlag(false) {
-	create(w, h);
-}
-
-XSurface::~XSurface() {
-	if (_freeFlag)
-		free();
-}
-
-void XSurface::create(uint16 width, uint16 height) {
-	Graphics::Surface::create(width, height, Graphics::PixelFormat::createFormatCLUT8());
-	_freeFlag = true;
-}
-
-void XSurface::create(XSurface *s, const Common::Rect &bounds) {
-	pixels = (byte *)s->getBasePtr(bounds.left, bounds.top);
-	format = Graphics::PixelFormat::createFormatCLUT8();
-	pitch = s->pitch;
-	w = bounds.width();
-	h = bounds.height();
-
-	_freeFlag = false;
-}
-
-void XSurface::blitTo(XSurface &dest) const {
-	blitTo(dest, Common::Point());
-}
-
-void XSurface::blitTo(XSurface &dest, const Common::Point &destPos) const {
-	if (dest.getPixels() == nullptr)
-		dest.create(w, h);
-
-	for (int yp = 0; yp < h; ++yp) {
-		const byte *srcP = (const byte *)getBasePtr(0, yp);
-		byte *destP = (byte *)dest.getBasePtr(destPos.x, destPos.y + yp);
-
-		Common::copy(srcP, srcP + w, destP);
-	}
-
-	dest.addDirtyRect(Common::Rect(destPos.x, destPos.y, destPos.x + w, destPos.y + h));
-}
-
 } // End of namespace Xeen
diff --git a/engines/xeen/xsurface.h b/engines/xeen/xsurface.h
index f562112..40d4611 100644
--- a/engines/xeen/xsurface.h
+++ b/engines/xeen/xsurface.h
@@ -26,29 +26,26 @@
 #include "common/scummsys.h"
 #include "common/system.h"
 #include "common/rect.h"
-#include "graphics/surface.h"
+#include "graphics/managed_surface.h"
 
 namespace Xeen {
 
-class XSurface: public Graphics::Surface {
-private:
-	bool _freeFlag;
+class BaseSurface: public Graphics::ManagedSurface {
 public:
-	virtual void addDirtyRect(const Common::Rect &r) {}
+	virtual void addDirtyRect(const Common::Rect &r) {
+		Graphics::ManagedSurface::addDirtyRect(r);
+	}
 public:
-	XSurface();
-	XSurface(int width, int height);
-	virtual ~XSurface();
-
-	void create(uint16 width, uint16 height);
-
-	void create(XSurface *s, const Common::Rect &bounds);
-
-	void blitTo(XSurface &dest, const Common::Point &destPos) const;
-
-	void blitTo(XSurface &dest) const;
+	BaseSurface() : Graphics::ManagedSurface() {}
+	BaseSurface(int width, int height) : Graphics::ManagedSurface(width, height) {}
+	virtual ~BaseSurface() {}
+};
 
-	bool empty() const { return getPixels() == nullptr; }
+class XSurface : public BaseSurface {
+public:
+	XSurface() : BaseSurface() {}
+	XSurface(int width, int height) : BaseSurface(width, height) {}
+	virtual ~XSurface() {}
 };
 
 } // End of namespace Xeen


Commit: 1a99d8ee8d25701ad991a67d65e68d1f3d1c7f86
    https://github.com/scummvm/scummvm/commit/1a99d8ee8d25701ad991a67d65e68d1f3d1c7f86
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2016-09-04T22:01:16-04:00

Commit Message:
XEEN: Fix compiler warnings

Changed paths:
    engines/xeen/dialogs_party.cpp
    engines/xeen/dialogs_party.h
    engines/xeen/dialogs_spells.cpp



diff --git a/engines/xeen/dialogs_party.cpp b/engines/xeen/dialogs_party.cpp
index 18f5f3a..a03e2d7 100644
--- a/engines/xeen/dialogs_party.cpp
+++ b/engines/xeen/dialogs_party.cpp
@@ -614,7 +614,7 @@ void PartyDialog::createChar() {
 		case Common::KEYCODE_c: {
 			_vm->_mode = MODE_FF;
 			bool result = saveCharacter(party._roster[freeCharList[charIndex]],
-				(CharacterClass)classId, race, sex, attribs);
+				classId, race, sex, attribs);
 			_vm->_mode = MODE_4;
 
 			if (result)
@@ -966,7 +966,7 @@ int PartyDialog::exchangeAttribute(int srcAttr) {
 	return result;
 }
 
-bool PartyDialog::saveCharacter(Character &c, CharacterClass classId,
+bool PartyDialog::saveCharacter(Character &c, int classId,
 		Race race, Sex sex, uint attribs[TOTAL_ATTRIBUTES]) {
 	if (classId == -1) {
 		ErrorScroll::show(_vm, SELECT_CLASS_BEFORE_SAVING);
@@ -997,7 +997,7 @@ bool PartyDialog::saveCharacter(Character &c, CharacterClass classId,
 	c._xeenSide = map._loadDarkSide;
 	c._sex = sex;
 	c._race = race;
-	c._class = classId;
+	c._class = (CharacterClass)classId;
 	c._level._permanent = isDarkCc ? 5 : 1;
 
 	c._might._permanent = attribs[MIGHT];
diff --git a/engines/xeen/dialogs_party.h b/engines/xeen/dialogs_party.h
index 2ad2dae..17ec4fd 100644
--- a/engines/xeen/dialogs_party.h
+++ b/engines/xeen/dialogs_party.h
@@ -100,7 +100,7 @@ private:
 	/**
 	 * Saves the rolled character into the roster
 	 */
-	bool saveCharacter(Character &c, CharacterClass classId, Race race,
+	bool saveCharacter(Character &c, int classId, Race race,
 		Sex sex, uint attribs[TOTAL_ATTRIBUTES]);
 public:
 	static void show(XeenEngine *vm);
diff --git a/engines/xeen/dialogs_spells.cpp b/engines/xeen/dialogs_spells.cpp
index a10dab6..e5d8cd0 100644
--- a/engines/xeen/dialogs_spells.cpp
+++ b/engines/xeen/dialogs_spells.cpp
@@ -233,7 +233,7 @@ Character *SpellsDialog::execute(ButtonContainer *priorDialog, Character *c, int
 				} else {
 					Common::String spellName = _spells[newSelection]._name;
 					Common::String msg = (castingCopy & 0x80) ?
-						Common::String::format(SPELLS_PRESS_A_KEY, msg.c_str()) :
+						Common::String::format(SPELLS_PRESS_A_KEY, spellName.c_str()) :
 						Common::String::format(SPELLS_PURCHASE, spellName.c_str(), spellCost);
 
 					if (Confirm::show(_vm, msg, castingCopy + 1)) {


Commit: a520a18a0101877d11cd488c5b6f93f5b63892af
    https://github.com/scummvm/scummvm/commit/a520a18a0101877d11cd488c5b6f93f5b63892af
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2016-09-04T22:37:42-04:00

Commit Message:
XEEN: Further fix identified warnings

Changed paths:
    engines/xeen/dialogs_spells.cpp
    engines/xeen/screen.cpp



diff --git a/engines/xeen/dialogs_spells.cpp b/engines/xeen/dialogs_spells.cpp
index e5d8cd0..e7bbbf5 100644
--- a/engines/xeen/dialogs_spells.cpp
+++ b/engines/xeen/dialogs_spells.cpp
@@ -224,10 +224,10 @@ Character *SpellsDialog::execute(ButtonContainer *priorDialog, Character *c, int
 					break;
 				}
 
-				warning("TODO: category -> SPELLS_ALLOWED category value");
-				int spellId = _spells[newSelection]._spellId;
 				int spellIndex = _spells[newSelection]._spellIndex;
+				int spellId = SPELLS_ALLOWED[category][spellIndex];
 				int spellCost = spells.calcSpellCost(spellId, expenseFactor);
+
 				if (isCasting) {
 					selection = newSelection;					
 				} else {
diff --git a/engines/xeen/screen.cpp b/engines/xeen/screen.cpp
index e1e7b50..03b751a 100644
--- a/engines/xeen/screen.cpp
+++ b/engines/xeen/screen.cpp
@@ -29,11 +29,11 @@
 
 namespace Xeen {
 
-Window::Window() : _vm(nullptr),  _enabled(false), _a(0), _border(0),
-	_xLo(0), _xHi(0), _ycL(0), _ycH(0) {
+Window::Window() : XSurface(), _vm(nullptr),  _enabled(false),
+	_a(0), _border(0), _xLo(0), _xHi(0), _ycL(0), _ycH(0) {
 }
 
-Window::Window(const Window &src) : _vm(src._vm), _enabled(src._enabled),
+Window::Window(const Window &src) : XSurface(), _vm(src._vm), _enabled(src._enabled),
 		_a(src._a), _border(src._border), _xLo(src._xLo), _ycL(src._ycL),
 		_xHi(src._xHi), _ycH(src._ycH) {
 	if (src._vm) {
@@ -43,7 +43,7 @@ Window::Window(const Window &src) : _vm(src._vm), _enabled(src._enabled),
 }
 
 Window::Window(XeenEngine *vm, const Common::Rect &bounds, int a, int border, 
-		int xLo, int ycL, int xHi, int ycH): 
+		int xLo, int ycL, int xHi, int ycH): XSurface(),
 		_vm(vm), _enabled(false), _a(a), _border(border), 
 		_xLo(xLo), _ycL(ycL), _xHi(xHi), _ycH(ycH) {
 	setBounds(bounds);


Commit: b7a8242b9b453d3e965f3d1d085c7456025ac8f8
    https://github.com/scummvm/scummvm/commit/b7a8242b9b453d3e965f3d1d085c7456025ac8f8
Author: Eugene Sandulenko (sev at scummvm.org)
Date: 2016-09-10T16:55:29+02:00

Commit Message:
Merge pull request #818 from dreammaster/xeen

XEEN: Might & Magic engine

Changed paths:
  A engines/xeen/character.cpp
  A engines/xeen/character.h
  A engines/xeen/combat.cpp
  A engines/xeen/combat.h
  A engines/xeen/configure.engine
  A engines/xeen/debugger.cpp
  A engines/xeen/debugger.h
  A engines/xeen/detection.cpp
  A engines/xeen/detection_tables.h
  A engines/xeen/dialogs.cpp
  A engines/xeen/dialogs.h
  A engines/xeen/dialogs_automap.cpp
  A engines/xeen/dialogs_automap.h
  A engines/xeen/dialogs_char_info.cpp
  A engines/xeen/dialogs_char_info.h
  A engines/xeen/dialogs_control_panel.cpp
  A engines/xeen/dialogs_control_panel.h
  A engines/xeen/dialogs_dismiss.cpp
  A engines/xeen/dialogs_dismiss.h
  A engines/xeen/dialogs_error.cpp
  A engines/xeen/dialogs_error.h
  A engines/xeen/dialogs_exchange.cpp
  A engines/xeen/dialogs_exchange.h
  A engines/xeen/dialogs_fight_options.cpp
  A engines/xeen/dialogs_fight_options.h
  A engines/xeen/dialogs_info.cpp
  A engines/xeen/dialogs_info.h
  A engines/xeen/dialogs_input.cpp
  A engines/xeen/dialogs_input.h
  A engines/xeen/dialogs_items.cpp
  A engines/xeen/dialogs_items.h
  A engines/xeen/dialogs_options.cpp
  A engines/xeen/dialogs_options.h
  A engines/xeen/dialogs_party.cpp
  A engines/xeen/dialogs_party.h
  A engines/xeen/dialogs_query.cpp
  A engines/xeen/dialogs_query.h
  A engines/xeen/dialogs_quests.cpp
  A engines/xeen/dialogs_quests.h
  A engines/xeen/dialogs_quick_ref.cpp
  A engines/xeen/dialogs_quick_ref.h
  A engines/xeen/dialogs_spells.cpp
  A engines/xeen/dialogs_spells.h
  A engines/xeen/dialogs_whowill.cpp
  A engines/xeen/dialogs_whowill.h
  A engines/xeen/events.cpp
  A engines/xeen/events.h
  A engines/xeen/files.cpp
  A engines/xeen/files.h
  A engines/xeen/font.cpp
  A engines/xeen/font.h
  A engines/xeen/interface.cpp
  A engines/xeen/interface.h
  A engines/xeen/interface_map.cpp
  A engines/xeen/interface_map.h
  A engines/xeen/items.cpp
  A engines/xeen/items.h
  A engines/xeen/map.cpp
  A engines/xeen/map.h
  A engines/xeen/module.mk
  A engines/xeen/party.cpp
  A engines/xeen/party.h
  A engines/xeen/resources.cpp
  A engines/xeen/resources.h
  A engines/xeen/saves.cpp
  A engines/xeen/saves.h
  A engines/xeen/screen.cpp
  A engines/xeen/screen.h
  A engines/xeen/scripts.cpp
  A engines/xeen/scripts.h
  A engines/xeen/sound.cpp
  A engines/xeen/sound.h
  A engines/xeen/spells.cpp
  A engines/xeen/spells.h
  A engines/xeen/sprites.cpp
  A engines/xeen/sprites.h
  A engines/xeen/town.cpp
  A engines/xeen/town.h
  A engines/xeen/worldofxeen/clouds_cutscenes.cpp
  A engines/xeen/worldofxeen/clouds_cutscenes.h
  A engines/xeen/worldofxeen/darkside_cutscenes.cpp
  A engines/xeen/worldofxeen/darkside_cutscenes.h
  A engines/xeen/worldofxeen/worldofxeen.cpp
  A engines/xeen/worldofxeen/worldofxeen.h
  A engines/xeen/xeen.cpp
  A engines/xeen/xeen.h
  A engines/xeen/xsurface.cpp
  A engines/xeen/xsurface.h








More information about the Scummvm-git-logs mailing list