Jump to content
  • 0

Randomizing Random Option


mawjustin

Question


  • Group:  Members
  • Topic Count:  47
  • Topics Per Day:  0.01
  • Content Count:  121
  • Reputation:   6
  • Joined:  09/26/14
  • Last Seen:  

May we ask for assistance on how to implement this? Specifically Mr. Jhedzkie's

I have this Random Option working already, but if I will to follow the current setup, it will take around 10k lines for me to finish.

I hope someone will post on how did Mr. Jhedzkie'  did his.

Link to comment
Share on other sites

12 answers to this question

Recommended Posts

  • 3

  • Group:  Members
  • Topic Count:  16
  • Topics Per Day:  0.00
  • Content Count:  658
  • Reputation:   663
  • Joined:  11/12/12
  • Last Seen:  

Heya,

If you want to achieve that behavior, you'll have to change a whole bunch of code. There was an earlier version of the system which greatly simplified the randomness of random option enchants. The system would rely on 3 files:

db/re/item_randomopt_db.txt (remains the same)
db/re/item_randoption_equips.txt (this replaces the db/re/mob_drops.txt file, the random options are instead attached to the weapon itself, rather than the mob the weapon drops from)
db/re/item_randoption_group.txt (remains mostly the same, except you add another optional column for the max value of the field)

item_randoption_equips.txt would look as below. You first define the random options for the specific weapons as such:

// Items Random Option Database	
//
// Structure of Database:
// Item_ID,RandomOption_GroupId1{,RandomOption_GroupId2,RandomOption_GroupId3,RandomOption_GroupId4,RandomOption_GroupId5}

28705,RDMOPTG_Crimson_Weapon_1,RDMOPTG_Crimson_Weapon_2,RDMOPTG_Crimson_Weapon_3
13327,RDMOPTG_Crimson_Weapon_1
28604,RDMOPTG_Crimson_Weapon_1
28007,RDMOPTG_Crimson_Weapon_1
1839,RDMOPTG_Crimson_Weapon_1
1498,RDMOPTG_Crimson_Weapon_1
16040,RDMOPTG_Crimson_Weapon_1
13454,RDMOPTG_Crimson_Weapon_1
1443,RDMOPTG_Crimson_Weapon_1
28106,RDMOPTG_Crimson_Weapon_1
21015,RDMOPTG_Crimson_Weapon_1
1939,RDMOPTG_Crimson_Weapon_1
1995,RDMOPTG_Crimson_Weapon_1

The random options for each groups are defined in item_randoption_group.txt. In the sample below, you'll notice a new colum for the 2nd and 3rd random options I chose, which will make the value vary between 30~50 for the earth resistance and 5~10 for... the others.

// Items Random Option Database	
//
// Structure of Database:
// Group_ID,rate,randopt_id1,randopt_value1,randopt_param1

// Crimson Weapon
RDMOPTG_Crimson_Weapon_1,1,RDMOPT_WEAPON_ATTR_NOTHING,0,0
RDMOPTG_Crimson_Weapon_1,1,RDMOPT_WEAPON_ATTR_WATER,0,0
RDMOPTG_Crimson_Weapon_1,1,RDMOPT_WEAPON_ATTR_GROUND,0,0
RDMOPTG_Crimson_Weapon_1,1,RDMOPT_WEAPON_ATTR_FIRE,0,0
RDMOPTG_Crimson_Weapon_1,1,RDMOPT_WEAPON_ATTR_WIND,0,0
RDMOPTG_Crimson_Weapon_1,1,RDMOPT_WEAPON_ATTR_SAINT,0,0

RDMOPTG_Crimson_Weapon_2,1,RDMOPT_ATTR_TOLERACE_GROUND,30,0,50

RDMOPTG_Crimson_Weapon_3,1,RDMOPT_DAMAGE_PROPERTY_GROUND_USER,5,0,10
RDMOPTG_Crimson_Weapon_3,1,RDMOPT_DAMAGE_PROPERTY_NOTHING_TARGET,5,0,10
RDMOPTG_Crimson_Weapon_3,1,RDMOPT_DAMAGE_PROPERTY_WATER_TARGET,5,0,10
RDMOPTG_Crimson_Weapon_3,1,RDMOPT_DAMAGE_PROPERTY_FIRE_USER,5,0,10

As for the source change, you can apply the diff below and do some tests with it (I didn't test it too seriously, it worked well enough for what I believe your request was though). The current weight/ratio system used... doesn't make any sense, so I made my own.

diff --git a/db/re/item_randomopt_group.txt b/db/re/item_randomopt_group.txt
index 6d9b9929a..05d579f9a 100644
--- a/db/re/item_randomopt_group.txt
+++ b/db/re/item_randomopt_group.txt
@@ -1,10 +1,16 @@
 // <randopt_groupid>,<rate>,<randopt_id1>,<randopt_value1>,<randopt_param1>{,<randopt_id2>,<randopt_value2>,<randopt_param2>,<randopt_id3>,<randopt_value3>,<randopt_param3>,<randopt_id4>,<randopt_value4>,<randopt_param4>,<randopt_id5>,<randopt_value5>,<randopt_param5>}
 
 // Crimson Weapon
-RDMOPTG_Crimson_Weapon,1,RDMOPT_WEAPON_ATTR_NOTHING,0,0
-RDMOPTG_Crimson_Weapon,1,RDMOPT_WEAPON_ATTR_WATER,0,0
-RDMOPTG_Crimson_Weapon,1,RDMOPT_WEAPON_ATTR_GROUND,0,0
-RDMOPTG_Crimson_Weapon,1,RDMOPT_WEAPON_ATTR_FIRE,0,0
-RDMOPTG_Crimson_Weapon,1,RDMOPT_WEAPON_ATTR_WIND,0,0
-RDMOPTG_Crimson_Weapon,1,RDMOPT_WEAPON_ATTR_SAINT,0,0
-RDMOPTG_Crimson_Weapon,1,RDMOPT_WEAPON_ATTR_DARKNESS,0,0
+RDMOPTG_Crimson_Weapon_1,1,RDMOPT_WEAPON_ATTR_NOTHING,0,0
+RDMOPTG_Crimson_Weapon_1,1,RDMOPT_WEAPON_ATTR_WATER,0,0
+RDMOPTG_Crimson_Weapon_1,1,RDMOPT_WEAPON_ATTR_GROUND,0,0
+RDMOPTG_Crimson_Weapon_1,1,RDMOPT_WEAPON_ATTR_FIRE,0,0
+RDMOPTG_Crimson_Weapon_1,1,RDMOPT_WEAPON_ATTR_WIND,0,0
+RDMOPTG_Crimson_Weapon_1,1,RDMOPT_WEAPON_ATTR_SAINT,0,0
+
+RDMOPTG_Crimson_Weapon_2,1,RDMOPT_ATTR_TOLERACE_GROUND,30,0,50
+
+RDMOPTG_Crimson_Weapon_3,1,RDMOPT_DAMAGE_PROPERTY_GROUND_USER,5,0,10
+RDMOPTG_Crimson_Weapon_3,1,RDMOPT_DAMAGE_PROPERTY_NOTHING_TARGET,5,0,10
+RDMOPTG_Crimson_Weapon_3,1,RDMOPT_DAMAGE_PROPERTY_WATER_TARGET,5,0,10
+RDMOPTG_Crimson_Weapon_3,1,RDMOPT_DAMAGE_PROPERTY_FIRE_USER,5,0,10
\ No newline at end of file
diff --git a/src/map/atcommand.cpp b/src/map/atcommand.cpp
index 266f37526..b0c6874e3 100644
--- a/src/map/atcommand.cpp
+++ b/src/map/atcommand.cpp
@@ -1403,6 +1403,9 @@ ACMD_FUNC(item)
 				item_tmp.nameid = item_id;
 				item_tmp.identify = 1;
 				item_tmp.bound = bound;
+
+				itemdb_add_randomopt(&item_tmp);
+
 				if ((flag = pc_additem(sd, &item_tmp, get_count, LOG_TYPE_COMMAND)))
 					clif_additem(sd, 0, 0, flag);
 			}
diff --git a/src/map/itemdb.cpp b/src/map/itemdb.cpp
index 56ced4d34..f7f606c4e 100644
--- a/src/map/itemdb.cpp
+++ b/src/map/itemdb.cpp
@@ -1783,53 +1783,138 @@ struct s_random_opt_group *itemdb_randomopt_group_exists(int id) {
 static bool itemdb_read_randomopt_group(char* str[], int columns, int current) {
 	int64 id_tmp;
 	int id = 0;
-	int i;
+	int64 randid_tmp;
+	int randid = 0;
 	unsigned short rate = (unsigned short)strtoul(str[1], NULL, 10);
 	struct s_random_opt_group *g = NULL;
 
 	if (!script_get_constant(str[0], &id_tmp)) {
-		ShowError("itemdb_read_randomopt_group: Invalid ID for Random Option Group '%s'.\n", str[0]);
-		return false;
+		// autogenerate constant, it gets annoying to define it everytime
+		script_set_constant(trim(str[0]), add_str(trim(str[0])), false, false);
+		
+		if (!script_get_constant(trim(str[0]), &id_tmp)) {	// Should never happen?
+			ShowError("itemdb_read_randomopt_group: Invalid ID for Random Option Group '%s'.\n", str[0]);
+			return false;
+		}
 	}
 
-	id = static_cast<int>(id_tmp);
-
-	if ((columns-2)%3 != 0) {
-		ShowError("itemdb_read_randomopt_group: Invalid column entries '%d'.\n", columns);
+	if (!script_get_constant(str[2], &randid_tmp) || ((randid = static_cast<int>(randid_tmp)) && !itemdb_randomopt_exists(randid))) {
+		ShowError("itemdb_read_randomopt_group: Invalid random group id '%s'!\n", str[2]);
 		return false;
 	}
 
+	id = static_cast<int>(id_tmp);
+
 	if (!(g = (struct s_random_opt_group *)uidb_get(itemdb_randomopt_group, id))) {
 		CREATE(g, struct s_random_opt_group, 1);
-		g->id = id;
 		g->total = 0;
 		g->entries = NULL;
-		uidb_put(itemdb_randomopt_group, g->id, g);
+		g->total_weight = 0;
+		uidb_put(itemdb_randomopt_group, id, g);
 	}
 
-	RECREATE(g->entries, struct s_random_opt_group_entry, g->total + rate);
+	RECREATE(g->entries, struct s_random_opt_group_entry, g->total + 1);
 
-	for (i = g->total; i < (g->total + rate); i++) {
-		int j, k;
-		memset(&g->entries[i].option, 0, sizeof(g->entries[i].option));
-		for (j = 0, k = 2; k < columns && j < MAX_ITEM_RDM_OPT; k+=3) {
-			int64 randid_tmp;
-			int randid = 0;
+	memset(&g->entries[g->total], 0, sizeof(g->entries[g->total]));
+	
+	g->entries[g->total].option.id = randid;
+	g->entries[g->total].option.value = (short)strtoul(str[3], NULL, 10);
+	g->entries[g->total].option.param = (char)strtoul(str[4], NULL, 10);
+	g->entries[g->total].weight = rate;
 
-			if (!script_get_constant(str[k], &randid_tmp) || ((randid = static_cast<int>(randid_tmp)) && !itemdb_randomopt_exists(randid))) {
-				ShowError("itemdb_read_randomopt_group: Invalid random group id '%s' in column %d!\n", str[k], k+1);
-				continue;
+	if (columns > 5) {
+		g->entries[g->total].max_value = max((short)strtoul(str[5], NULL, 10), g->entries[g->total].option.value);
+	}
+
+	g->total_weight += rate;
+	g->total++;
+	return true;
+}
+
+/**
+* Read Item Random Option Group from db file
+**/
+static bool itemdb_read_randomopt_equip(char* str[], int columns, int current) {
+	unsigned short nameid;
+	int64 group_id_tmp;
+	int group_id = -1;
+	struct item_data *item = NULL;
+	int i;
+
+	nameid = atoi(str[0]);
+
+	for (i = 1; i < columns; i++) {
+		if (ISDIGIT(str[i][0])) {
+			group_id = (int)strtoul(str[i], NULL, 10); 
+		}
+		else {
+			if (!script_get_constant(trim(str[i]), &group_id_tmp)) {
+				ShowError("itemdb_read_randopt_equip: Invalid constant '%s'!\n", str[i]);
+				return false;
 			}
-			g->entries[i].option[j].id = randid;
-			g->entries[i].option[j].value = (short)strtoul(str[k+1], NULL, 10);
-			g->entries[i].option[j].param = (char)strtoul(str[k+2], NULL, 10);
-			j++;
+
+			group_id = static_cast<int>(group_id_tmp);
+		}
+
+		if ((item = itemdb_exists(nameid)) == NULL) {
+			ShowWarning("itemdb_read_randopt_equip: Invalid item ID %hu.\n", nameid);
+			return false;
 		}
+
+		if (!itemdb_randomopt_group_exists(group_id)) {
+			ShowWarning("itemdb_read_randopt_equip: Invalid random option group ID %hu.\n", group_id);
+			return false;
+		}
+
+		item->randomopt_groupid[i - 1] = group_id;
 	}
-	g->total += rate;
+
 	return true;
 }
 
+/**
+* Sets random options to a weapon, if it has any.
+**/
+void itemdb_add_randomopt(struct item *it) {
+	struct item_data *id;
+	struct s_random_opt_group *randomopt_group;
+	int i;
+
+	if (!it || !it->nameid || (id = itemdb_exists(it->nameid)) == NULL) {
+		return;
+	}
+
+	for (i = 0; i < MAX_ITEM_RDM_OPT; i++) {
+		if (id->randomopt_groupid[i] && ((randomopt_group = itemdb_randomopt_group_exists(id->randomopt_groupid[i])) != NULL)) {
+			int rnd_value = rnd() % (randomopt_group->total_weight);
+			int total = 0;
+			int j;
+
+			for (j = 0; j < randomopt_group->total; j++) {
+				total += randomopt_group->entries[j].weight;
+
+				if (rnd_value < total) {
+					it->option[i].id = randomopt_group->entries[j].option.id;
+
+					if (randomopt_group->entries[j].max_value > 0 && randomopt_group->entries[j].max_value != randomopt_group->entries[j].option.value) {
+						int max = randomopt_group->entries[j].max_value;
+						int min = randomopt_group->entries[j].option.value;
+						
+						it->option[i].value = rnd() % (max - min + 1) + min;
+					}
+					else {
+						it->option[i].value = randomopt_group->entries[j].option.value;
+					}
+
+					it->option[i].param = randomopt_group->entries[j].option.param;
+					break;
+				}
+			}
+		}
+	}
+}
+
 /**
 * Read all item-related databases
 */
@@ -1881,7 +1966,8 @@ static void itemdb_read(void) {
 		sv_readdb(dbsubpath2, "item_delay.txt",         ',', 2, 3, -1, &itemdb_read_itemdelay, i > 0);
 		sv_readdb(dbsubpath2, "item_buyingstore.txt",   ',', 1, 1, -1, &itemdb_read_buyingstore, i > 0);
 		sv_readdb(dbsubpath2, "item_flag.txt",          ',', 2, 2, -1, &itemdb_read_flag, i > 0);
-		sv_readdb(dbsubpath2, "item_randomopt_group.txt", ',', 5, 2+5*MAX_ITEM_RDM_OPT, -1, &itemdb_read_randomopt_group, i > 0);
+		sv_readdb(dbsubpath2, "item_randomopt_group.txt", ',', 5, 6, -1, &itemdb_read_randomopt_group, i > 0);
+		sv_readdb(dbsubpath2, "item_randomopt_equips.txt",',', 2, 1 + MAX_ITEM_RDM_OPT, -1, &itemdb_read_randomopt_equip, i > 0);
 		aFree(dbsubpath1);
 		aFree(dbsubpath2);
 	}
diff --git a/src/map/itemdb.hpp b/src/map/itemdb.hpp
index 546d4ef14..af460a82c 100644
--- a/src/map/itemdb.hpp
+++ b/src/map/itemdb.hpp
@@ -865,6 +865,7 @@ struct item_data
 
 	bool isStackable();
 	int inventorySlotNeeded(int quantity);
+	unsigned int randomopt_groupid[MAX_ITEM_RDM_OPT];
 };
 
 // Struct for item random option [Secret]
@@ -882,14 +883,16 @@ enum Random_Option_Group {
 
 /// Struct for random option group entry
 struct s_random_opt_group_entry {
-	struct s_item_randomoption option[MAX_ITEM_RDM_OPT];
+	struct s_item_randomoption option;
+	short max_value;
+	int weight;
 };
 
 /// Struct for Random Option Group
 struct s_random_opt_group {
-	uint8 id;
 	struct s_random_opt_group_entry *entries;
 	uint16 total;
+	int total_weight;
 };
 
 struct item_data* itemdb_searchname(const char *name);
@@ -964,6 +967,7 @@ bool itemdb_parse_roulette_db(void);
 
 struct s_random_opt_data *itemdb_randomopt_exists(short id);
 struct s_random_opt_group *itemdb_randomopt_group_exists(int id);
+void itemdb_add_randomopt(struct item *it);
 
 void itemdb_reload(void);
 
diff --git a/src/map/mob.cpp b/src/map/mob.cpp
index f48c4d942..37e016f65 100644
--- a/src/map/mob.cpp
+++ b/src/map/mob.cpp
@@ -2119,7 +2119,7 @@ static struct item_drop* mob_setdropitem(struct s_mob_drop *mobdrop, int qty, un
 	drop->item_data.nameid = mobdrop->nameid;
 	drop->item_data.amount = qty;
 	drop->item_data.identify = itemdb_isidentified(mobdrop->nameid);
-	mob_setdropitem_option(&drop->item_data, mobdrop);
+	itemdb_add_randomopt(&drop->item_data);
 	drop->mob_id = mob_id;
 	drop->next = NULL;
 	return drop;
@@ -2931,7 +2931,7 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type)
 					intif_broadcast(message,strlen(message)+1,BC_DEFAULT);
 				}
 
-				mob_setdropitem_option(&item, &mdrop[i]);
+				itemdb_add_randomopt(&item);
 
 				if((temp = pc_additem(mvp_sd,&item,1,LOG_TYPE_PICKDROP_PLAYER)) != 0) {
 					clif_additem(mvp_sd,0,0,temp);
diff --git a/src/map/pc.cpp b/src/map/pc.cpp
index 8f609f505..ce4eb55e3 100755
--- a/src/map/pc.cpp
+++ b/src/map/pc.cpp
@@ -5632,7 +5632,7 @@ bool pc_steal_item(struct map_session_data *sd,struct block_list *bl, uint16 ski
 	tmp_item.nameid = itemid;
 	tmp_item.amount = 1;
 	tmp_item.identify = itemdb_isidentified(itemid);
-	mob_setdropitem_option(&tmp_item, &md->db->dropitem[i]);
+	itemdb_add_randomopt(&tmp_item);
 	flag = pc_additem(sd,&tmp_item,1,LOG_TYPE_PICKDROP_PLAYER);
 
 	//TODO: Should we disable stealing when the item you stole couldn't be added to your inventory? Perhaps players will figure out a way to exploit this behaviour otherwise?
diff --git a/src/map/script.cpp b/src/map/script.cpp
index 5af99c5a5..f99bff45e 100644
--- a/src/map/script.cpp
+++ b/src/map/script.cpp
@@ -7438,6 +7438,8 @@ BUILDIN_FUNC(getitem)
 		// if not pet egg
 		if (!pet_create_egg(sd, nameid))
 		{
+			itemdb_add_randomopt(&it);
+
 			if ((flag = pc_additem(sd, &it, get_count, LOG_TYPE_SCRIPT)))
 			{
 				clif_additem(sd, 0, 0, flag);

Of course, this system isn't compatible with the default one on rAthena, so you'll have to modify your current random option weapons if you have any. Goodluck!

 

option.diff

Edited by Tokei
Link to comment
Share on other sites

  • 1

  • Group:  Members
  • Topic Count:  16
  • Topics Per Day:  0.00
  • Content Count:  658
  • Reputation:   663
  • Joined:  11/12/12
  • Last Seen:  

@mawjustin Hmmm, you'd get this error because the group IDs aren't defined. That... shouldn't be the case, though. The constant for your group ID, "7934", does seem to exist. Can you show me both of your itemdb_read_randomopt_group and itemdb_read_randomopt_equip functions, in itemdb.cpp? Also please show me one item you made in item_randoopt_equips.txt with one of the group from item_randoption_group.txt that is used. The error is somewhat vague.

Link to comment
Share on other sites

  • 1

  • Group:  Members
  • Topic Count:  16
  • Topics Per Day:  0.00
  • Content Count:  658
  • Reputation:   663
  • Joined:  11/12/12
  • Last Seen:  

Hmm, your base is different than rAthena (you do not have the int64 script update applied). There's a couple of mistakes with how you assigned the integers, replace your two functions with this instead:

/**
* Read Item Random Option Group from db file
* @author [Cydh]
**/
static bool itemdb_read_randomopt_group(char* str[], int columns, int current) {
	int id = 0;
	int randid = 0;
	unsigned short rate = (unsigned short)strtoul(str[1], NULL, 10);
	struct s_random_opt_group *g = NULL;

	if (!script_get_constant(str[0], &id)) {
		// autogenerate constant, it gets annoying to define it everytime
		script_set_constant(trim(str[0]), add_str(trim(str[0])), false, false);

		if (!script_get_constant(trim(str[0]), &id)) {	// Should never happen?
			ShowError("itemdb_read_randomopt_group: Invalid ID for Random Option Group '%s'.\n", str[0]);
			return false;
		}
	}

	if (!script_get_constant(str[2], &randid) || !itemdb_randomopt_exists(randid)) {
		ShowError("itemdb_read_randomopt_group: Invalid random group id '%s'!\n", str[2]);
		return false;
	}

	if (!(g = (struct s_random_opt_group *)uidb_get(itemdb_randomopt_group, id))) {
		CREATE(g, struct s_random_opt_group, 1);
		g->total = 0;
		g->entries = NULL;
		g->total_weight = 0;
		uidb_put(itemdb_randomopt_group, id, g);
	}

	RECREATE(g->entries, struct s_random_opt_group_entry, g->total + 1);

	memset(&g->entries[g->total], 0, sizeof(g->entries[g->total]));

	g->entries[g->total].option.id = randid;
	g->entries[g->total].option.value = (short)strtoul(str[3], NULL, 10);
	g->entries[g->total].option.param = (char)strtoul(str[4], NULL, 10);
	g->entries[g->total].weight = rate;
	if (columns > 5) {
		g->entries[g->total].max_value = max((short)strtoul(str[5], NULL, 10), g->entries[g->total].option.value);
	}

	g->total_weight += rate;
	g->total++;
	return true;
}

/**
* Read Item Random Option Group from db file
**/
static bool itemdb_read_randomopt_equip(char* str[], int columns, int current) {
	unsigned short nameid;
	int group_id = -1;
	struct item_data *item = NULL;
	int i;

	nameid = atoi(str[0]);

	for (i = 1; i < columns; i++) {
		if (ISDIGIT(str[i][0])) {
			group_id = (int)strtoul(str[i], NULL, 10);
		}
		else {
			if (!script_get_constant(trim(str[i]), &group_id)) {
				ShowError("itemdb_read_randopt_equip: Invalid constant '%s'!\n", str[i]);
				return false;
			}
		}

		if ((item = itemdb_exists(nameid)) == NULL) {
			ShowWarning("itemdb_read_randopt_equip: Invalid item ID %hu.\n", nameid);
			return false;
		}

		if (!itemdb_randomopt_group_exists(group_id)) {
			ShowWarning("itemdb_read_randopt_equip: Invalid random option group ID %hu.\n", group_id);
			return false;
		}

		item->randomopt_groupid[i - 1] = group_id;
	}

	return true;
}

 

Link to comment
Share on other sites

  • 1

  • Group:  Members
  • Topic Count:  0
  • Topics Per Day:  0
  • Content Count:  3
  • Reputation:   0
  • Joined:  05/10/18
  • Last Seen:  

@Tokei

I applied it on my server I don't get any error. When the monster drops the items it doesn't have any options.
does this diff still work?
sorry for the bad english.

Edited by LaikaAboss
Link to comment
Share on other sites

  • 1

  • Group:  Members
  • Topic Count:  15
  • Topics Per Day:  0.01
  • Content Count:  21
  • Reputation:   0
  • Joined:  06/25/20
  • Last Seen:  

Hello there!

  I applied this patch and everything seems to work perfectly fine, however, when I want to make a random group to apply different values, it would just apply the first one of each group (RDMOPT_DAMAGE_PROPERTY_GROUND_USER in this case), for example:

RDMOPTG_Crimson_Weapon_3,1,RDMOPT_DAMAGE_PROPERTY_GROUND_USER,5,0,10
RDMOPTG_Crimson_Weapon_3,1,RDMOPT_DAMAGE_PROPERTY_NOTHING_TARGET,5,0,10
RDMOPTG_Crimson_Weapon_3,1,RDMOPT_DAMAGE_PROPERTY_WATER_TARGET,5,0,10
RDMOPTG_Crimson_Weapon_3,1,RDMOPT_DAMAGE_PROPERTY_FIRE_USER,5,0,10

For this specific group, it is intended that one of these four values would apply randomly to an specific weapon, but, after applying the patch, the first in these lines will only apply. The other three effects are not being taken into consideration when dropping the weapon.

Does someone have any idea what might be causing this or any work-around?

Edited by Vyserion
Link to comment
Share on other sites

  • 1

  • Group:  Members
  • Topic Count:  76
  • Topics Per Day:  0.02
  • Content Count:  461
  • Reputation:   61
  • Joined:  08/28/12
  • Last Seen:  

First of all, thanks for sharing.
But I have a question about this, would it be possible to add the function that it has a chance to appear?
Like: 

// Item_ID,Chance,RandomOption_GroupId1{,Chance,RandomOption_GroupId2,Chance,RandomOption_GroupId3,Chance,RandomOption_GroupId4,Chance,RandomOption_GroupId5}

So that every random option has its own chance.
Here an example with a Knife[4]:

//100 = 1% Chance
1202,5000,RDMOPTG_Crimson_Weapon_1,3000,RDMOPTG_Crimson_Weapon_2,2000,RDMOPTG_Crimson_Weapon_3,500,RDMOPTG_Crimson_Weapon_4,100,RDMOPTG_Crimson_Weapon_5

So there is a 50% chance that the Knife gets 1 bonus, 30% chance the 2nd bonus and so on.
Then the options would not be fixed so that there are always directly all 3 or 4 bonuses, but from 1 to 5 (if set).

Hope it is obvious what I mean. xD

Link to comment
Share on other sites

  • 0

  • Group:  Members
  • Topic Count:  47
  • Topics Per Day:  0.01
  • Content Count:  121
  • Reputation:   6
  • Joined:  09/26/14
  • Last Seen:  

On 2/26/2020 at 12:41 PM, Tokei said:

....

Apologies for the late reply sir, thank you for this, this works on renewal as well, right? I'm currently testing it right now. 

 

@Tokei im having this error while using .diff
image.png.a938f8b7306f521b35c81808ee5a70d0.png
 

@Tokei I did the diff manually, but I'm having these errors.image.thumb.png.b6ddb6cb636b1d414f5a04ea03f34532.png
 

Link to comment
Share on other sites

  • 0

  • Group:  Members
  • Topic Count:  47
  • Topics Per Day:  0.01
  • Content Count:  121
  • Reputation:   6
  • Joined:  09/26/14
  • Last Seen:  

Link to comment
Share on other sites

  • 0

  • Group:  Members
  • Topic Count:  16
  • Topics Per Day:  0.00
  • Content Count:  658
  • Reputation:   663
  • Joined:  11/12/12
  • Last Seen:  

13 hours ago, Vyserion said:

Hello there!

  I applied this patch and everything seems to work perfectly fine, however, when I want to make a random group to apply different values, it would just apply the first one of each group (RDMOPT_DAMAGE_PROPERTY_GROUND_USER in this case), for example:


RDMOPTG_Crimson_Weapon_3,1,RDMOPT_DAMAGE_PROPERTY_GROUND_USER,5,0,10
RDMOPTG_Crimson_Weapon_3,1,RDMOPT_DAMAGE_PROPERTY_NOTHING_TARGET,5,0,10
RDMOPTG_Crimson_Weapon_3,1,RDMOPT_DAMAGE_PROPERTY_WATER_TARGET,5,0,10
RDMOPTG_Crimson_Weapon_3,1,RDMOPT_DAMAGE_PROPERTY_FIRE_USER,5,0,10

For this specific group, it is intended that one of these four values would apply randomly to an specific weapon, but, after applying the patch, the first in these lines will only apply. The other three effects are not being taken into consideration when dropping the weapon.

Does someone have any idea what might be causing this or any work-around?

Well the group is being chosen there:

int rnd_value = rnd() % (randomopt_group->total_weight);

Using a debugger would show you where the issue is. Otherwise, you can add debug lines, I suppose:

			int rnd_value = rnd() % (randomopt_group->total_weight);
			int total = 0;
			int j;
			ShowDebug("itemdb_add_randomopt: total_weight '%d', total '%d', rnd_value '%d'\n", randomopt_group->total_weight, randomopt_group->total, rnd_value);

 

If the total_weight isn't 4, then it wasn't read properly and something's missing near

	g->total_weight += rate;
	g->total++;

 

Link to comment
Share on other sites

  • 0

  • Group:  Members
  • Topic Count:  0
  • Topics Per Day:  0
  • Content Count:  4
  • Reputation:   1
  • Joined:  09/04/18
  • Last Seen:  

On 9/9/2020 at 1:33 PM, WhiteEagle said:

First of all, thanks for sharing.
But I have a question about this, would it be possible to add the function that it has a chance to appear?
Like: 


// Item_ID,Chance,RandomOption_GroupId1{,Chance,RandomOption_GroupId2,Chance,RandomOption_GroupId3,Chance,RandomOption_GroupId4,Chance,RandomOption_GroupId5}

So that every random option has its own chance.
Here an example with a Knife[4]:

//100 = 1% Chance
1202,5000,RDMOPTG_Crimson_Weapon_1,3000,RDMOPTG_Crimson_Weapon_2,2000,RDMOPTG_Crimson_Weapon_3,500,RDMOPTG_Crimson_Weapon_4,100,RDMOPTG_Crimson_Weapon_5

So there is a 50% chance that the Knife gets 1 bonus, 30% chance the 2nd bonus and so on.
Then the options would not be fixed so that there are always directly all 3 or 4 bonuses, but from 1 to 5 (if set).

Hope it is obvious what I mean. xD

I needed a quick change to make something like this work.... It might help you:
You just need to replace the function void itemdb_add_randomopt(struct item *it) in itemdb.cpp and recompile. It makes 1random option 100%, 2nd 80%, 3rd 60% and so on...

 

void itemdb_add_randomopt(struct item *it)
{
	struct item_data *id;
	struct s_random_opt_group *randomopt_group;
	int i;

	if (!it || !it->nameid || (id = itemdb_exists(it->nameid)) == NULL)
	{
		return;
	}

	for (i = 0; i < MAX_ITEM_RDM_OPT; i++)
	{
		if (id->randomopt_groupid[i] && ((randomopt_group = itemdb_randomopt_group_exists(id->randomopt_groupid[i])) != NULL))
		{

			int rndOpt = rnd() % (MAX_ITEM_RDM_OPT);

			if (i > 0)
			{
				if ((i > 3 && rndOpt < 4) || (i > 2 && rndOpt < 3) || (i > 1 && rndOpt < 2))
					break;
				if (rndOpt < 1)
					break;
			}
			int rnd_value = rnd() % (randomopt_group->total_weight);
			int total = 0;
			int j;

			for (j = 0; j < randomopt_group->total; j++)
			{
				total += randomopt_group->entries[j].weight;

				if (rnd_value < total)
				{
					it->option[i].id = randomopt_group->entries[j].option.id;

					if (randomopt_group->entries[j].max_value > 0 && randomopt_group->entries[j].max_value != randomopt_group->entries[j].option.value)
					{
						int max = randomopt_group->entries[j].max_value;
						int min = randomopt_group->entries[j].option.value;

						it->option[i].value = rnd() % (max - min + 1) + min;
					}
					else
					{
						it->option[i].value = randomopt_group->entries[j].option.value;
					}

					it->option[i].param = randomopt_group->entries[j].option.param;
					break;
				}
			}
		}
	}
}

In item_randomopt_equips.txt you cannot duplicate any RandomOption_GroupId in the same item. You can use something like this:

1202,RDMOPT_Weapon_Tier1_Slot1,RDMOPT_Weapon_Tier1_Slot2,RDMOPT_Weapon_Tier1_Slot3,RDMOPT_Weapon_Tier1_Slot4,RDMOPT_Weapon_TierSpecial_Slot5

If you want a item to have less than 5 options, you just need to remove the option from this file.

Edited by -to-
typo
Link to comment
Share on other sites

  • 0

  • Group:  Members
  • Topic Count:  47
  • Topics Per Day:  0.01
  • Content Count:  121
  • Reputation:   6
  • Joined:  09/26/14
  • Last Seen:  

After more than a year I managed to make this work. Thank you everyone. @Tokei @-to-

Link to comment
Share on other sites

  • 0

  • Group:  Members
  • Topic Count:  0
  • Topics Per Day:  0
  • Content Count:  1
  • Reputation:   0
  • Joined:  12/03/22
  • Last Seen:  

can I download a version that random option is working? I'm very noob with stuff like this and I cracked my brain just to make the offline server run, I just want a offline server to play by myself, thansk!

 

@Tokei @-to- @mawjustin, sorry for "@" u guys

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Answer this question...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...