[Scummvm-git-logs] scummvm master -> 0bf5460ab3e96201a6ad059cbc3d4fc542f9b8b7

dreammaster noreply at scummvm.org
Tue May 23 04:34:35 UTC 2023


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

Summary:
5f5874ff84 MM: XEEN: Annotate item generation code
0bf5460ab3 MM: XEEN: Fix item enchantments random distribution


Commit: 5f5874ff84fb5a5954830edaa05cb07e5951080a
    https://github.com/scummvm/scummvm/commit/5f5874ff84fb5a5954830edaa05cb07e5951080a
Author: Alexander Izmailov (yarolig at gmail.com)
Date: 2023-05-22T21:30:00-07:00

Commit Message:
MM: XEEN: Annotate item generation code

Changed paths:
    devtools/create_mm/create_xeen/constants.cpp
    engines/mm/xeen/character.cpp
    engines/mm/xeen/item.cpp
    engines/mm/xeen/item.h
    engines/mm/xeen/party.cpp


diff --git a/devtools/create_mm/create_xeen/constants.cpp b/devtools/create_mm/create_xeen/constants.cpp
index 0fb843f5d7f..eae2cd2dc55 100644
--- a/devtools/create_mm/create_xeen/constants.cpp
+++ b/devtools/create_mm/create_xeen/constants.cpp
@@ -514,6 +514,7 @@ const int LangConstants::STAT_BONUSES[24] = {
 	7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 20
 };
 
+//                                                fire elec ice acid energy magic
 const int LangConstants::ELEMENTAL_CATEGORIES[6] = { 8, 15, 20, 25, 33, 36 };
 
 const int LangConstants::ATTRIBUTE_CATEGORIES[10] = {
@@ -576,34 +577,39 @@ const int LangConstants::ARMOR_STRENGTHS[14] = { 0, 2, 4, 5, 6, 7, 8, 10, 4, 2,
 const int LangConstants::MAKE_ITEM_ARR1[6] = { 0, 8, 15, 20, 25, 33 };
 
 const int LangConstants::MAKE_ITEM_ARR2[6][7][2] = {
-	{ { 0, 0 }, { 1, 3 }, { 2, 5 }, { 3, 6 }, { 4, 7 }, { 5, 8 }, { 8, 8 } },
-	{ { 0, 0 }, { 1, 3 }, { 2, 5 }, { 3, 6 }, { 4, 7 }, { 6, 7 }, { 7, 7 } },
-	{ { 0, 0 }, { 1, 2 }, { 1, 3 }, { 2, 4 }, { 3, 5 }, { 4, 5 }, { 5, 5 } },
-	{ { 0, 0 }, { 1, 2 }, { 1, 3 }, { 2, 4 }, { 3, 4 }, { 4, 5 }, { 5, 5 } },
-	{ { 0, 0 }, { 1, 3 }, { 2, 5 }, { 3, 6 }, { 4, 7 }, { 5, 8 }, { 8, 8 } },
-	{ { 0, 0 }, { 1, 1 }, { 1, 1 }, { 1, 2 }, { 2, 2 }, { 2, 3 }, { 3, 3 } }
+	//  L1        L2         L3        L4        L5        L6        L7
+	{ { 0, 0 }, { 1, 3 }, { 2, 5 }, { 3, 6 }, { 4, 7 }, { 5, 8 }, { 8, 8 } }, // fire
+	{ { 0, 0 }, { 1, 3 }, { 2, 5 }, { 3, 6 }, { 4, 7 }, { 6, 7 }, { 7, 7 } }, // electricity
+	{ { 0, 0 }, { 1, 2 }, { 1, 3 }, { 2, 4 }, { 3, 5 }, { 4, 5 }, { 5, 5 } }, // frost
+	{ { 0, 0 }, { 1, 2 }, { 1, 3 }, { 2, 4 }, { 3, 4 }, { 4, 5 }, { 5, 5 } }, // acid
+	{ { 0, 0 }, { 1, 3 }, { 2, 5 }, { 3, 6 }, { 4, 7 }, { 5, 8 }, { 8, 8 } }, // energy
+	{ { 0, 0 }, { 1, 1 }, { 1, 1 }, { 1, 2 }, { 2, 2 }, { 2, 3 }, { 3, 3 } }  // magic
 };
 
 const int LangConstants::MAKE_ITEM_ARR3[10][7][2] = {
-	{ { 0, 0 }, { 1, 4 }, { 2, 5 }, { 3, 6 }, { 4, 7 }, { 6, 10 }, { 10, 10 } },
-	{ { 0, 0 }, { 1, 3 }, { 2, 5 }, { 3, 6 }, { 4, 7 }, { 5, 8 }, { 8, 8 } },
-	{ { 0, 0 }, { 1, 3 }, { 2, 5 }, { 3, 6 }, { 4, 7 }, { 5, 8 }, { 8, 8 } },
-	{ { 0, 0 }, { 1, 3 }, { 2, 5 }, { 3, 6 }, { 4, 7 }, { 5, 8 }, { 8, 8 } },
-	{ { 0, 0 }, { 1, 2 }, { 1, 3 }, { 2, 4 }, { 3, 5 }, { 4, 6 }, { 6, 6 } },
-	{ { 0, 0 }, { 1, 2 }, { 2, 3 }, { 3, 4 }, { 4, 5 }, { 5, 6 }, { 6, 6 } },
-	{ { 0, 0 }, { 1, 2 }, { 1, 3 }, { 2, 4 }, { 3, 4 }, { 4, 5 }, { 5, 5 } },
-	{ { 0, 0 }, { 1, 2 }, { 1, 3 }, { 2, 4 }, { 3, 5 }, { 4, 6 }, { 6, 6 } },
-	{ { 0, 0 }, { 1, 2 }, { 1, 3 }, { 2, 4 }, { 3, 4 }, { 4, 5 }, { 5, 5 } },
-	{ { 0, 0 }, { 1, 2 }, { 1, 4 }, { 3, 6 }, { 5, 8 }, { 7, 10 }, { 10, 10 } }
+	//  L1        L2         L3        L4        L5        L6        L7
+	{ { 0, 0 }, { 1, 4 }, { 2, 5 }, { 3, 6 }, { 4, 7 }, { 6, 10 }, { 10, 10 } }, // str
+	{ { 0, 0 }, { 1, 3 }, { 2, 5 }, { 3, 6 }, { 4, 7 }, { 5, 8 }, { 8, 8 } },    // int
+	{ { 0, 0 }, { 1, 3 }, { 2, 5 }, { 3, 6 }, { 4, 7 }, { 5, 8 }, { 8, 8 } },    // per
+	{ { 0, 0 }, { 1, 3 }, { 2, 5 }, { 3, 6 }, { 4, 7 }, { 5, 8 }, { 8, 8 } },    // spd
+	{ { 0, 0 }, { 1, 2 }, { 1, 3 }, { 2, 4 }, { 3, 5 }, { 4, 6 }, { 6, 6 } },    // acc
+	{ { 0, 0 }, { 1, 2 }, { 2, 3 }, { 3, 4 }, { 4, 5 }, { 5, 6 }, { 6, 6 } },    // luc
+	{ { 0, 0 }, { 1, 2 }, { 1, 3 }, { 2, 4 }, { 3, 4 }, { 4, 5 }, { 5, 5 } },    // hp
+	{ { 0, 0 }, { 1, 2 }, { 1, 3 }, { 2, 4 }, { 3, 5 }, { 4, 6 }, { 6, 6 } },    // sp
+	{ { 0, 0 }, { 1, 2 }, { 1, 3 }, { 2, 4 }, { 3, 4 }, { 4, 5 }, { 5, 5 } },    // ac
+	{ { 0, 0 }, { 1, 2 }, { 1, 4 }, { 3, 6 }, { 5, 8 }, { 7, 10 }, { 10, 10 } }  // thievery
 };
 
 const int LangConstants::MAKE_ITEM_ARR4[2][7][2] = {
-	{ { 0, 0 }, { 1, 4 }, { 3, 7 }, { 4, 8 }, { 5, 9 }, { 8, 9 }, { 9, 9 } },
-	{ { 0, 0 }, { 1, 4 }, { 2, 6 }, { 4, 7 }, { 6, 10 }, { 9, 13 }, { 13, 13 } }
+	//  L1        L2         L3        L4        L5        L6        L7
+	{ { 0, 0 }, { 1, 4 }, { 3, 7 }, { 4, 8 }, { 5, 9 }, { 8, 9 }, { 9, 9 } },      // common
+	{ { 0, 0 }, { 1, 4 }, { 2, 6 }, { 4, 7 }, { 6, 10 }, { 9, 13 }, { 13, 13 } }   // rare and precious
 };
 
 const int LangConstants::MAKE_ITEM_ARR5[8][2] = {
+	//           L1        L2         L3             L4
 	{ 0, 0 }, { 1, 15 }, { 16, 30 }, { 31, 40 }, { 41, 50 },
+	//   L5        L6           L7
 	{ 51, 60 }, { 61, 73 }, { 61, 73 }
 };
 
diff --git a/engines/mm/xeen/character.cpp b/engines/mm/xeen/character.cpp
index 0b0476b3fb2..7549c2c18c2 100644
--- a/engines/mm/xeen/character.cpp
+++ b/engines/mm/xeen/character.cpp
@@ -561,8 +561,9 @@ int Character::itemScan(int itemId) const {
 		const XeenItem &item = _weapons[idx];
 
 		if (item._frame && !item.isBad() && itemId < 11
-				&& itemId != 3 && item._material >= 59 && item._material <= 130) {
+				&& itemId != ENDURANCE && item._material >= 59 && item._material <= 130) {
 			int mIndex = (int)item.getAttributeCategory();
+			// There is no Endurance bonus. This enchantment category skipped.
 			if (mIndex > PERSONALITY)
 				++mIndex;
 
@@ -971,21 +972,21 @@ int Character::getNumAwards() const {
 	return total;
 }
 
-ItemCategory Character::makeItem(int p1, int itemIndex, int p3) {
+ItemCategory Character::makeItem(int itemLevel, int itemIndex, int reason) {
 	XeenEngine *vm = Party::_vm;
 	int itemOffset = vm->getGameID() == GType_Swords ? 6 : 0;
 
-	if (!p1)
+	if (!itemLevel)
 		return CATEGORY_WEAPON;
 
 	int itemId = 0;
-	int v4 = vm->getRandomNumber(100);
-	int v6 = vm->getRandomNumber(p1 < 6 ? 100 : 80);
+	int categoryRN = vm->getRandomNumber(100);
+	int subcategoryRN = vm->getRandomNumber(itemLevel < 6 ? 100 : 80);
 	ItemCategory category;
-	int v16 = 0, v14 = 0, miscCharges = 0, miscId = 0, v8 = 0, v12 = 0;
+	int material = 0, attrBonus = 0, miscCharges = 0, miscId = 0, enchantmentType = 0, element = 0;
 
 	// Randomly pick a category and item Id
-	if (p3 == 12) {
+	if (reason == MAKE_ITEM_SPECIAL_EVENT) {
 		if (_itemType < (35 + itemOffset)) {
 			category = CATEGORY_WEAPON;
 			itemId = _itemType;
@@ -1000,80 +1001,81 @@ ItemCategory Character::makeItem(int p1, int itemIndex, int p3) {
 			itemId = _itemType - (60 + itemOffset);
 		}
 	} else {
-		switch (p3) {
-		case 1:
-			v4 = 35;
+		switch (reason) {
+		case MAKE_ITEM_ENCHANT_WEAPON:
+			categoryRN = 35;
 			break;
-		case 2:
-			v4 = 60;
+		case MAKE_ITEM_ENCHANT_ARMOR:
+			categoryRN = 60;
 			break;
-		case 3:
-			v4 = 100;
+		case MAKE_ITEM_ENCHANT_ACCESSORY: // never used
+			categoryRN = 100;
 			break;
 		default:
 			break;
 		}
 
-		if (p1 == 1) {
-			if (v4 <= 40) {
+		if (itemLevel == 1) {
+			if (categoryRN <= 40) {
 				category = CATEGORY_WEAPON;
-				if (v6 <= 30) {
-					itemId = vm->getRandomNumber(1, 6);
-				} else if (v6 <= 60) {
-					itemId = vm->getRandomNumber(7, 17);
-				} else if (v6 <= 85) {
-					itemId = vm->getRandomNumber(18, 29);
+				if (subcategoryRN <= 30) {
+					itemId = vm->getRandomNumber(1, 6); // swords
+				} else if (subcategoryRN <= 60) {
+					itemId = vm->getRandomNumber(7, 17); // one-handed
+				} else if (subcategoryRN <= 85) {
+					itemId = vm->getRandomNumber(18, 29); // two-handed
 				} else {
-					itemId = vm->getRandomNumber(30, 33);
+					itemId = vm->getRandomNumber(30, 33); // ranged
 				}
-			} else if (v4 <= 85) {
+			} else if (categoryRN <= 85) {
 				category = CATEGORY_ARMOR;
-				itemId = vm->getRandomNumber(1, 7);
+				itemId = vm->getRandomNumber(1, 7); // armor
 			} else {
 				category = CATEGORY_MISC;
-				itemId = vm->getRandomNumber(1, 9);
+				itemId = vm->getRandomNumber(1, 9); // wand
 			}
-		} else if (v4 <= 35) {
+		} else if (categoryRN <= 35) {
 			category = CATEGORY_WEAPON;
-			if (v6 <= 30) {
-				itemId = vm->getRandomNumber(1, 6);
-			} else if (v6 <= 60) {
-				itemId = vm->getRandomNumber(7, 17);
-			} else if (v6 <= 85) {
-				itemId = vm->getRandomNumber(18, 29);
+			if (subcategoryRN <= 30) {
+				itemId = vm->getRandomNumber(1, 6); // swords
+			} else if (subcategoryRN <= 60) {
+				itemId = vm->getRandomNumber(7, 17); // one-handed
+			} else if (subcategoryRN <= 85) {
+				itemId = vm->getRandomNumber(18, 29); // two-handed
 			} else {
-				itemId = vm->getRandomNumber(30, 33);
+				itemId = vm->getRandomNumber(30, 33); // ranged
 			}
-		} else if (v4 <= 60) {
+		} else if (categoryRN <= 60) {
 			category = CATEGORY_ARMOR;
-			itemId = (v6 > 70) ? 8 : vm->getRandomNumber(1, 7);
-		} else if (v6 <= 10) {
+			itemId = (subcategoryRN > 70) ? 8 : vm->getRandomNumber(1, 7); // shield or armor
+
+		} else if (subcategoryRN <= 10) {
 			category = CATEGORY_ARMOR;
-			itemId = 9;
-		} else if (v6 <= 20) {
+			itemId = 9; // helm
+		} else if (subcategoryRN <= 20) {
 			category = CATEGORY_ARMOR;
-			itemId = 13;
-		} else if (v6 <= 35) {
+			itemId = 13; // gauntlets
+		} else if (subcategoryRN <= 35) {
 			category = CATEGORY_ACCESSORY;
-			itemId = 1;
-		} else if (v6 <= 45) {
+			itemId = 1; // ring
+		} else if (subcategoryRN <= 45) {
 			category = CATEGORY_ARMOR;
-			itemId = 10;
-		} else if (v6 <= 55) {
+			itemId = 10; // boots
+		} else if (subcategoryRN <= 55) {
 			category = CATEGORY_ARMOR;
-			itemId = vm->getRandomNumber(11, 12);
-		} else if (v6 <= 65) {
+			itemId = vm->getRandomNumber(11, 12); // cloak, cape
+		} else if (subcategoryRN <= 65) {
 			category = CATEGORY_ACCESSORY;
-			itemId = 2;
-		} else if (v6 <= 75) {
+			itemId = 2; // belt
+		} else if (subcategoryRN <= 75) {
 			category = CATEGORY_ACCESSORY;
-			itemId = vm->getRandomNumber(3, 7);
-		} else if (v6 <= 80) {
+			itemId = vm->getRandomNumber(3, 7); // medal-like
+		} else if (subcategoryRN <= 80) {
 			category = CATEGORY_ACCESSORY;
-			itemId = vm->getRandomNumber(8, 10);
+			itemId = vm->getRandomNumber(8, 10); // amulet-like
 		} else {
 			category = CATEGORY_MISC;
-			itemId = vm->getRandomNumber(1, 9);
+			itemId = vm->getRandomNumber(1, 9); // wand-like
 		}
 	}
 
@@ -1081,101 +1083,111 @@ ItemCategory Character::makeItem(int p1, int itemIndex, int p3) {
 	newItem.clear();
 	newItem._id = itemId;
 
-	v4 = vm->getRandomNumber(1, 100);
+	int enchanntmentRN = vm->getRandomNumber(1, 100);
 	switch (category) {
 	case CATEGORY_WEAPON:
 	case CATEGORY_ARMOR:
-		if (p1 != 1) {
-			if (v4 <= 70) {
-				v8 = 3;
-			} else if (v4 <= 98) {
-				v8 = 1;
+		if (itemLevel != 1) {
+			if (enchanntmentRN <= 70) {
+				enchantmentType = ENCHANTMENT_TYPE_MATERIAL;
+			} else if (enchanntmentRN <= 98) {
+				enchantmentType = ENCHANTMENT_TYPE_ELEMENT;
 			} else {
-				v8 = 2;
+				enchantmentType = ENCHANTMENT_TYPE_ATTR_BONUS;
 			}
 		}
 		break;
 
 	case CATEGORY_ACCESSORY:
-		if (v4 <= 20) {
-			v8 = 3;
-		} else if (v4 <= 60) {
-			v8 = 1;
+		if (enchanntmentRN <= 20) {
+			enchantmentType = ENCHANTMENT_TYPE_MATERIAL;
+		} else if (enchanntmentRN <= 60) {
+			enchantmentType = ENCHANTMENT_TYPE_ELEMENT;
 		} else {
-			v8 = 2;
+			enchantmentType = ENCHANTMENT_TYPE_ATTR_BONUS;
 		}
 		break;
 
 	case CATEGORY_MISC:
 		newItem._material = itemId;
-		v8 = 4;
+		enchantmentType = ENCHANTMENT_TYPE_USABLE;
 		break;
 
 	default:
 		break;
 	}
 
-	if (p1 != 1 || category == CATEGORY_MISC) {
-		int rval, mult;
-		switch (v8) {
-		case 1:
-			rval = vm->getRandomNumber(1, 100);
-			if (rval <= 25) {
-				mult = 0;
-			} else if (rval <= 45) {
-				mult = 1;
-			} else if (rval <= 60) {
-				mult = 2;
-			} else if (rval <= 75) {
-				mult = 3;
-			} else if (rval <= 95) {
-				mult = 4;
+	if (itemLevel != 1 || category == CATEGORY_MISC) {
+		int rn, enchantmentSubtype, r1, r2;
+		switch (enchantmentType) {
+		case ENCHANTMENT_TYPE_ELEMENT:
+			rn = vm->getRandomNumber(1, 100);
+			if (rn <= 25) {
+				enchantmentSubtype = ELEM_FIRE;
+			} else if (rn <= 45) {
+				enchantmentSubtype = ELEM_ELECTRICITY;
+			} else if (rn <= 60) {
+				enchantmentSubtype = ELEM_COLD;
+			} else if (rn <= 75) {
+				enchantmentSubtype = ELEM_ACID_POISON;
+			} else if (rn <= 95) {
+				enchantmentSubtype = ELEM_ENERGY;
 			} else {
-				mult = 5;
+				enchantmentSubtype = ELEM_MAGIC;
 			}
 
-			v12 = Res.MAKE_ITEM_ARR1[vm->getRandomNumber(Res.MAKE_ITEM_ARR2[mult][p1][0],
-				Res.MAKE_ITEM_ARR2[mult][p1][1])];
+			r1 = Res.MAKE_ITEM_ARR2[enchantmentSubtype][itemLevel][0];
+			r2 = Res.MAKE_ITEM_ARR2[enchantmentSubtype][itemLevel][1];
+			element = Res.MAKE_ITEM_ARR1[vm->getRandomNumber(r1, r2)];
 			break;
-
-		case 2:
-			rval = vm->getRandomNumber(1, 100);
-			if (rval <= 15) {
-				mult = 0;
-			} else if (rval <= 25) {
-				mult = 1;
-			} else if (rval <= 35) {
-				mult = 2;
-			} else if (rval <= 50) {
-				mult = 3;
-			} else if (rval <= 65) {
-				mult = 4;
-			} else if (rval <= 80) {
-				mult = 5;
-			} else if (rval <= 85) {
-				mult = 6;
-			} else if (rval <= 90) {
-				mult = 7;
-			} else if (rval <= 95) {
-				mult = 8;
+		case ENCHANTMENT_TYPE_ATTR_BONUS:
+			rn = vm->getRandomNumber(1, 100);
+			if (rn <= 15) {
+				enchantmentSubtype = ATTR_MIGHT;
+			} else if (rn <= 25) {
+				enchantmentSubtype = ATTR_INTELLECT;
+			} else if (rn <= 35) {
+				enchantmentSubtype = ATTR_PERSONALITY;
+			} else if (rn <= 50) {
+				enchantmentSubtype = ATTR_SPEED;
+			} else if (rn <= 65) {
+				enchantmentSubtype = ATTR_ACCURACY;
+			} else if (rn <= 80) {
+				enchantmentSubtype = ATTR_LUCK;
+			} else if (rn <= 85) {
+				enchantmentSubtype = ATTR_HIT_POINTS;
+			} else if (rn <= 90) {
+				enchantmentSubtype = ATTR_SPELL_POINTS;
+			} else if (rn <= 95) {
+				enchantmentSubtype = ATTR_ARMOR_CLASS;
 			} else {
-				mult = 9;
+				enchantmentSubtype = ATTR_THIEVERY;
 			}
 
-			v14 = Res.MAKE_ITEM_ARR1[vm->getRandomNumber(Res.MAKE_ITEM_ARR3[mult][p1][0],
-				Res.MAKE_ITEM_ARR3[mult][p1][1])];
+			r1 = Res.MAKE_ITEM_ARR3[enchantmentSubtype][itemLevel][0];
+			r2 = Res.MAKE_ITEM_ARR3[enchantmentSubtype][itemLevel][1];
+			// wrong formula here:
+			attrBonus = Res.MAKE_ITEM_ARR1[vm->getRandomNumber(r1, r2)];
 			break;
 
-		case 3:
-			mult = p1 == 7 || vm->getRandomNumber(1, 100) > 70 ? 1 : 0;
-			v16 = vm->getRandomNumber(Res.MAKE_ITEM_ARR4[mult][p1 - 1][0],
-				Res.MAKE_ITEM_ARR4[mult][p1 - 1][1]);
-			if (mult)
-				v16 += 9;
+		case ENCHANTMENT_TYPE_MATERIAL:
+			enchantmentSubtype = itemLevel == 7 || vm->getRandomNumber(1, 100) > 70 ? 1 : 0;
+
+			// It is unclear why itemLevel - 1 is here.
+			r1 = Res.MAKE_ITEM_ARR4[enchantmentSubtype][itemLevel - 1][0];
+			r2 = Res.MAKE_ITEM_ARR4[enchantmentSubtype][itemLevel - 1][1];
+			material = vm->getRandomNumber(r1, r2);
+
+			// Change from common/rare to rare/precious
+			if (enchantmentSubtype)
+				material += 9;
 			break;
 
-		case 4:
-			miscId = vm->getRandomNumber(Res.MAKE_ITEM_ARR5[p1][0], Res.MAKE_ITEM_ARR5[p1][1]);
+		case ENCHANTMENT_TYPE_USABLE:
+			r1 = Res.MAKE_ITEM_ARR5[itemLevel][0];
+			r2 = Res.MAKE_ITEM_ARR5[itemLevel][1];
+
+			miscId = vm->getRandomNumber(r1, r2);
 			miscCharges = vm->getRandomNumber(1, 8);
 			break;
 
@@ -1186,17 +1198,25 @@ ItemCategory Character::makeItem(int p1, int itemIndex, int p3) {
 
 	switch (category) {
 	case CATEGORY_WEAPON:
-		if (p1 != 1) {
-			newItem._material = (v14 ? v14 + 58 : 0) + (v16 ? v16 + 36 : 0) + v12;
-			if (vm->getRandomNumber(20) == 10)
-				newItem._state._counter = vm->getRandomNumber(1, 6);
+		if (itemLevel != 1) {
+			newItem._material = (attrBonus ? attrBonus + 58 : 0) +
+								(material ? material + 36 : 0) +
+								element;
+
+
+			if (vm->getRandomNumber(20) == 10) {
+				// of undead/golem/dragon/etc-slaying
+				newItem._state._counter = vm->getRandomNumber(EFFECTIVE_DRAGON, EFFECTIVE_ANIMAL);
+			}
 		}
 		break;
 
 	case CATEGORY_ARMOR:
 	case CATEGORY_ACCESSORY:
-		if (p1 != 1) {
-			newItem._material = (v14 ? v14 + 58 : 0) + (v16 ? v16 + 36 : 0) + v12;
+		if (itemLevel != 1) {
+			newItem._material = (attrBonus ? attrBonus + 58 : 0) +
+								(material ? material + 36 : 0) +
+								element;
 		}
 		break;
 
diff --git a/engines/mm/xeen/item.cpp b/engines/mm/xeen/item.cpp
index 763128efa4c..aa7c92eb47a 100644
--- a/engines/mm/xeen/item.cpp
+++ b/engines/mm/xeen/item.cpp
@@ -383,7 +383,8 @@ void WeaponItems::enchantItem(int itemIndex, int amount) {
 	Character tempCharacter;
 
 	if (item._material == 0 && item._state.empty() && item._id < XEEN_SLAYER_SWORD) {
-		tempCharacter.makeItem(amount, 0, 1);
+		// make a random enchanted weapon and then copy its enchantments
+		tempCharacter.makeItem(amount, 0, MAKE_ITEM_ENCHANT_WEAPON);
 		XeenItem &tempItem = tempCharacter._weapons[0];
 
 		if (tempItem._material != 0 || !tempItem._state.empty()) {
@@ -565,7 +566,8 @@ void ArmorItems::enchantItem(int itemIndex, int amount) {
 	Character tempCharacter;
 
 	if (item._material == 0 && item._state.empty()) {
-		tempCharacter.makeItem(amount, 0, 2);
+		// make a random enchanted armor and then copy its enchantments
+		tempCharacter.makeItem(amount, 0, MAKE_ITEM_ENCHANT_ARMOR);
 		XeenItem &tempItem = tempCharacter._armor[0];
 
 		if (tempItem._material != 0 || !tempItem._state.empty()) {
diff --git a/engines/mm/xeen/item.h b/engines/mm/xeen/item.h
index 125128216e1..257ee6306e8 100644
--- a/engines/mm/xeen/item.h
+++ b/engines/mm/xeen/item.h
@@ -52,6 +52,11 @@ enum ElementalCategory {
 	ELEM_ENERGY = 4, ELEM_MAGIC = 5
 };
 
+enum EnchantmentType {
+	ENCHANTMENT_TYPE_ELEMENT = 1, ENCHANTMENT_TYPE_ATTR_BONUS = 2,
+	ENCHANTMENT_TYPE_MATERIAL = 3, ENCHANTMENT_TYPE_USABLE = 4
+};
+
 enum WeaponId {
 	XEEN_SLAYER_SWORD = 34
 };
@@ -61,6 +66,11 @@ enum Effectiveness {
 	EFFECTIVE_INSECT = 4, EFFEctIVE_MONSTERS = 5, EFFECTIVE_ANIMAL = 6
 };
 
+enum MakeItemReason {
+	MAKE_ITEM_ENCHANT_WEAPON = 1, MAKE_ITEM_ENCHANT_ARMOR = 2,
+	MAKE_ITEM_ENCHANT_ACCESSORY = 3, MAKE_ITEM_SPECIAL_EVENT = 12
+};
+
 struct ItemState {
 	byte _counter : 6;		// Stores charges for Misc items, and the effective against for weapons
 	bool _cursed : 1;
diff --git a/engines/mm/xeen/party.cpp b/engines/mm/xeen/party.cpp
index 2a25234c320..f9f2aac9a7c 100644
--- a/engines/mm/xeen/party.cpp
+++ b/engines/mm/xeen/party.cpp
@@ -1385,7 +1385,7 @@ bool Party::giveTake(int takeMode, uint takeVal, int giveMode, uint giveVal, int
 		}
 
 		// Create the item and it's category
-		ItemCategory itemCat = tempChar.makeItem(giveVal, 0, (idx == -1) ? 0 : 12);
+		ItemCategory itemCat = tempChar.makeItem(giveVal, 0, (idx == -1) ? 0 : MAKE_ITEM_SPECIAL_EVENT);
 		XeenItem &srcItem = tempChar._items[itemCat][0];
 		XeenItem *trItems = _treasure[itemCat];
 


Commit: 0bf5460ab3e96201a6ad059cbc3d4fc542f9b8b7
    https://github.com/scummvm/scummvm/commit/0bf5460ab3e96201a6ad059cbc3d4fc542f9b8b7
Author: Alexander Izmailov (yarolig at gmail.com)
Date: 2023-05-22T21:30:05-07:00

Commit Message:
MM: XEEN: Fix item enchantments random distribution

Changed paths:
    engines/mm/xeen/character.cpp
    engines/mm/xeen/item.cpp


diff --git a/engines/mm/xeen/character.cpp b/engines/mm/xeen/character.cpp
index 7549c2c18c2..66d8688b25d 100644
--- a/engines/mm/xeen/character.cpp
+++ b/engines/mm/xeen/character.cpp
@@ -973,6 +973,9 @@ int Character::getNumAwards() const {
 }
 
 ItemCategory Character::makeItem(int itemLevel, int itemIndex, int reason) {
+	assert(1 <= itemLevel && itemLevel <= 7);
+	assert(0 <= itemIndex && itemIndex < INV_ITEMS_TOTAL);
+
 	XeenEngine *vm = Party::_vm;
 	int itemOffset = vm->getGameID() == GType_Swords ? 6 : 0;
 
@@ -981,6 +984,7 @@ ItemCategory Character::makeItem(int itemLevel, int itemIndex, int reason) {
 
 	int itemId = 0;
 	int categoryRN = vm->getRandomNumber(100);
+	// generate no wands, no bows and less two-handed weapons on levels 6 and 7
 	int subcategoryRN = vm->getRandomNumber(itemLevel < 6 ? 100 : 80);
 	ItemCategory category;
 	int material = 0, attrBonus = 0, miscCharges = 0, miscId = 0, enchantmentType = 0, element = 0;
@@ -1084,6 +1088,7 @@ ItemCategory Character::makeItem(int itemLevel, int itemIndex, int reason) {
 	newItem._id = itemId;
 
 	int enchanntmentRN = vm->getRandomNumber(1, 100);
+
 	switch (category) {
 	case CATEGORY_WEAPON:
 	case CATEGORY_ARMOR:
@@ -1136,9 +1141,9 @@ ItemCategory Character::makeItem(int itemLevel, int itemIndex, int reason) {
 				enchantmentSubtype = ELEM_MAGIC;
 			}
 
-			r1 = Res.MAKE_ITEM_ARR2[enchantmentSubtype][itemLevel][0];
-			r2 = Res.MAKE_ITEM_ARR2[enchantmentSubtype][itemLevel][1];
-			element = Res.MAKE_ITEM_ARR1[vm->getRandomNumber(r1, r2)];
+			r1 = Res.MAKE_ITEM_ARR2[enchantmentSubtype][itemLevel - 1][0];
+			r2 = Res.MAKE_ITEM_ARR2[enchantmentSubtype][itemLevel - 1][1];
+			element = Res.MAKE_ITEM_ARR1[enchantmentSubtype] + vm->getRandomNumber(r1, r2);
 			break;
 		case ENCHANTMENT_TYPE_ATTR_BONUS:
 			rn = vm->getRandomNumber(1, 100);
@@ -1164,16 +1169,19 @@ ItemCategory Character::makeItem(int itemLevel, int itemIndex, int reason) {
 				enchantmentSubtype = ATTR_THIEVERY;
 			}
 
-			r1 = Res.MAKE_ITEM_ARR3[enchantmentSubtype][itemLevel][0];
-			r2 = Res.MAKE_ITEM_ARR3[enchantmentSubtype][itemLevel][1];
-			// wrong formula here:
-			attrBonus = Res.MAKE_ITEM_ARR1[vm->getRandomNumber(r1, r2)];
+			{
+				// similar to Res.ATTRIBUTE_CATEGORIES
+				const int SUBTYPE_OFFSETS[] = {0, 10, 18, 26, 34, 40, 46, 51, 57, 62, 72};
+
+				r1 = Res.MAKE_ITEM_ARR3[enchantmentSubtype][itemLevel - 1][0];
+				r2 = Res.MAKE_ITEM_ARR3[enchantmentSubtype][itemLevel - 1][1];
+				attrBonus = SUBTYPE_OFFSETS[enchantmentSubtype] + vm->getRandomNumber(r1, r2);
+			}
 			break;
 
 		case ENCHANTMENT_TYPE_MATERIAL:
-			enchantmentSubtype = itemLevel == 7 || vm->getRandomNumber(1, 100) > 70 ? 1 : 0;
 
-			// It is unclear why itemLevel - 1 is here.
+			enchantmentSubtype = itemLevel == 7 || vm->getRandomNumber(1, 100) > 70 ? 1 : 0;
 			r1 = Res.MAKE_ITEM_ARR4[enchantmentSubtype][itemLevel - 1][0];
 			r2 = Res.MAKE_ITEM_ARR4[enchantmentSubtype][itemLevel - 1][1];
 			material = vm->getRandomNumber(r1, r2);
diff --git a/engines/mm/xeen/item.cpp b/engines/mm/xeen/item.cpp
index aa7c92eb47a..09a88fec9dd 100644
--- a/engines/mm/xeen/item.cpp
+++ b/engines/mm/xeen/item.cpp
@@ -64,11 +64,12 @@ void XeenItem::synchronize(Common::Serializer &s) {
 }
 
 ElementalCategory XeenItem::getElementalCategory() const {
-	assert(_material < 36);
+	assert(_material <= 36);
 	return getElementalCategory(_material);
 }
 
 ElementalCategory XeenItem::getElementalCategory(int material) {
+	assert(material <= 36);
 	int idx;
 	for (idx = 0; Res.ELEMENTAL_CATEGORIES[idx] < material; ++idx)
 		;
@@ -77,6 +78,7 @@ ElementalCategory XeenItem::getElementalCategory(int material) {
 }
 
 AttributeCategory XeenItem::getAttributeCategory() const {
+	assert(59 <= _material && _material <= 130);
 	int m = _material - 59;
 	int idx;
 	for (idx = 0; Res.ATTRIBUTE_CATEGORIES[idx] < m; ++idx)




More information about the Scummvm-git-logs mailing list