Jump to content

  •  

Bug Tracker Migration

June 3rd
Good news everyone! The staff has decided that it is time to slowly kill off this Bug Tracker. We will begin the process of slowly migrating from this Bug Tracker over to our Github Issues which can be found here: https://github.com/HerculesWS/Hercules/issues

Over the next couple of days, I will be closing off any opportunity to create new reports. However, I still will keep the opportunity to reply to existing Bug Reports. Doing this will allow us to slowly fix any bug reports we have listed here so that we can easily migrate over to our Issue Tracker.

Update - June 7th 2015: Creating new bug posts has been disabled. Please use our https://github.com/HerculesWS/Hercules/issues tracker to post bugs. Users are still able to reply to existing bug posts.

- Administration

Issue Information

  • #008427

  • 0 - None Assigned

  • Confirmed

Issue Confirmations

  • Yes (1)No (0)
Photo

Pet_db/Pet_db2

Posted by Garr on 06 November 2014 - 08:41 PM

Well, I always thought that like in mob_db/mob_db2 and all such files, entries from pet_db2 would overwrite entries on same monsters within pet_db, but it seems that's not happening. As far as I understood it just copies in all entries from pet_db and pet_db2 disregarding any similar mob IDs, and then the first entry (pet_db one) takes effect over pet_db2 one when it searches for pet index. Is there a chance we'll get same behaviour as the other db/db2 files?

I was able to implement that on my own, but I'm not sure if my way is at all efficient.

Just in case, my curent read_petdb:
int read_petdb()
{
	char* filename[] = {"pet_db.txt","pet_db2.txt"};
	FILE *fp;
	int nameid,i,j,k,l;

	// Remove any previous scripts in case reloaddb was invoked.
	for( j = 0; j < MAX_PET_DB; j++ )
	{
		if( pet->db[j].pet_script )
		{
			script->free_code(pet->db[j].pet_script);
			pet->db[j].pet_script = NULL;
		}
		if( pet->db[j].equip_script )
		{
			script->free_code(pet->db[j].equip_script);
			pet->db[j].pet_script = NULL;
		}
	}

	// clear database
	memset(pet->db,0,sizeof(pet->db));

	j = 0; // entry counter
	for( i = 0; i < ARRAYLENGTH(filename); i++ ) {
		char line[1024];
		int lines, entries;

		sprintf(line, "%s/%s", map->db_path, filename[i]);
		fp=fopen(line,"r");
		if( fp == NULL ) {
			if( i == 0 )
				ShowError("can't read %s\n",line);
			continue;
		}

		lines = entries = 0;
		while( fgets(line, sizeof(line), fp) && j < MAX_PET_DB ) {
			char *str[22], *p;
			lines++;

			if(line[0] == '/' && line[1] == '/')
				continue;
			memset(str, 0, sizeof(str));
			p = line;
			while( ISSPACE(*p) )
				++p;
			if( *p == '\0' )
				continue; // empty line
			for( k = 0; k < 20; ++k )
			{
				str[k] = p;
				p = strchr(p,',');
				if( p == NULL )
					break; // comma not found
				*p = '\0';
				++p;
			}

			if( p == NULL )
			{
				ShowError("read_petdb: Insufficient columns in line %d, skipping.\n", lines);
				continue;
			}

			// Pet Script
			if( *p != '{' )
			{
				ShowError("read_petdb: Invalid format (Pet Script column) in line %d, skipping.\n", lines);
				continue;
			}

			str[20] = p;
			p = strstr(p+1,"},");
			if( p == NULL )
			{
				ShowError("read_petdb: Invalid format (Pet Script column) in line %d, skipping.\n", lines);
				continue;
			}
			p[1] = '\0';
			p += 2;

			// Equip Script
			if( *p != '{' )
			{
				ShowError("read_petdb: Invalid format (Equip Script column) in line %d, skipping.\n", lines);
				continue;
			}
			str[21] = p;

			if( (nameid = atoi(str[0])) <= 0 )
				continue;

			if( !mob->db_checkid(nameid) )
			{
				ShowWarning("pet_db reading: Invalid mob-class %d, pet not read.\n", nameid);
				continue;
			}
			
			k = -1;
			ARR_FIND( 0, j, l, pet->db[l].class_ == nameid);
			if ( l < j ) {
				k = j;
				j = l;
				if( pet->db[j].pet_script ) {
					script->free_code(pet->db[j].pet_script);
					pet->db[j].pet_script = NULL;
				}
				if( pet->db[j].equip_script ) {
					script->free_code(pet->db[j].equip_script);
					pet->db[j].pet_script = NULL;
				}
				memset(&pet->db[j],0,sizeof(pet->db[j]));
			}
			
			pet->db[j].class_ = nameid;
			safestrncpy(pet->db[j].name,str[1],NAME_LENGTH);
			safestrncpy(pet->db[j].jname,str[2],NAME_LENGTH);
			pet->db[j].itemID=atoi(str[3]);
			pet->db[j].EggID=atoi(str[4]);
			pet->db[j].AcceID=atoi(str[5]);
			pet->db[j].FoodID=atoi(str[6]);
			pet->db[j].fullness=atoi(str[7]);
			pet->db[j].hungry_delay=atoi(str[8])*1000;
			pet->db[j].r_hungry=atoi(str[9]);
			if( pet->db[j].r_hungry <= 0 )
				pet->db[j].r_hungry=1;
			pet->db[j].r_full=atoi(str[10]);
			pet->db[j].intimate=atoi(str[11]);
			pet->db[j].die=atoi(str[12]);
			pet->db[j].capture=atoi(str[13]);
			pet->db[j].speed=atoi(str[14]);
			pet->db[j].s_perfor=(char)atoi(str[15]);
			pet->db[j].talk_convert_class=atoi(str[16]);
			pet->db[j].attack_rate=atoi(str[17]);
			pet->db[j].defence_attack_rate=atoi(str[18]);
			pet->db[j].change_target_rate=atoi(str[19]);
			pet->db[j].pet_script = NULL;
			pet->db[j].equip_script = NULL;

			if( *str[20] )
				pet->db[j].pet_script = script->parse(str[20], filename[i], lines, 0, NULL);
			if( *str[21] )
				pet->db[j].equip_script = script->parse(str[21], filename[i], lines, 0, NULL);
			
			if (k != -1) j = k; else j++;
			
			entries++;
		}

		if( j >= MAX_PET_DB )
			ShowWarning("read_petdb: Reached max number of pets [%d]. Remaining pets were not read.\n ", MAX_PET_DB);
		fclose(fp);
		ShowStatus("Done reading '"CL_WHITE"%d"CL_RESET"' pets in '"CL_WHITE"%s"CL_RESET"'.\n", entries, filename[i]);
	}
	
	return 0;
}

Edited by Garr, 06 November 2014 - 08:43 PM.


pet_db2.txt is for custom pets (not the pet_db.txt to be overwritten as I think)
would have to wait for haru/Ind to know what is the intended behaviour.

moved issue from Database

as the code says it will override the entry from 'pet_db.txt'...

this code will find the existing mob id..then the next will the overwriting of data entries..
ARR_FIND( 0, j, l, pet->db[l].class_ == nameid);
if ( l < j ) { // found existing id
    k = j; // temp variable
    j = l; // set current entry to the found pet entry

:meow:

I don't think it is intended to create two different pets with the same mob_id (especially if you look at the function search_petDB_index, it doesn't seem to expect multiple entries with the same mob id), so it would be better to overwrite entries based on the same mob, rather than creating new ones.

I think we need a more efficient way to do that, than how you suggested, though. Looping through the entire mob_db every time a new entry is inserted, doesn't seem too good.

changed status to: Confirmed

@malufett Yes, I know, as I said that's MY modified version to check for previously used same mob id. But as I said I don't think that code is in any way efficient, that's why I asked for help here. Unmodified looks currently like this:
int read_petdb()
{
	char* filename[] = {"pet_db.txt","pet_db2.txt"};
	FILE *fp;
	int nameid,i,j,k;

	// Remove any previous scripts in case reloaddb was invoked.
	for( j = 0; j < MAX_PET_DB; j++ )
	{
		if( pet->db[j].pet_script )
		{
			script->free_code(pet->db[j].pet_script);
			pet->db[j].pet_script = NULL;
		}
		if( pet->db[j].equip_script )
		{
			script->free_code(pet->db[j].equip_script);
			pet->db[j].pet_script = NULL;
		}
	}

	// clear database
	memset(pet->db,0,sizeof(pet->db));

	j = 0; // entry counter
	for( i = 0; i < ARRAYLENGTH(filename); i++ ) {
		char line[1024];
		int lines, entries;

		sprintf(line, "%s/%s", map->db_path, filename[i]);
		fp=fopen(line,"r");
		if( fp == NULL ) {
			if( i == 0 )
				ShowError("can't read %s\n",line);
			continue;
		}

		lines = entries = 0;
		while( fgets(line, sizeof(line), fp) && j < MAX_PET_DB ) {
			char *str[22], *p;
			lines++;

			if(line[0] == '/' && line[1] == '/')
				continue;
			memset(str, 0, sizeof(str));
			p = line;
			while( ISSPACE(*p) )
				++p;
			if( *p == '\0' )
				continue; // empty line
			for( k = 0; k < 20; ++k )
			{
				str[k] = p;
				p = strchr(p,',');
				if( p == NULL )
					break; // comma not found
				*p = '\0';
				++p;
			}

			if( p == NULL )
			{
				ShowError("read_petdb: Insufficient columns in line %d, skipping.\n", lines);
				continue;
			}

			// Pet Script
			if( *p != '{' )
			{
				ShowError("read_petdb: Invalid format (Pet Script column) in line %d, skipping.\n", lines);
				continue;
			}

			str[20] = p;
			p = strstr(p+1,"},");
			if( p == NULL )
			{
				ShowError("read_petdb: Invalid format (Pet Script column) in line %d, skipping.\n", lines);
				continue;
			}
			p[1] = '\0';
			p += 2;

			// Equip Script
			if( *p != '{' )
			{
				ShowError("read_petdb: Invalid format (Equip Script column) in line %d, skipping.\n", lines);
				continue;
			}
			str[21] = p;

			if( (nameid = atoi(str[0])) <= 0 )
				continue;

			if( !mob->db_checkid(nameid) )
			{
				ShowWarning("pet_db reading: Invalid mob-class %d, pet not read.\n", nameid);
				continue;
			}

			pet->db[j].class_ = nameid;
			safestrncpy(pet->db[j].name,str[1],NAME_LENGTH);
			safestrncpy(pet->db[j].jname,str[2],NAME_LENGTH);
			pet->db[j].itemID=atoi(str[3]);
			pet->db[j].EggID=atoi(str[4]);
			pet->db[j].AcceID=atoi(str[5]);
			pet->db[j].FoodID=atoi(str[6]);
			pet->db[j].fullness=atoi(str[7]);
			pet->db[j].hungry_delay=atoi(str[8])*1000;
			pet->db[j].r_hungry=atoi(str[9]);
			if( pet->db[j].r_hungry <= 0 )
				pet->db[j].r_hungry=1;
			pet->db[j].r_full=atoi(str[10]);
			pet->db[j].intimate=atoi(str[11]);
			pet->db[j].die=atoi(str[12]);
			pet->db[j].capture=atoi(str[13]);
			pet->db[j].speed=atoi(str[14]);
			pet->db[j].s_perfor=(char)atoi(str[15]);
			pet->db[j].talk_convert_class=atoi(str[16]);
			pet->db[j].attack_rate=atoi(str[17]);
			pet->db[j].defence_attack_rate=atoi(str[18]);
			pet->db[j].change_target_rate=atoi(str[19]);
			pet->db[j].pet_script = NULL;
			pet->db[j].equip_script = NULL;

			if( *str[20] )
				pet->db[j].pet_script = script->parse(str[20], filename[i], lines, 0, NULL);
			if( *str[21] )
				pet->db[j].equip_script = script->parse(str[21], filename[i], lines, 0, NULL);

			j++;
			entries++;
		}

		if( j >= MAX_PET_DB )
			ShowWarning("read_petdb: Reached max number of pets [%d]. Remaining pets were not read.\n ", MAX_PET_DB);
		fclose(fp);
		ShowStatus("Done reading '"CL_WHITE"%d"CL_RESET"' pets in '"CL_WHITE"%s"CL_RESET"'.\n", entries, filename[i]);
	}
	return 0;
}



@Haru Indeed, as it can create tonns of confusion. And I know it's not efficient at all, just nothing else came to mind for a quick fix :(

Edited by Garr, 07 November 2014 - 06:51 AM.


Still not fixed?

I don't know how to search commit on github.

This will get fixed when we convert the Pet DB to libconfig.