[Scummvm-git-logs] scummvm master -> 31bcb0961981e3e647b2de912927145e8e9429aa

dreammaster dreammaster at scummvm.org
Sat Mar 31 18:37:38 CEST 2018


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

Summary:
31bcb09619 XEEN: Cleanup of item bonus flags to a bitfield state structure


Commit: 31bcb0961981e3e647b2de912927145e8e9429aa
    https://github.com/scummvm/scummvm/commit/31bcb0961981e3e647b2de912927145e8e9429aa
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-03-31T12:37:36-04:00

Commit Message:
XEEN: Cleanup of item bonus flags to a bitfield state structure

Changed paths:
    engines/xeen/character.cpp
    engines/xeen/character.h
    engines/xeen/combat.cpp
    engines/xeen/dialogs/dialogs_items.cpp
    engines/xeen/item.cpp
    engines/xeen/item.h
    engines/xeen/locations.cpp
    engines/xeen/map.cpp
    engines/xeen/map.h
    engines/xeen/party.cpp
    engines/xeen/scripts.cpp


diff --git a/engines/xeen/character.cpp b/engines/xeen/character.cpp
index 2eb37bc..50ad2fe 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 019fd9b..77e3360 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 3a248e5..2c87018 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 2e01681..41233c9 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 cb18bd4..c52f4e9 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 105df0e..9bd70c7 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 6f8bc82..9b0eec3 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 ce14553..19312b6 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 c34ef9e..a84c338 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 d6ef377..dc90863 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 9700047..5bb6c4f 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();
 		}
 	}
 





More information about the Scummvm-git-logs mailing list