aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Gilbert2015-02-04 19:18:51 -0500
committerPaul Gilbert2015-02-04 19:18:51 -0500
commit4953b7954aca078be9655971f925f82c51e472db (patch)
tree7037d7bfcd5148c2ebe41b6b526b5004b4f80e6c
parentf34c5ad9b65f626884736faf802d627dc2fe68c0 (diff)
downloadscummvm-rg350-4953b7954aca078be9655971f925f82c51e472db.tar.gz
scummvm-rg350-4953b7954aca078be9655971f925f82c51e472db.tar.bz2
scummvm-rg350-4953b7954aca078be9655971f925f82c51e472db.zip
XEEN: Partial implementation of doItemOptions
-rw-r--r--engines/xeen/combat.cpp2
-rw-r--r--engines/xeen/combat.h2
-rw-r--r--engines/xeen/dialogs_char_info.cpp4
-rw-r--r--engines/xeen/dialogs_error.cpp11
-rw-r--r--engines/xeen/dialogs_error.h2
-rw-r--r--engines/xeen/dialogs_items.cpp265
-rw-r--r--engines/xeen/dialogs_items.h11
-rw-r--r--engines/xeen/interface_map.h7
-rw-r--r--engines/xeen/items.cpp58
-rw-r--r--engines/xeen/items.h28
-rw-r--r--engines/xeen/party.cpp2
-rw-r--r--engines/xeen/party.h10
-rw-r--r--engines/xeen/resources.cpp37
-rw-r--r--engines/xeen/resources.h27
-rw-r--r--engines/xeen/spells.cpp134
-rw-r--r--engines/xeen/spells.h83
16 files changed, 656 insertions, 27 deletions
diff --git a/engines/xeen/combat.cpp b/engines/xeen/combat.cpp
index 6237e0c5ba..fec244b63a 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 c2554d5bf9..ef82de5af2 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 1d907cf7d9..0c71bfb0be 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 e8512216c7..a58e0e9e78 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 ba36f285cf..1a86afce87 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 1043be8d9e..634fb2de39 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 74be9215ce..c30eaa9a4a 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 fb448e1f29..197f239404 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 5881fb378b..13418262bd 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 5a8c4d71a1..c0b82b9fce 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 0a276b29cd..7d47eafaf4 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 6f70c4b49c..73de7065aa 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 8a23216e90..1f1c979f7a 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 c851db75a4..88e01cdb51 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 588fa1b510..3492510db9 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 96f491684e..241d35dca7 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