aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--engines/xeen/character.cpp18
-rw-r--r--engines/xeen/character.h4
-rw-r--r--engines/xeen/combat.cpp36
-rw-r--r--engines/xeen/dialogs/dialogs_items.cpp33
-rw-r--r--engines/xeen/item.cpp106
-rw-r--r--engines/xeen/item.h70
-rw-r--r--engines/xeen/locations.cpp17
-rw-r--r--engines/xeen/map.cpp2
-rw-r--r--engines/xeen/map.h2
-rw-r--r--engines/xeen/party.cpp10
-rw-r--r--engines/xeen/scripts.cpp8
11 files changed, 185 insertions, 121 deletions
diff --git a/engines/xeen/character.cpp b/engines/xeen/character.cpp
index 2eb37bcbeb..50ad2fe388 100644
--- a/engines/xeen/character.cpp
+++ b/engines/xeen/character.cpp
@@ -554,7 +554,7 @@ int Character::itemScan(int itemId) const {
for (int idx = 0; idx < INV_ITEMS_TOTAL; ++idx) {
const XeenItem &item = _weapons[idx];
- if (item._frame && !(item._bonusFlags & 0xC0) && itemId < 11
+ if (item._frame && !item.isBad() && itemId < 11
&& itemId != 3 && item._material >= 59 && item._material <= 130) {
int mIndex = (int)item.getAttributeCategory();
if (mIndex > PERSONALITY)
@@ -569,7 +569,7 @@ int Character::itemScan(int itemId) const {
for (int idx = 0; idx < INV_ITEMS_TOTAL; ++idx) {
const XeenItem &item = _armor[idx];
- if (item._frame && !(item._bonusFlags & 0xC0)) {
+ if (item._frame && !item.isBad()) {
if (itemId < 11 && itemId != 3 && item._material >= 59 && item._material <= 130) {
int mIndex = (int)item.getAttributeCategory();
if (mIndex > PERSONALITY)
@@ -600,7 +600,7 @@ int Character::itemScan(int itemId) const {
for (int idx = 0; idx < INV_ITEMS_TOTAL; ++idx) {
const XeenItem &item = _accessories[idx];
- if (item._frame && !(item._bonusFlags & 0xC0)) {
+ if (item._frame && !item.isBad()) {
if (itemId < 11 && itemId != 3 && item._material >= 59 && item._material <= 130) {
int mIndex = (int)item.getAttributeCategory();
if (mIndex > PERSONALITY)
@@ -963,7 +963,7 @@ ItemCategory Character::makeItem(int p1, int itemIndex, int p3) {
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;
+ int v16 = 0, v14 = 0, miscCharges = 0, miscId = 0, v8 = 0, v12 = 0;
// Randomly pick a category and item Id
if (p3 == 12) {
@@ -1155,7 +1155,7 @@ ItemCategory Character::makeItem(int p1, int itemIndex, int p3) {
break;
case 4:
- miscBonus = vm->getRandomNumber(Res.MAKE_ITEM_ARR5[p1][0], Res.MAKE_ITEM_ARR5[p1][1]);
+ miscCharges = vm->getRandomNumber(Res.MAKE_ITEM_ARR5[p1][0], Res.MAKE_ITEM_ARR5[p1][1]);
break;
default:
@@ -1168,7 +1168,7 @@ ItemCategory Character::makeItem(int p1, int itemIndex, int p3) {
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);
+ newItem._state._counter = vm->getRandomNumber(1, 6);
}
break;
@@ -1181,7 +1181,7 @@ ItemCategory Character::makeItem(int p1, int itemIndex, int p3) {
case CATEGORY_MISC:
newItem._id = miscId;
- newItem._bonusFlags = miscBonus;
+ newItem._state._counter = miscCharges;
break;
default:
@@ -1242,7 +1242,7 @@ void Character::subtractHitPoints(int amount) {
for (int idx = 0; idx < INV_ITEMS_TOTAL; ++idx) {
XeenItem &item = _armor[idx];
if (item._id && item._frame)
- item._bonusFlags |= ITEMFLAG_BROKEN;
+ item._state._broken = true;
}
}
}
@@ -1250,7 +1250,7 @@ void Character::subtractHitPoints(int amount) {
bool Character::hasSlayerSword() const {
for (uint idx = 0; idx < INV_ITEMS_TOTAL; ++idx) {
- if (_weapons[idx]._id == 34)
+ if (_weapons[idx]._id == XEEN_SLAYER_SWORD)
// Character has Xeen Slayer sword
return true;
}
diff --git a/engines/xeen/character.h b/engines/xeen/character.h
index 019fd9bff8..77e3360748 100644
--- a/engines/xeen/character.h
+++ b/engines/xeen/character.h
@@ -44,10 +44,6 @@ enum Award {
LAKESIDE_GUILD_MEMBER = 85, NECROPOLIS_GUILD_MEMBER = 86, OLYMPUS_GUILD_MEMBER = 87
};
-enum BonusFlags {
- ITEMFLAG_CURSED = 0x40, ITEMFLAG_BROKEN = 0x80, ITEMFLAG_BONUS_MASK = 0xBF, ITEMFLAG_CHARGES_MASK = 0x3F
-};
-
enum Sex { MALE = 0, FEMALE = 1, YES_PLEASE = 2 };
enum Race { HUMAN = 0, ELF = 1, DWARF = 2, GNOME = 3, HALF_ORC = 4 };
diff --git a/engines/xeen/combat.cpp b/engines/xeen/combat.cpp
index 3a248e5942..2c87018613 100644
--- a/engines/xeen/combat.cpp
+++ b/engines/xeen/combat.cpp
@@ -348,13 +348,7 @@ void Combat::doCharDamage(Character &c, int charNum, int monsterDataIndex) {
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;
- }
+ c._items.curseUncurse(true);
sound.playFX(37);
break;
case SA_DRAINSP:
@@ -384,8 +378,8 @@ void Combat::doCharDamage(Character &c, int charNum, int monsterDataIndex) {
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;
+ if (weapon._id < XEEN_SLAYER_SWORD && weapon._id != 0 && weapon._frame != 0) {
+ weapon._state._broken = true;
weapon._frame = 0;
}
}
@@ -1354,32 +1348,34 @@ void Combat::attack(Character &c, RangeType rangeType) {
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 (weapon.isEquipped()) {
+ switch (weapon._state._counter) {
+ case EFFECTIVE_DRAGON:
if (monsterData._monsterType == MONSTER_DRAGON)
damage *= 3;
break;
- case 2:
+ case EFFECTIVE_UNDEAD :
if (monsterData._monsterType == MONSTER_UNDEAD)
damage *= 3;
break;
- case 3:
+ case EFFECTIVE_GOLEM:
if (monsterData._monsterType == MONSTER_GOLEM)
damage *= 3;
break;
- case 4:
+ case EFFECTIVE_INSECT:
if (monsterData._monsterType == MONSTER_INSECT)
damage *= 3;
break;
- case 5:
- if (monsterData._monsterType == MONSTER_0)
+ case EFFEctIVE_MONSTERS:
+ if (monsterData._monsterType == MONSTER_MONSTERS)
damage *= 3;
break;
- case 6:
+ case EFFECTIVE_ANIMAL:
if (monsterData._monsterType == MONSTER_ANIMAL)
damage *= 3;
break;
+ default:
+ break;
}
}
}
@@ -1516,8 +1512,8 @@ void Combat::attack2(int damage, RangeType rangeType) {
if (!ccNum && monster._spriteId == 89) {
// Xeen's Scepter of Temporal Distortion
party._treasure._weapons[0]._id = 90;
- party._treasure._weapons[0]._bonusFlags = 0;
party._treasure._weapons[0]._material = 0;
+ party._treasure._weapons[0]._state.clear();
party._treasure._hasItems = true;
party._questItems[8]++;
}
@@ -1692,7 +1688,7 @@ void Combat::getWeaponDamage(Character &c, RangeType rangeType) {
}
if (flag) {
- if (!(weapon._bonusFlags & (ITEMFLAG_BROKEN | ITEMFLAG_CURSED))) {
+ if (!weapon.isBad()) {
_attackWeapon = &weapon;
if (weapon._material < 37) {
diff --git a/engines/xeen/dialogs/dialogs_items.cpp b/engines/xeen/dialogs/dialogs_items.cpp
index 2e01681e5c..41233c9946 100644
--- a/engines/xeen/dialogs/dialogs_items.cpp
+++ b/engines/xeen/dialogs/dialogs_items.cpp
@@ -326,7 +326,7 @@ Character *ItemsDialog::execute(Character *c, ItemsMode mode) {
InventoryItems &srcItems = c->_items[category];
XeenItem &srcItem = srcItems[itemIndex];
- if (srcItem._bonusFlags & ITEMFLAG_CURSED)
+ if (srcItem._state._cursed)
ErrorScroll::show(_vm, Res.CANNOT_REMOVE_CURSED_ITEM);
else if (destItems.isFull())
ErrorScroll::show(_vm, Common::String::format(
@@ -736,7 +736,7 @@ int ItemsDialog::calcItemCost(Character *c, int itemIndex, ItemsMode mode,
case ITEMMODE_5:
case ITEMMODE_ENCHANT:
// Show number of charges
- result = i._bonusFlags & ITEMFLAG_CHARGES_MASK;
+ result = i._state._counter;
break;
default:
@@ -802,10 +802,8 @@ int ItemsDialog::doItemOptions(Character &c, int actionIndex, int itemIndex, Ite
default:
if (combat._itemFlag) {
ErrorScroll::show(_vm, Res.USE_ITEM_IN_COMBAT);
- } else if (i._id && (i._bonusFlags & ITEMFLAG_BONUS_MASK)
- && !(i._bonusFlags & (ITEMFLAG_BROKEN | ITEMFLAG_CURSED))) {
- int charges = (i._bonusFlags & ITEMFLAG_BONUS_MASK) - 1;
- i._bonusFlags = charges;
+ } else if (i._id && !i.isBad() && i._state._counter > 0) {
+ --i._state._counter;
_oldCharacter = &c;
windows[30].close();
@@ -813,7 +811,7 @@ int ItemsDialog::doItemOptions(Character &c, int actionIndex, int itemIndex, Ite
windows[24].close();
spells.castItemSpell(i._id);
- if (!charges) {
+ if (!i._state._counter) {
// Ran out of charges, so make item disappear
c._items[category][itemIndex].clear();
c._items[category].sort();
@@ -876,10 +874,10 @@ int ItemsDialog::doItemOptions(Character &c, int actionIndex, int itemIndex, Ite
bool noNeed;
switch (category) {
case CATEGORY_WEAPON:
- noNeed = (item._bonusFlags & ITEMFLAG_CURSED) || item._id == 34;
+ noNeed = (item._state._cursed) || item._id >= XEEN_SLAYER_SWORD;
break;
default:
- noNeed = item._bonusFlags & ITEMFLAG_CURSED;
+ noNeed = item._state._cursed;
break;
}
@@ -904,17 +902,12 @@ int ItemsDialog::doItemOptions(Character &c, int actionIndex, int itemIndex, Ite
}
case ITEMMODE_RECHARGE:
- if (category != CATEGORY_MISC || c._misc[itemIndex]._material > 9
- || c._misc[itemIndex]._id == 53 || c._misc[itemIndex]._id == 0) {
+ if (category != CATEGORY_MISC || item._material > 9 || item._id == 53 || item._id == 0) {
sound.playFX(21);
ErrorScroll::show(_vm, Common::String::format(Res.NOT_RECHARGABLE, Res.SPELL_FAILED));
} else {
- int charges = MIN(63, _vm->getRandomNumber(1, 6) +
- (c._misc[itemIndex]._bonusFlags & ITEMFLAG_BONUS_MASK));
+ item._state._counter = MIN(63, _vm->getRandomNumber(1, 6) + item._state._counter);
sound.playFX(20);
-
- c._misc[itemIndex]._bonusFlags = (c._misc[itemIndex]._bonusFlags
- & ~ITEMFLAG_BONUS_MASK) | charges;
}
return 2;
@@ -926,7 +919,7 @@ int ItemsDialog::doItemOptions(Character &c, int actionIndex, int itemIndex, Ite
}
case ITEMMODE_REPAIR:
- if (!(item._bonusFlags & ITEMFLAG_BROKEN)) {
+ if (!item._state._broken) {
ErrorScroll::show(_vm, Res.ITEM_NOT_BROKEN);
} else {
int cost = calcItemCost(&c, itemIndex, mode, actionIndex, category);
@@ -936,7 +929,7 @@ int ItemsDialog::doItemOptions(Character &c, int actionIndex, int itemIndex, Ite
cost);
if (Confirm::show(_vm, msg) && party.subtract(CONS_GOLD, cost, WHERE_PARTY)) {
- item._bonusFlags &= ~ITEMFLAG_BROKEN;
+ item._state._broken = false;
}
}
break;
@@ -991,11 +984,11 @@ void ItemsDialog::itemToGold(Character &c, int itemIndex, ItemCategory category,
Party &party = *_vm->_party;
Sound &sound = *_vm->_sound;
- if (category == CATEGORY_WEAPON && item._id == 34) {
+ if (category == CATEGORY_WEAPON && item._id >= XEEN_SLAYER_SWORD) {
sound.playFX(21);
ErrorScroll::show(_vm, Common::String::format("\v012\t000\x03""c%s",
Res.SPELL_FAILED));
- } else if (item._id != 0) {
+ } else if (!item.empty()) {
// 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);
diff --git a/engines/xeen/item.cpp b/engines/xeen/item.cpp
index cb18bd4b02..c52f4e998b 100644
--- a/engines/xeen/item.cpp
+++ b/engines/xeen/item.cpp
@@ -27,19 +27,39 @@
namespace Xeen {
+void ItemState::synchronize(Common::Serializer &s) {
+ byte b = _counter | (_cursed ? 0x40 : 0) | (_broken ? 0x80 : 0);
+ s.syncAsByte(b);
+
+ if (s.isLoading()) {
+ _counter = b & 63;
+ _cursed = (b & 0x40) != 0;
+ _broken = (b & 0x80) != 0;
+ }
+}
+
+void ItemState::operator=(byte val) {
+ _counter = val & 63;
+ _cursed = (val & 0x40) != 0;
+ _broken = (val & 0x80) != 0;
+}
+
+/*------------------------------------------------------------------------*/
+
XeenItem::XeenItem() {
clear();
}
void XeenItem::clear() {
- _material = _id = _bonusFlags = 0;
+ _material = _id = 0;
+ _state.clear();
_frame = 0;
}
void XeenItem::synchronize(Common::Serializer &s) {
s.syncAsByte(_material);
s.syncAsByte(_id);
- s.syncAsByte(_bonusFlags);
+ _state.synchronize(s);
s.syncAsByte(_frame);
}
@@ -178,7 +198,7 @@ bool InventoryItems::discardItem(int itemIndex) {
XeenItem &item = operator[](itemIndex);
XeenEngine *vm = Party::_vm;
- if (item._bonusFlags & ITEMFLAG_CURSED) {
+ if (item._state._cursed) {
ErrorScroll::show(vm, Res.CANNOT_DISCARD_CURSED_ITEM);
} else {
Common::String itemDesc = getFullDescription(itemIndex, 4);
@@ -218,7 +238,7 @@ void InventoryItems::removeItem(int itemIndex) {
XeenItem &item = operator[](itemIndex);
XeenEngine *vm = Party::_vm;
- if (item._bonusFlags & ITEMFLAG_CURSED)
+ if (item._state._cursed)
ErrorScroll::show(vm, Res.CANNOT_REMOVE_CURSED_ITEM);
else
item._frame = 0;
@@ -319,14 +339,13 @@ Common::String WeaponItems::getFullDescription(int itemIndex, int displayNum) {
Resources &res = *getVm()->_resources;
Common::String desc = Common::String::format("\f%02u%s%s%s\f%02u%s%s%s", displayNum,
- !i._bonusFlags ? res._maeNames[i._material].c_str() : "",
- (i._bonusFlags & ITEMFLAG_BROKEN) ? Res.ITEM_BROKEN : "",
- (i._bonusFlags & ITEMFLAG_CURSED) ? Res.ITEM_CURSED : "",
+ !i._state._cursed && !i._state._broken ? "" : res._maeNames[i._material].c_str(),
+ i._state._broken ? Res.ITEM_BROKEN : "",
+ i._state._cursed ? Res.ITEM_CURSED : "",
displayNum,
Res.WEAPON_NAMES[i._id],
- !i._bonusFlags ? "" : Res.BONUS_NAMES[i._bonusFlags & ITEMFLAG_BONUS_MASK],
- (i._bonusFlags & (ITEMFLAG_BROKEN | ITEMFLAG_CURSED)) ||
- !i._bonusFlags ? "\b " : ""
+ !i._state._counter ? "" : Res.BONUS_NAMES[i._state._counter],
+ (i._state._cursed || i._state._broken) || !i._id ? "\b " : ""
);
capitalizeItem(desc);
return desc;
@@ -337,12 +356,12 @@ void WeaponItems::enchantItem(int itemIndex, int amount) {
XeenItem &item = operator[](itemIndex);
Character tempCharacter;
- if (item._material == 0 && item._bonusFlags == 0 && item._id != 34) {
+ if (item._material == 0 && item._state.empty() && item._id != 34) {
tempCharacter.makeItem(amount, 0, 1);
XeenItem &tempItem = tempCharacter._weapons[0];
item._material = tempItem._material;
- item._bonusFlags = tempItem._bonusFlags;
+ item._state = tempItem._state;
sound.playFX(19);
} else {
InventoryItems::enchantItem(itemIndex, amount);
@@ -381,10 +400,9 @@ Common::String WeaponItems::getAttributes(XeenItem &item, const Common::String &
}
// Handle weapon effective against
- int effective = item._bonusFlags & ITEMFLAG_BONUS_MASK;
+ Effectiveness effective = (Effectiveness)item._state._counter;
if (effective) {
- specialPower = Common::String::format(Res.EFFECTIVE_AGAINST,
- Res.EFFECTIVENESS_NAMES[effective]);
+ specialPower = Common::String::format(Res.EFFECTIVE_AGAINST, Res.EFFECTIVENESS_NAMES[effective]);
}
return Common::String::format(Res.ITEM_DETAILS, classes.c_str(),
@@ -489,13 +507,12 @@ Common::String ArmorItems::getFullDescription(int itemIndex, int displayNum) {
Resources &res = *getVm()->_resources;
Common::String desc = 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) ? Res.ITEM_BROKEN : "",
- (i._bonusFlags & ITEMFLAG_CURSED) ? Res.ITEM_CURSED : "",
+ !i._state._cursed && !i._state._broken ? "" : res._maeNames[i._material].c_str(),
+ i._state._broken ? Res.ITEM_BROKEN : "",
+ i._state._cursed ? Res.ITEM_CURSED : "",
displayNum,
Res.ARMOR_NAMES[i._id],
- (i._bonusFlags & (ITEMFLAG_BROKEN | ITEMFLAG_CURSED)) ||
- !i._bonusFlags ? "\b " : ""
+ (i._state._cursed || i._state._broken) || !i._id ? "\b " : ""
);
capitalizeItem(desc);
return desc;
@@ -506,12 +523,12 @@ void ArmorItems::enchantItem(int itemIndex, int amount) {
XeenItem &item = operator[](itemIndex);
Character tempCharacter;
- if (item._material == 0 && item._bonusFlags == 0) {
+ if (item._material == 0 && item._state.empty()) {
tempCharacter.makeItem(amount, 0, 2);
XeenItem &tempItem = tempCharacter._armor[0];
item._material = tempItem._material;
- item._bonusFlags = tempItem._bonusFlags;
+ item._state = tempItem._state;
sound.playFX(19);
} else {
InventoryItems::enchantItem(itemIndex, amount);
@@ -603,13 +620,12 @@ Common::String AccessoryItems::getFullDescription(int itemIndex, int displayNum)
Resources &res = *getVm()->_resources;
Common::String desc = 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) ? Res.ITEM_BROKEN : "",
- (i._bonusFlags & ITEMFLAG_CURSED) ? Res.ITEM_CURSED : "",
+ !i._state._cursed && !i._state._broken ? "" : res._maeNames[i._material].c_str(),
+ i._state._broken ? Res.ITEM_BROKEN : "",
+ i._state._cursed ? Res.ITEM_CURSED : "",
displayNum,
Res.ACCESSORY_NAMES[i._id],
- (i._bonusFlags & (ITEMFLAG_BROKEN | ITEMFLAG_CURSED)) ||
- !i._bonusFlags ? "\b " : ""
+ (i._state._cursed || i._state._broken) || !i._id ? "\b " : ""
);
capitalizeItem(desc);
return desc;
@@ -651,13 +667,12 @@ Common::String MiscItems::getFullDescription(int itemIndex, int displayNum) {
Resources &res = *getVm()->_resources;
Common::String desc = 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) ? Res.ITEM_BROKEN : "",
- (i._bonusFlags & ITEMFLAG_CURSED) ? Res.ITEM_CURSED : "",
+ !i._state._cursed && !i._state._broken ? "" : res._maeNames[i._material].c_str(),
+ i._state._broken ? Res.ITEM_BROKEN : "",
+ i._state._cursed ? Res.ITEM_CURSED : "",
displayNum,
Res.MISC_NAMES[i._id],
- (i._bonusFlags & (ITEMFLAG_BROKEN | ITEMFLAG_CURSED)) ||
- !i._id ? "\b " : ""
+ (i._state._cursed || i._state._broken) || !i._id ? "\b " : ""
);
capitalizeItem(desc);
return desc;
@@ -706,16 +721,35 @@ const InventoryItems &InventoryItemsGroup::operator[](ItemCategory category) con
void InventoryItemsGroup::breakAllItems() {
for (int idx = 0; idx < INV_ITEMS_TOTAL; ++idx) {
if (_owner->_weapons[idx]._id != 34) {
- _owner->_weapons[idx]._bonusFlags |= ITEMFLAG_BROKEN;
+ _owner->_weapons[idx]._state._broken = true;
_owner->_weapons[idx]._frame = 0;
}
- _owner->_armor[idx]._bonusFlags |= ITEMFLAG_BROKEN;
- _owner->_accessories[idx]._bonusFlags |= ITEMFLAG_BROKEN;
- _owner->_misc[idx]._bonusFlags |= ITEMFLAG_BROKEN;
+ _owner->_armor[idx]._state._broken = true;
+ _owner->_accessories[idx]._state._broken = true;
+ _owner->_misc[idx]._state._broken = true;
_owner->_armor[idx]._frame = 0;
_owner->_accessories[idx]._frame = 0;
}
}
+void InventoryItemsGroup::curseUncurse(bool curse) {
+ for (int idx = 0; idx < INV_ITEMS_TOTAL; ++idx) {
+ _owner->_weapons[idx]._state._cursed = curse && _owner->_weapons[idx]._id < XEEN_SLAYER_SWORD;
+ _owner->_armor[idx]._state._cursed = curse;
+ _owner->_accessories[idx]._state._cursed = curse;
+ _owner->_misc[idx]._state._cursed = curse;
+ }
+}
+
+bool InventoryItemsGroup::hasCursedItems() const {
+ bool isCursed = false;
+ for (int idx = 0; idx < INV_ITEMS_TOTAL; ++idx) {
+ for (ItemCategory cat = CATEGORY_WEAPON; cat <= CATEGORY_MISC; cat = (ItemCategory)((int)cat + 1)) {
+ if ((*this)[cat][idx]._state._cursed)
+ return true;
+ }
+ }
+}
+
} // End of namespace Xeen
diff --git a/engines/xeen/item.h b/engines/xeen/item.h
index 105df0e661..9bd70c71da 100644
--- a/engines/xeen/item.h
+++ b/engines/xeen/item.h
@@ -52,11 +52,54 @@ enum ElementalCategory {
ELEM_ENERGY = 4, ELEM_MAGIC = 5
};
+enum ItemId {
+ XEEN_SLAYER_SWORD = 34
+};
+
+enum Effectiveness {
+ EFFECTIVE_NONE = 0, EFFECTIVE_DRAGON = 1, EFFECTIVE_UNDEAD = 2, EFFECTIVE_GOLEM = 3,
+ EFFECTIVE_INSECT = 4, EFFEctIVE_MONSTERS = 5, EFFECTIVE_ANIMAL = 6
+};
+
+struct ItemState {
+ byte _counter : 6; // Stores charges for Misc items, and the effective against for weapons
+ bool _cursed : 1;
+ bool _broken : 1;
+
+ /**
+ * Constructor
+ */
+ ItemState() : _counter(0), _cursed(false), _broken(false) {}
+
+ /**
+ * Clear the state
+ */
+ void clear() {
+ _counter = 0;
+ _cursed = _broken = false;
+ }
+
+ /**
+ * Returns true if the state is empty
+ */
+ bool empty() const { return !_counter && !_cursed && !_broken; }
+
+ /**
+ * Synchronizes the item's state
+ */
+ void synchronize(Common::Serializer &s);
+
+ /**
+ * Set the entire state value
+ */
+ void operator=(byte val);
+};
+
class XeenItem {
public:
int _material;
uint _id;
- int _bonusFlags;
+ ItemState _state;
int _frame;
public:
/**
@@ -70,11 +113,6 @@ public:
XeenItem();
/**
- * Constructor
- */
- XeenItem(uint id, int material, int bonusFlags) : _id(id), _material(material), _bonusFlags(bonusFlags) {}
-
- /**
* Clear the data for the item
*/
void clear();
@@ -85,6 +123,16 @@ public:
bool empty() const { return _id == 0; }
/**
+ * Returns true if the item is cursed or broken
+ */
+ bool isBad() const { return _state._cursed || _state._broken; }
+
+ /**
+ * Returns true for weapons if it's equipped
+ */
+ bool isEquipped() const { return _frame != 0; }
+
+ /**
* Synchronizes the data for the item
*/
void synchronize(Common::Serializer &s);
@@ -305,6 +353,16 @@ public:
* Breaks all the items in a given character's inventory
*/
void breakAllItems();
+
+ /**
+ * Curses or curses all the items
+ */
+ void curseUncurse(bool curse);
+
+ /**
+ * Returns true if the character has any cursed items
+ */
+ bool hasCursedItems() const;
};
} // End of namespace Xeen
diff --git a/engines/xeen/locations.cpp b/engines/xeen/locations.cpp
index 6f8bc82470..9b0eec382a 100644
--- a/engines/xeen/locations.cpp
+++ b/engines/xeen/locations.cpp
@@ -868,14 +868,7 @@ Common::String TempleLocation::createLocationText(Character &ch) {
_v5 = (_currentCharLevel * 1000) + (ch._conditions[ERADICATED] * 500) + _v11;
}
- bool isCursed = false;
- for (int idx = 0; idx < INV_ITEMS_TOTAL; ++idx) {
- isCursed |= (ch._weapons[idx]._bonusFlags & ITEMFLAG_CURSED) != 0;
- isCursed |= (ch._armor[idx]._bonusFlags & ITEMFLAG_CURSED) != 0;
- isCursed |= (ch._accessories[idx]._bonusFlags & ITEMFLAG_CURSED) != 0;
- isCursed |= (ch._misc[idx]._bonusFlags & ITEMFLAG_CURSED) != 0;
- }
-
+ bool isCursed = ch._items.hasCursedItems();
if (isCursed || ch._conditions[CURSED])
_uncurseCost = (_currentCharLevel * 20) + _v10;
@@ -962,13 +955,7 @@ Character *TempleLocation::doOptions(Character *c) {
case Common::KEYCODE_u:
if (_uncurseCost && party.subtract(CONS_GOLD, _uncurseCost, WHERE_PARTY, WT_LOC_WAIT)) {
- for (int idx = 0; idx < 9; ++idx) {
- c->_weapons[idx]._bonusFlags &= ~ITEMFLAG_CURSED;
- c->_armor[idx]._bonusFlags &= ~ITEMFLAG_CURSED;
- c->_accessories[idx]._bonusFlags &= ~ITEMFLAG_CURSED;
- c->_misc[idx]._bonusFlags &= ~ITEMFLAG_CURSED;
- }
-
+ c->_items.curseUncurse(false);
c->_conditions[CURSED] = 0;
_farewellTime = 1440;
intf.drawParty(true);
diff --git a/engines/xeen/map.cpp b/engines/xeen/map.cpp
index ce14553ce7..19312b6bcc 100644
--- a/engines/xeen/map.cpp
+++ b/engines/xeen/map.cpp
@@ -52,7 +52,7 @@ MonsterStruct::MonsterStruct() {
_specialAttack = SA_NONE;
_hitChance = 0;
_rangeAttack = 0;
- _monsterType = MONSTER_0;
+ _monsterType = MONSTER_MONSTERS;
_fireResistence = 0;
_electricityResistence = 0;
_coldResistence = 0;
diff --git a/engines/xeen/map.h b/engines/xeen/map.h
index c34ef9e76e..a84c338d41 100644
--- a/engines/xeen/map.h
+++ b/engines/xeen/map.h
@@ -42,7 +42,7 @@ namespace Xeen {
class XeenEngine;
enum MonsterType {
- MONSTER_0 = 0, MONSTER_ANIMAL = 1, MONSTER_INSECT = 2,
+ MONSTER_MONSTERS = 0, MONSTER_ANIMAL = 1, MONSTER_INSECT = 2,
MONSTER_HUMANOID = 3, MONSTER_UNDEAD = 4, MONSTER_GOLEM = 5,
MONSTER_DRAGON = 6
};
diff --git a/engines/xeen/party.cpp b/engines/xeen/party.cpp
index d6ef37791e..dc90863b8c 100644
--- a/engines/xeen/party.cpp
+++ b/engines/xeen/party.cpp
@@ -114,7 +114,7 @@ void BlacksmithWares::regenerate() {
XeenItem &item = (*this)[itemCat][0][slotNum][catCount[itemCat]];
item._id = tempChar._weapons[0]._id;
item._material = tempChar._weapons[0]._material;
- item._bonusFlags = tempChar._weapons[0]._bonusFlags;
+ item._state = tempChar._weapons[0]._state;
++catCount[itemCat];
}
@@ -133,7 +133,7 @@ void BlacksmithWares::regenerate() {
XeenItem &item = (*this)[itemCat][1][slotNum][catCount[itemCat]];
item._id = tempChar._misc[0]._id;
item._material = tempChar._misc[0]._material;
- item._bonusFlags = tempChar._misc[0]._bonusFlags;
+ item._state = tempChar._misc[0]._state;
++catCount[itemCat];
}
@@ -713,8 +713,8 @@ void Party::giveTreasure() {
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
+ if (_treasure._weapons[itemNum]._id >= XEEN_SLAYER_SWORD) {
+ // Xeen Slayer Sword, so clear a slot for it
_activeParty[0]._weapons[INV_ITEMS_TOTAL - 1].clear();
} else {
// Otherwise, clear all the remaining treasure items,
@@ -1356,7 +1356,7 @@ bool Party::giveTake(int takeMode, uint takeVal, int giveMode, uint giveVal, int
// Found a free slot, so copy the created item into it
trItems[idx]._material = srcItem._material;
trItems[idx]._id = srcItem._id;
- trItems[idx]._bonusFlags = srcItem._bonusFlags;
+ trItems[idx]._state = srcItem._state;
_treasure._hasItems = true;
break;
}
diff --git a/engines/xeen/scripts.cpp b/engines/xeen/scripts.cpp
index 970004765c..5bb6c4f4ee 100644
--- a/engines/xeen/scripts.cpp
+++ b/engines/xeen/scripts.cpp
@@ -966,9 +966,9 @@ bool Scripts::cmdConfirmWord(ParamsIterator &params) {
for (int idx = 0; idx < MAX_TREASURE_ITEMS; ++idx) {
XeenItem &item = party._treasure._weapons[idx];
if (!item._id) {
- item._id = 34;
+ item._id = XEEN_SLAYER_SWORD;
item._material = 0;
- item._bonusFlags = 0;
+ item._state.clear();
party._treasure._hasItems = true;
return cmdExit(params);
@@ -1259,12 +1259,12 @@ bool Scripts::cmdGiveEnchanted(ParamsIterator &params) {
// Handling of misc items. Note that for them, id actually specifies the material field
item->_material = id;
item->_id = params.readByte();
- item->_bonusFlags = (item->_material == 10 || item->_material == 11) ? 1 : _vm->getRandomNumber(3, 10);
+ item->_state._counter = (item->_material == 10 || item->_material == 11) ? 1 : _vm->getRandomNumber(3, 10);
} else {
// Weapons, armor, and accessories
item->_id = id;
item->_material = params.readByte();
- item->_bonusFlags = params.readByte();
+ item->_state = params.readByte();
}
}