From: Lyberta <lyberta@lyberta.net>
Date: Mon, 19 Mar 2018 12:22:20 +0000 (+0300)
Subject: Better random item selection algorithm.
X-Git-Tag: xonotic-v0.8.5~2207^2~4
X-Git-Url: https://git.rm.cloudns.org/?a=commitdiff_plain;h=81ff677563ba3b90fd7a8e7a868d7f80073f50c4;p=xonotic%2Fxonotic-data.pk3dir.git

Better random item selection algorithm.
---

diff --git a/qcsrc/common/items/item.qh b/qcsrc/common/items/item.qh
index e59152076..22f291f6b 100644
--- a/qcsrc/common/items/item.qh
+++ b/qcsrc/common/items/item.qh
@@ -8,6 +8,7 @@
 #endif
 
 #ifdef SVQC
+#include <server/defs.qh>
 #include <server/items.qh>
 #endif
 
@@ -56,7 +57,7 @@ const int IT_PICKUPMASK                	= IT_UNLIMITED_AMMO | IT_JETPACK | IT_FU
 	{ \
 		if (!Item_IsDefinitionAllowed(item)) \
 		{ \
-			startitem_failed = true; \
+			/*startitem_failed = true;*/ \
 			delete(this); \
 			return; \
 		} \
diff --git a/qcsrc/common/mutators/mutator/random_items/sv_random_items.qc b/qcsrc/common/mutators/mutator/random_items/sv_random_items.qc
index 3d5d5c0f8..553dcf582 100644
--- a/qcsrc/common/mutators/mutator/random_items/sv_random_items.qc
+++ b/qcsrc/common/mutators/mutator/random_items/sv_random_items.qc
@@ -7,15 +7,6 @@
 
 //============================ Constants ======================================
 
-enum
-{
-	RANDOM_ITEM_TYPE_HEALTH = 1,
-	RANDOM_ITEM_TYPE_ARMOR,
-	RANDOM_ITEM_TYPE_RESOURCE,
-	RANDOM_ITEM_TYPE_WEAPON,
-	RANDOM_ITEM_TYPE_POWERUP
-};
-
 //======================= Global variables ====================================
 
 // Replace cvars
@@ -72,99 +63,137 @@ string RandomItems_GetRandomItemClassName(string prefix)
 	{
 		return RandomItems_GetRandomOverkillItemClassName(prefix);
 	}
-	return RandomItems_GetRandomVanillaItemClassName(prefix);
+	return RandomItems_GetRandomVanillaItemClassName(prefix,
+		RANDOM_ITEM_TYPE_ALL);
 }
 
-string RandomItems_GetRandomVanillaItemClassName(string prefix)
+string RandomItems_GetRandomVanillaItemClassName(string prefix, int types)
 {
-	RandomSelection_Init();
-	string cvar_name = sprintf("g_%s_health_probability", prefix);
-	if (!(cvar_type(cvar_name) & CVAR_TYPEFLAG_EXISTS))
-	{
-		LOG_WARNF("Random items: cvar %s doesn't exist.", cvar_name);
-	}
-	else
-	{
-		RandomSelection_AddFloat(RANDOM_ITEM_TYPE_HEALTH, cvar(cvar_name), 1);
-	}
-	cvar_name = sprintf("g_%s_armor_probability", prefix);
-	if (!(cvar_type(cvar_name) & CVAR_TYPEFLAG_EXISTS))
-	{
-		LOG_WARNF("Random items: cvar %s doesn't exist.", cvar_name);
-	}
-	else
+	if (types == 0)
 	{
-		RandomSelection_AddFloat(RANDOM_ITEM_TYPE_ARMOR, cvar(cvar_name), 1);
-	}
-	cvar_name = sprintf("g_%s_resource_probability", prefix);
-	if (!(cvar_type(cvar_name) & CVAR_TYPEFLAG_EXISTS))
-	{
-		LOG_WARNF("Random items: cvar %s doesn't exist.", cvar_name);
-	}
-	else
-	{
-		RandomSelection_AddFloat(RANDOM_ITEM_TYPE_RESOURCE, cvar(cvar_name), 1);
-	}
-	cvar_name = sprintf("g_%s_weapon_probability", prefix);
-	if (!(cvar_type(cvar_name) & CVAR_TYPEFLAG_EXISTS))
-	{
-		LOG_WARNF("Random items: cvar %s doesn't exist.", cvar_name);
-	}
-	else
-	{
-		RandomSelection_AddFloat(RANDOM_ITEM_TYPE_WEAPON, cvar(cvar_name), 1);
-	}
-	cvar_name = sprintf("g_%s_powerup_probability", prefix);
-	if (!(cvar_type(cvar_name) & CVAR_TYPEFLAG_EXISTS))
-	{
-		LOG_WARNF("Random items: cvar %s doesn't exist.", cvar_name);
-	}
-	else
-	{
-		RandomSelection_AddFloat(RANDOM_ITEM_TYPE_POWERUP, cvar(cvar_name), 1);
+		return "";
 	}
-	int item_type = RandomSelection_chosen_float;
-	switch (item_type)
+	while (types != 0)
 	{
-		case RANDOM_ITEM_TYPE_HEALTH:
+		string cvar_name;
+		RandomSelection_Init();
+		if (types & RANDOM_ITEM_TYPE_HEALTH)
 		{
-			return RandomItems_GetRandomItemClassNameWithProperty(prefix,
-				instanceOfHealth);
+			cvar_name = sprintf("g_%s_health_probability", prefix);
+			if (!(cvar_type(cvar_name) & CVAR_TYPEFLAG_EXISTS))
+			{
+				LOG_WARNF("Random items: cvar %s doesn't exist.", cvar_name);
+			}
+			else
+			{
+				RandomSelection_AddFloat(RANDOM_ITEM_TYPE_HEALTH,
+					cvar(cvar_name), 1);
+			}
 		}
-		case RANDOM_ITEM_TYPE_ARMOR:
+		if (types & RANDOM_ITEM_TYPE_ARMOR)
 		{
-			return RandomItems_GetRandomItemClassNameWithProperty(prefix,
-				instanceOfArmor);
+			cvar_name = sprintf("g_%s_armor_probability", prefix);
+			if (!(cvar_type(cvar_name) & CVAR_TYPEFLAG_EXISTS))
+			{
+				LOG_WARNF("Random items: cvar %s doesn't exist.", cvar_name);
+			}
+			else
+			{
+				RandomSelection_AddFloat(RANDOM_ITEM_TYPE_ARMOR,
+					cvar(cvar_name), 1);
+			}
 		}
-		case RANDOM_ITEM_TYPE_RESOURCE:
+		if (types & RANDOM_ITEM_TYPE_RESOURCE)
 		{
-			return RandomItems_GetRandomItemClassNameWithProperty(prefix,
-				instanceOfAmmo);
+			cvar_name = sprintf("g_%s_resource_probability", prefix);
+			if (!(cvar_type(cvar_name) & CVAR_TYPEFLAG_EXISTS))
+			{
+				LOG_WARNF("Random items: cvar %s doesn't exist.", cvar_name);
+			}
+			else
+			{
+				RandomSelection_AddFloat(RANDOM_ITEM_TYPE_RESOURCE,
+					cvar(cvar_name), 1);
+			}
+		}
+		if (types & RANDOM_ITEM_TYPE_WEAPON)
+		{
+			cvar_name = sprintf("g_%s_weapon_probability", prefix);
+			if (!(cvar_type(cvar_name) & CVAR_TYPEFLAG_EXISTS))
+			{
+				LOG_WARNF("Random items: cvar %s doesn't exist.", cvar_name);
+			}
+			else
+			{
+				RandomSelection_AddFloat(RANDOM_ITEM_TYPE_WEAPON, cvar(cvar_name), 1);
+			}
+		}
+		if (types & RANDOM_ITEM_TYPE_POWERUP)
+		{
+			cvar_name = sprintf("g_%s_powerup_probability", prefix);
+			if (!(cvar_type(cvar_name) & CVAR_TYPEFLAG_EXISTS))
+			{
+				LOG_WARNF("Random items: cvar %s doesn't exist.", cvar_name);
+			}
+			else
+			{
+				RandomSelection_AddFloat(RANDOM_ITEM_TYPE_POWERUP, cvar(cvar_name), 1);
+			}
 		}
-		case RANDOM_ITEM_TYPE_WEAPON:
+		int item_type = RandomSelection_chosen_float;
+		string class_name = "";
+		switch (item_type)
 		{
-			RandomSelection_Init();
-			FOREACH(Weapons, it != WEP_Null &&
-				!(it.spawnflags & WEP_FLAG_MUTATORBLOCKED),
+			case RANDOM_ITEM_TYPE_HEALTH:
+			{
+				class_name = RandomItems_GetRandomItemClassNameWithProperty(
+					prefix, instanceOfHealth);
+				break;
+			}
+			case RANDOM_ITEM_TYPE_ARMOR:
+			{
+				class_name = RandomItems_GetRandomItemClassNameWithProperty(
+					prefix, instanceOfArmor);
+				break;
+			}
+			case RANDOM_ITEM_TYPE_RESOURCE:
 			{
-				cvar_name = sprintf("g_%s_%s_probability", prefix,
-					it.m_canonical_spawnfunc);
-				if (!(cvar_type(cvar_name) & CVAR_TYPEFLAG_EXISTS))
+				class_name = RandomItems_GetRandomItemClassNameWithProperty(
+					prefix, instanceOfAmmo);
+				break;
+			}
+			case RANDOM_ITEM_TYPE_WEAPON:
+			{
+				RandomSelection_Init();
+				FOREACH(Weapons, it != WEP_Null &&
+					!(it.spawnflags & WEP_FLAG_MUTATORBLOCKED),
 				{
-					LOG_WARNF("Random items: cvar %s doesn't exist.",
-						cvar_name);
-					continue;
-				}
-				RandomSelection_AddString(it.m_canonical_spawnfunc,
-					cvar(cvar_name), 1);
-			});
-			return RandomSelection_chosen_string;
+					cvar_name = sprintf("g_%s_%s_probability", prefix,
+						it.m_canonical_spawnfunc);
+					if (!(cvar_type(cvar_name) & CVAR_TYPEFLAG_EXISTS))
+					{
+						LOG_WARNF("Random items: cvar %s doesn't exist.",
+							cvar_name);
+						continue;
+					}
+					RandomSelection_AddString(it.m_canonical_spawnfunc,
+						cvar(cvar_name), 1);
+				});
+				class_name = RandomSelection_chosen_string;
+				break;
+			}
+			case RANDOM_ITEM_TYPE_POWERUP:
+			{
+				class_name = RandomItems_GetRandomItemClassNameWithProperty(
+					prefix, instanceOfPowerup);
+				break;
+			}
 		}
-		case RANDOM_ITEM_TYPE_POWERUP:
+		if (class_name != "")
 		{
-			return RandomItems_GetRandomItemClassNameWithProperty(prefix,
-				instanceOfPowerup);
+			return class_name;
 		}
+		types &= ~item_type;
 	}
 	return "";
 }
diff --git a/qcsrc/common/mutators/mutator/random_items/sv_random_items.qh b/qcsrc/common/mutators/mutator/random_items/sv_random_items.qh
index c9b4dbb90..575336301 100644
--- a/qcsrc/common/mutators/mutator/random_items/sv_random_items.qh
+++ b/qcsrc/common/mutators/mutator/random_items/sv_random_items.qh
@@ -7,6 +7,16 @@
 
 bool autocvar_g_random_items; ///< Whether to enable random items.
 
+enum
+{
+	RANDOM_ITEM_TYPE_HEALTH = BIT(1),
+	RANDOM_ITEM_TYPE_ARMOR = BIT(2),
+	RANDOM_ITEM_TYPE_RESOURCE = BIT(3),
+	RANDOM_ITEM_TYPE_WEAPON = BIT(4),
+	RANDOM_ITEM_TYPE_POWERUP = BIT(5),
+	RANDOM_ITEM_TYPE_ALL = BITS(6)
+};
+
 /// \brief Returns a random classname of the item.
 /// \param[in] prefix Prefix of the cvars that hold probabilities.
 /// \return Random classname of the item.
@@ -16,10 +26,11 @@ string RandomItems_GetRandomItemClassName(string prefix);
 
 /// \brief Returns a random classname of the vanilla item.
 /// \param[in] prefix Prefix of the cvars that hold probabilities.
+/// \param[in] types Bitmask of the types. See RANDOM_ITEM_TYPE constants.
 /// \return Random classname of the vanilla item.
 /// \note This includes mutator items that don't change gameplay a lot such as
 /// jetpack and new toys.
-string RandomItems_GetRandomVanillaItemClassName(string prefix);
+string RandomItems_GetRandomVanillaItemClassName(string prefix, int types);
 
 /// \brief Returns a random classname of the instagib item.
 /// \param[in] prefix Prefix of the cvars that hold probabilities.