diff options
author | Paul Gilbert | 2018-03-31 12:37:36 -0400 |
---|---|---|
committer | Paul Gilbert | 2018-03-31 12:37:36 -0400 |
commit | 31bcb0961981e3e647b2de912927145e8e9429aa (patch) | |
tree | 0bc9f8c159820509b3bf8628a80b4345050488c0 | |
parent | 572dbd86239426c54776f02a538f1bea45f4abd3 (diff) | |
download | scummvm-rg350-31bcb0961981e3e647b2de912927145e8e9429aa.tar.gz scummvm-rg350-31bcb0961981e3e647b2de912927145e8e9429aa.tar.bz2 scummvm-rg350-31bcb0961981e3e647b2de912927145e8e9429aa.zip |
XEEN: Cleanup of item bonus flags to a bitfield state structure
-rw-r--r-- | engines/xeen/character.cpp | 18 | ||||
-rw-r--r-- | engines/xeen/character.h | 4 | ||||
-rw-r--r-- | engines/xeen/combat.cpp | 36 | ||||
-rw-r--r-- | engines/xeen/dialogs/dialogs_items.cpp | 33 | ||||
-rw-r--r-- | engines/xeen/item.cpp | 106 | ||||
-rw-r--r-- | engines/xeen/item.h | 70 | ||||
-rw-r--r-- | engines/xeen/locations.cpp | 17 | ||||
-rw-r--r-- | engines/xeen/map.cpp | 2 | ||||
-rw-r--r-- | engines/xeen/map.h | 2 | ||||
-rw-r--r-- | engines/xeen/party.cpp | 10 | ||||
-rw-r--r-- | engines/xeen/scripts.cpp | 8 |
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 ¶ms) { 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 ¶ms) { // 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(); } } |