Go Back   EQEmulator Home > EQEmulator Forums > Development > Development::Server Code Submissions

Closed Thread
 
Thread Tools Display Modes
  #1  
Old 09-13-2008, 01:55 AM
Rocker8956
Hill Giant
 
Join Date: Sep 2007
Posts: 117
Lightbulb Zone instancing

(Sorry, I would have put this in the old thread but I did not want to confuse anyone on how the code worked)

This code basically enables zone instancing

Select a zone you want to instance
Set that zone's insttype to 1
Select a character you want to access that zone
Set that character's
instZflagNum to a number greater than 1000
instZOrgID to the zoneID of the zone you picked
rinse and repeat with second character changing the instZflagNum (if you want them to go to a different zone)

Zone characters into the zone you picked.

K, here is my example
I want to instance blackburrow (has a zoneid of 17
I set blackburrow's insttype to 1 in the zone table
I want my toon MonkGod to access an instance of blackburrow
I set MonkGod's
instZflagNum to 1001
instZOrgID to 17


I then set the instZflagnum and insZordID on Aries, my other character.
changing the instZflagNum to 1002
Setting instZOrgID to 17


All that would be required to get this fully functional is a quest command that sets a character’s InstZflagNum and instZOrgID. I have a method for doing this but don’t know where to put the code. Anyone willing to help write it please let me know.

Anyhow here are the required changes. This was done against 1129 using PEQ database.
Please let me know what bugs you notice.

Required SQL
Code:
ALTER TABLE `zone` ADD column `insttype` tinyint (1) zerofill unsigned NOT NULL default '0';
ALTER table character_ ADD column `instZflagNum` int(10) unsigned NOT NULL default '0';
ALTER table character_ ADD column `instZOrgID` int(11) NOT NULL default '0';
INSERT INTO variables VALUES ('curInstFlagNum', 1000, 'Determines what instance flag will be handed out next', '2008-09-05 04:46:47');
INSERT INTO variables VALUES ('dfltInstZflag',1000, 'Used to determine if a zone is instanced, must be 1000 or greater', '2008-09-05 04:46:47');
World\Zoneserver.cpp
Line 498 insert
Code:
ztz->requested_zone_id = database.GetInstZoneID(ztz->requested_zone_id, ztz->name);
Line 508-509 insert
Code:
int server_id;
ztz->requested_zone_id = database.GetInstZoneID(ztz->requested_zone_id, ztz->name);
if ((server_id = zoneserver_list.TriggerBootup(ztz->requested_zone_id)))
Line 533 insert
Code:
zlog(WORLD__ZONE,"Processing ZTZ for ingress to zone for client %s\n", ztz->name);
ztz->current_zone_id = database.GetInstZoneID(ztz->current_zone_id, ztz->name); //Rocker8956 possible fix for wrong zone shutdown
ZoneServer *egress_server = zoneserver_list.FindByZoneID(ztz->current_zone_id);

World\Client.cpp
Line 644 insert
Code:
zoneID = database.GetInstZoneID(zoneID, GetCharName());
Zone\zoning.cpp
Line 122
Code:
//Checks if the zone can be instanced, character has a instance flag, and 
//that the character is not zoning into an instance that is already loaded
if(database.GetInstType(target_zone_id) == 1){
	int32 characterID = database.GetCharacterID(zc->char_name);
	int32 instFlagNum = database.GetCharInstFlagNum(characterID);
	if(instFlagNum >= database.GetDfltInstZFlag())
	{
			int32 charInstZOrgID = database.GetCharInstZOrgID(characterID);
			// If instance flag matches then...
			if(charInstZOrgID == target_zone_id)
			{
				//If instance zone is not in database then it is copied to database
				if(!database.InstZoneLoaded(instFlagNum)) {
					database.LoadInstZone(target_zone_id, instFlagNum);
				}
				target_zone_id = instFlagNum;
			}
	}
}
Common\database.h
Line 201 insert
Code:
int32	GetCharInstFlagNum(int32 charID);
int32	GetCharInstZOrgID(int32 charID);
int32   GetInstZoneID(int32 zoneID, const char* charName);
void	DeleteInstZone(int32 instZoneID);
int32   GetDfltInstZFlag();
Common\database.cpp
Line 1173
Code:
const char* Database::GetZoneName(int32 zoneID, bool ErrorUnknown) {
	if (zonename_array == 0) {
		if (ErrorUnknown)
			return "UNKNOWN";
		else
			return 0;
	}
	if (zoneID > GetDfltInstZFlag())
	{
		char errbuf[MYSQL_ERRMSG_SIZE];
		char *query = 0;
		MYSQL_RES *result;
		MYSQL_ROW row;
		if (RunQuery(query, MakeAnyLenString(&query, "SELECT instZOrgID FROM character_ WHERE instZflagNum=%i", zoneID), errbuf, &result)) {
			safe_delete_array(query);
			if (mysql_num_rows(result) > 0) {
				row = mysql_fetch_row(result);
				int8 tmp = atoi(row[0]);
				mysql_free_result(result);
				return zonename_array[tmp];
			}
			mysql_free_result(result);
		}
		else 
		{
			cerr << "Error in instZOrgID query in database.cpp GetZoneName'" << query << "' " << errbuf << endl;
			safe_delete_array(query);
		}
	}
	else if (zoneID <= max_zonename) {
  		if (zonename_array[zoneID])
  			return zonename_array[zoneID];
  		else {
  			if (ErrorUnknown)
  				return "UNKNOWN";
  			else
  				return 0;
  		}
  	}
	else {
		if (ErrorUnknown)
			return "UNKNOWN";
		else
			return 0;
	}
}
End of Common\database.cpp insert
Code:
int32 Database::GetDfltInstZFlag(){
char errbuf[MYSQL_ERRMSG_SIZE];
   	 char *query = 0;
   	 MYSQL_RES *result;
   	 MYSQL_ROW row;
	if (RunQuery(query, MakeAnyLenString(&query, "SELECT value FROM variables WHERE varname = 'dfltInstZflag'"), errbuf, &result))
	{
		safe_delete_array(query);
		if (mysql_num_rows(result) == 1) {
			row = mysql_fetch_row(result);
			int32 tmp = atoi(row[0]);
			mysql_free_result(result);
			return tmp;
		}
		mysql_free_result(result);
	}

	else {
		cerr << "Error in GetDfltInstZFlag query '" << query << "' " << errbuf << endl;
		safe_delete_array(query);
	}
	return 0;
}
int32 Database::GetCharInstFlagNum(int32 charID){
	char errbuf[MYSQL_ERRMSG_SIZE];
    char *query = 0;
    MYSQL_RES *result;
    MYSQL_ROW row;
	
	if (RunQuery(query, MakeAnyLenString(&query, "SELECT instZflagNum FROM character_ WHERE id=%i", charID), errbuf, &result))
	{
		safe_delete_array(query);
		if (mysql_num_rows(result) == 1) {
			row = mysql_fetch_row(result);
			int tmp = atoi(row[0]);
			mysql_free_result(result);
			return tmp;
		}
		mysql_free_result(result);
	}
	else {
		cerr << "Error in GetCharInstFlag Numquery '" << query << "' " << errbuf << endl;
		safe_delete_array(query);
	}
	return 0;
}

int32 Database::GetCharInstZOrgID(int32 charID){
	char errbuf[MYSQL_ERRMSG_SIZE];
    char *query = 0;
    MYSQL_RES *result;
    MYSQL_ROW row;
	if (RunQuery(query, MakeAnyLenString(&query, "SELECT instZOrgID FROM character_ WHERE id=%i", charID), errbuf, &result))
	{
		safe_delete_array(query);
		if (mysql_num_rows(result) == 1) {
			row = mysql_fetch_row(result);
			int32 tmp = atoi(row[0]);
			mysql_free_result(result);
			return tmp;

		}
		mysql_free_result(result);
	}
	else {
		cerr << "Error in GetInstType query '" << query << "' " << errbuf << endl;
		safe_delete_array(query);
	}
	return 0;
}
int32 Database::GetInstZoneID(int32 zoneID, const char* charName) {
	if (zoneID == 0)
		return 0;
	int32 charID = GetCharacterID(charName);
	if (zoneID == GetCharInstZOrgID(charID))
	{
		zoneID = GetCharInstFlagNum(charID);
		return zoneID;
	}
	else
		return (zoneID);
}

void Database::DeleteInstZone(int32 instZoneID)
{
	char errbuf[MYSQL_ERRMSG_SIZE];
    char *query = 0;
    MYSQL_RES *result;
	if (RunQuery(query, MakeAnyLenString(&query, "DELETE FROM zone WHERE zoneidnumber=%i", instZoneID), errbuf, &result))
	{
		safe_delete_array(query);
		mysql_free_result(result);
	}
	else {
		cerr << "Error in DeleteInstZone query '" << query << "' " << errbuf << endl;
		safe_delete_array(query);
	}
}
Zone\zonedb.cpp
Append to the end
Code:
int32 ZoneDatabase::GetInstType(int32 zoneid) {
    char errbuf[MYSQL_ERRMSG_SIZE];
    char *query = 0;
    MYSQL_RES *result;
    MYSQL_ROW row;
	
	if (RunQuery(query, MakeAnyLenString(&query, "SELECT insttype FROM zone WHERE zoneidnumber=%i", zoneid), errbuf, &result))
	{
		safe_delete_array(query);
		if (mysql_num_rows(result) == 1) {
			row = mysql_fetch_row(result);
			int8 tmp = atoi(row[0]);
			mysql_free_result(result);
			return tmp;

		}
		mysql_free_result(result);
	}

	else {
		cerr << "Error in GetInstType query '" << query << "' " << errbuf << endl;
		safe_delete_array(query);
	}
	return 0;
}
bool ZoneDatabase::InstZoneLoaded(int32 charInstFlagNum){
    char errbuf[MYSQL_ERRMSG_SIZE];
    char *query = 0;
    MYSQL_RES *result;
    MYSQL_ROW row;
	
	if (RunQuery(query, MakeAnyLenString(&query, "SELECT zoneidnumber FROM zone WHERE zoneidnumber=%i", charInstFlagNum), errbuf, &result))
	{
		safe_delete_array(query);
		if (mysql_num_rows(result) == 1) {
			return true;
		}
		else if (mysql_num_rows(result) == 0) {
			return false;
		}
		mysql_free_result(result);
	}

	else {
		cerr << "Error in isInstZoneLoad query '" << query << "' " << errbuf << endl;
		safe_delete_array(query);
	}
	return 0;
}



//Copies original zones information into a new zone entry replacing the old zoneidnumber with the instflagnum
void ZoneDatabase::LoadInstZone(int32 target_zone_ID, int32 instFlagNum){
	char errbuf[MYSQL_ERRMSG_SIZE];
    char *query = 0;
    MYSQL_RES *result;
    MYSQL_ROW row;
	int32 affected_rows = 0;
	string tmpzonename = database.GetZoneName(target_zone_ID);
	string temp;
	const char* temp2;
	stringstream tmpFlag; // used for converting int32 instFlagNum to a string

	tmpFlag << instFlagNum;
	temp = tmpFlag.str();
	temp.append(tmpzonename);
	temp2 = temp.c_str();

	if (RunQuery(query, MakeAnyLenString(&query, "INSERT INTO zone (short_name, file_name, long_name, safe_x, safe_y, safe_z, graveyard_id, min_level, min_status, zoneidnumber, timezone, maxclients, weather, note, underworld, minclip, maxclip, fog_minclip, fog_maxclip, fog_blue, fog_red, fog_green, sky, ztype, zone_exp_multiplier, walkspeed, time_type, fog_red1, fog_green1, fog_blue1, fog_minclip1, fog_maxclip1, fog_red2, fog_green2, fog_blue2, fog_minclip2, fog_maxclip2, fog_red3, fog_green3, fog_blue3, fog_minclip3, fog_maxclip3, fog_red4, fog_green4, fog_blue4, fog_minclip4, fog_maxclip4, flag_needed, canbind, cancombat, canlevitate, castoutdoor, insttype, insttimer) SELECT '%s', file_name, long_name, safe_x, safe_y, safe_z, graveyard_id, min_level, min_status, %i, timezone, maxclients, weather, note, underworld, minclip, maxclip, fog_minclip, fog_maxclip, fog_blue, fog_red, fog_green, sky, ztype, zone_exp_multiplier, walkspeed, time_type, fog_red1, fog_green1, fog_blue1, fog_minclip1, fog_maxclip1, fog_red2, fog_green2, fog_blue2, fog_minclip2, fog_maxclip2, fog_red3, fog_green3, fog_blue3, fog_minclip3, fog_maxclip3, fog_red4, fog_green4, fog_blue4, fog_minclip4, fog_maxclip4, flag_needed, canbind, cancombat, canlevitate, castoutdoor, insttype, insttimer FROM zone WHERE zoneidnumber =%i", temp2,instFlagNum,target_zone_ID), errbuf, 0, &affected_rows)){
		safe_delete_array(query);}
	else {
		cerr << "Error in LoadInstZone query '" << query << "' " << errbuf << endl;
		safe_delete_array(query);
	}
}
Zone\zoneDB.cpp line 13 insert
Code:
#include <string>
#include <sstream>

Zone\zonedb.h
line 194 change const char* zone_name to int32 zoneid
Code:
bool	PopulateZoneSpawnList(int32 zoneid, LinkedList<Spawn2*> &spawn2_list, int32 repopdelay = 0);
Zone\Zonedb.h
At the end of Zone Related around line 181
Code:
int32   GetInstType(int32 zoneid);
bool    InstZoneLoaded(int32 target_zone_ID);
void    LoadInstZone(int32 target_zone_ID, int32 InstFlagNum);

Zone.cpp Line 1146 change short_name to zoneid
Code:
if (!database.PopulateZoneSpawnList(zoneid, spawn2_list, delay))
Zone.cpp Line 779 change short_name to zoneid
Code:
if (!database.PopulateZoneSpawnList(zoneid, spawn2_list))

Zone.cpp Line 772 change short_name to zoneid
Code:
else if (tmp == 0) {
	LogFile->write(EQEMuLog::Status, "No state saved, loading spawn2 points...");
	if (!database.PopulateZoneSpawnList(zoneid, spawn2_list))
	return false;
		}
Zone\Zone.cpp line 616 bottom of Zone::Shutdown insert
Code:
zone->ResetAuth();
	if (zone->GetZoneID() > database.GetDfltInstZFlag()){
		database.DeleteInstZone(zone->GetZoneID());
	}
	safe_delete(zone);
	dbasync->CommitWrites();
	UpdateWindowTitle();

Zone\spawn2.cpp line 226
Code:
bool ZoneDatabase::PopulateZoneSpawnList(int32 zoneid, LinkedList<Spawn2*> &spawn2_list, int32 repopdelay) {
	char errbuf[MYSQL_ERRMSG_SIZE];
	char* query = 0;
	MYSQL_RES *result;
	MYSQL_ROW row;
	
	const char *zone_name = database.GetZoneName(zoneid);
	int32 dfltInstZFlag = database.GetDfltInstZFlag();

	MakeAnyLenString(&query, "SELECT id, spawngroupID, x, y, z, heading, respawntime, variance, pathgrid, timeleft, _condition, cond_value FROM spawn2 WHERE zone='%s'", zone_name);
	
	if (RunQuery(query, strlen(query), errbuf, &result))
	{
		safe_delete_array(query);
		while((row = mysql_fetch_row(result)))
		{
			Spawn2* newSpawn = 0;
			if (zoneid > dfltInstZFlag){
				newSpawn = new Spawn2(atoi(row[0]), atoi(row[1]), atof(row[2]), atof(row[3]), atof(row[4]), atof(row[5]), atoi(row[6]), atoi(row[7]), 0, atoi(row[8]), atoi(row[10]), atoi(row[11]));
			}
			else {
				newSpawn = new Spawn2(atoi(row[0]), atoi(row[1]), atof(row[2]), atof(row[3]), atof(row[4]), atof(row[5]), atoi(row[6]), atoi(row[7]), atoi(row[9]), atoi(row[8]), atoi(row[10]), atoi(row[11]));
			}
			//newSpawn->Repop(repopdelay);
			spawn2_list.Insert( newSpawn );
		}
		mysql_free_result(result);
	}
	else
	{
		LogFile->write(EQEMuLog::Error, "Error in PopulateZoneLists query '%s': %s", query, errbuf);
		safe_delete_array(query);
		return false;
	}
	
	return true;
}
  #2  
Old 09-13-2008, 04:05 AM
trevius's Avatar
trevius
Developer
 
Join Date: Aug 2006
Location: USA
Posts: 5,946
Default

Definitely some interesting stuff! I will have to check this out more when I get a bit more time. I think this code could definitely be useful at some point. I don't want you to feel like your submissions are getting ignored though. If this can be finalized and get the quest commands added, this could actually be some really useful code. With limited resources for creating content, some of the more popular custom servers may have bottlenecks in some zones that are very popular. Maybe adding 1 instance during peak times, or when needed, would help balance out players and content. So, a small server with limited content could still be enjoyed by many.

Anyway, it is definitely something worth looking into more. I was wondering why you named the setting "instZOrgID" instead of something like "instZoneID". I am all for anything that is clear and as simple as possible. So, naming settings after what they are used to set is IMO the best way.
__________________
Trevazar/Trevius Owner of: Storm Haven
Everquest Emulator FAQ (Frequently Asked Questions) - Read It!
  #3  
Old 09-13-2008, 10:26 AM
Rocker8956
Hill Giant
 
Join Date: Sep 2007
Posts: 117
Default

Thank you for the reply Trevius.

If I get some time this weekend, after work and college, I will knock out some of the quest code to use for setting the instance flags and such. After looking at the questmgr.cpp it does not look like it would be too bad especially since a kind soul put instructions at the top.

The instZOrgID actually stands for Instance Zone’s Original Zone ID. It is used in the code to track what zone the instZflagNum (later used as the instance zone’s ID) belongs too. I couldn’t think of a better name for instZOrgID so I went with it but if we can come up with something a little more intuitive adjusting the code would not be difficult.
  #4  
Old 09-16-2008, 10:25 AM
Rocker8956
Hill Giant
 
Join Date: Sep 2007
Posts: 117
Default

Please note this code is not tested, I have no experience writing quests so I am hoping someone with quest writing experience will test it for me.

This code adds a quest function that will set a character's instance flag. Sending that character to an instance the next time they zone into the zone of your choice.

It requires two bits of information. The character's ID and the zoneID of the zone you want instanced.

If there are any questions please let me know.

Anyhow here is the code.

Zone\perlparser.cpp
Near Line 1759 insert
Code:
XS(XS__setindinstflag);
XS(XS__setindinstflag)
{
	dXSARGS;
	if (items != 2)
		Perl_croak(aTHX_ "Usage: setindinstflag(charID, orginalZoneID)");

	int32	charID = (int)SvIV(ST(0));
	int32	orgZoneID = (int)SvIV(ST(1));

	quest_manager.setindinstflag(charID, orgZoneID);

	XSRETURN_EMPTY;
}
Zone\perlparser.cpp
Around Line 1899 insert
Code:
newXS(strcpy(buf, "setindinstflag"), XS__setindinstflag, file);
Zone\questmgr.h
Around line 150 insert
Code:
void setindinstflag(int32 charID, int32 orgZoneID);
Zone\questmgr.cpp
At the end insert
Code:
void QuestManager::setindinstflag(int32 charID, int32 orgZoneID)
{
	database.setOneCharInstFlag(charID, orgZoneID);
}
Common\database.cpp
At the end insert
Code:
void Database::setOneCharInstFlag(int32 charID, int32 orgZoneID)
{
	char errbuf[MYSQL_ERRMSG_SIZE];
    char *query = 0;
    MYSQL_RES *result;
    MYSQL_ROW row;
	int instFlag;
	
	if (RunQuery(query, MakeAnyLenString(&query, "SELECT value FROM variables WHERE varname = 'curInstFlagNum'"), errbuf, &result))
	{
		safe_delete_array(query);
		if (mysql_num_rows(result) == 1) {
			row = mysql_fetch_row(result);
			instFlag = atoi(row[0]);
			mysql_free_result(result);
		}
		mysql_free_result(result);
	}
	else {
		cerr << "Error in GetCurInstFlagNum query '" << query << "' " << errbuf << endl;
		safe_delete_array(query);
	}
	
	if (RunQuery(query, MakeAnyLenString(&query, "UPDATE character_ SET instZflagNum=%i, instZOrgID=%i WHERE id=%i", instFlag, orgZoneID, charID), errbuf, &result))
	{
		safe_delete_array(query);
		mysql_free_result(result);
	}
	else {
		cerr << "Error in setCharInstFlagNum query '" << query << "' " << errbuf << endl;
		safe_delete_array(query);
	}

	instFlag++;

	if (RunQuery(query, MakeAnyLenString(&query, "UPDATE variables SET value=%i WHERE varname='curInstFlagNum'", instFlag), errbuf, &result))
	{
		safe_delete_array(query);
		mysql_free_result(result);
	}
	else {
		cerr << "Error in incrCurInstFlagNum query '" << query << "' " << errbuf << endl;
		safe_delete_array(query);
	}

}
Common\database.h
At the end insert
Code:
void	setOneCharInstFlag(int32 charID, int32 orgZoneID);
  #5  
Old 09-17-2008, 10:24 AM
Rocker8956
Hill Giant
 
Join Date: Sep 2007
Posts: 117
Default

Here is the code for setting a group’s instance flags through quests. This will allow the whole group to zone into the same instance.
Please note, I have no experience writing quests so this is untested. I appreciate any feedback.

zone\perlparser.cpp
Insert at the end around line 1914
Code:
newXS(strcpy(buf, "setgroupinstflag"), XS__setgroupinstflag, file);
zone\perparser.cpp
insert around line 1758
Code:
XS(XS__setgroupinstflag);
XS(XS__setgroupinstflag)
{
	dXSARGS;
	if (items != 2)
		Perl_croak(aTHX_ "Usage: setgroupinstflag(charID, orginalZoneID)");

	int32	charID = (int)SvIV(ST(0));
	int32	orgZoneID = (int)SvIV(ST(1));

	quest_manager.setgroupinstflag(charID, orgZoneID);

	XSRETURN_EMPTY;
}
zone\questmgr.h
Insert around line 151
Code:
void setgroupinstflag(int32 charID, int32 orgZoneID);
zone\questmgr.cpp
Insert at the end
Code:
void QuestManager::setgroupinstflag(int32 charID, int32 orgZoneID)
{
	database.setGroupInstFlagNum(charID, orgZoneID);
}
common\database.cpp
Insert at the end
Code:
void Database::setGroupInstFlagNum(int32 charID, int32 orgZoneID)
{
	char errbuf[MYSQL_ERRMSG_SIZE];
    char *query = 0;
    MYSQL_RES *result;
    MYSQL_ROW row;
	int32 groupid = 0;
	int instFlag = 0;
	int numCharsInGroup = 0; // Used to count number of characters in group
	
	// Get the current instant flag number
	if (RunQuery(query, MakeAnyLenString(&query, "SELECT value FROM variables WHERE varname = 'curInstFlagNum'"), errbuf, &result))
	{
		safe_delete_array(query);
		if (mysql_num_rows(result) == 1) {
			row = mysql_fetch_row(result);
			instFlag = atoi(row[0]);
			mysql_free_result(result);
		}
		mysql_free_result(result);
	}
	else {
		cerr << "Error in GetCurInstFlagNum query '" << query << "' " << errbuf << endl;
		safe_delete_array(query);
	}
	// Find out what group the character is in
	if (RunQuery(query, MakeAnyLenString(&query, "SELECT groupid from group_id where charid=%i", charID), errbuf, &result)) {
		if((row = mysql_fetch_row(result)))
		{
			if(row[0])
				groupid=atoi(row[0]);
		}
		else
			printf("Unable to get group id, char not found!\n");
		mysql_free_result(result);
	}
	else
			printf("Unable to get group id: %s\n",errbuf);
	safe_delete_array(query);
	// Find out how many other characters are in the group
	if (RunQuery(query, ("SELECT COUNT(charid) FROM group_id WHERE groupid=%i", groupid), errbuf, &result)) {
		safe_delete_array(query);
		row = mysql_fetch_row(result);
		if (row && row[0])
		{ 
			numCharsInGroup = atoi(row[0]);
			mysql_free_result(result);
		}
	}
	// Select the character IDs of the characters in the group
	if (RunQuery(query, MakeAnyLenString(&query, "SELECT charid from group_id where groupid='%i'", groupid), errbuf, &result))
	{
		int i = 0;
		// Set each group members instflag
		while ((i <= numCharsInGroup)) 
		{
			charID = atoi(row[i]);
			if (RunQuery(query, MakeAnyLenString(&query, "UPDATE character_ SET instZflagNum=%i, instZOrgID=%i WHERE id=%i", instFlag, orgZoneID, charID), errbuf, &result))
			{
				safe_delete_array(query);
				mysql_free_result(result);
			}
			else {
				cerr << "Error in setCharInstFlagNum query '" << query << "' " << errbuf << endl;
				safe_delete_array(query);
			}
			i++;
		}
			safe_delete_array(query);
			mysql_free_result(result);
	}
	// Increment the curInstFlagNum
	instFlag++;

	if (RunQuery(query, MakeAnyLenString(&query, "UPDATE variables SET value=%i WHERE varname='curInstFlagNum'", instFlag), errbuf, &result))
	{
		safe_delete_array(query);
		mysql_free_result(result);
	}
	else {
		cerr << "Error in incrCurInstFlagNum query '" << query << "' " << errbuf << endl;
		safe_delete_array(query);
	}
}
common\database.h
Insert at the end
Code:
void	setGroupInstFlagNum(int32 charID, int32 orgZoneID);
  #6  
Old 09-19-2008, 07:30 PM
Rocker8956
Hill Giant
 
Join Date: Sep 2007
Posts: 117
Default

Some changes to the quest code plus a way to manually set a characters instflag.

Syntax for quest functions
setinstflag(charID, originalZoneID, type)
charID = character ID of the character requesting flag
originalZoneID = zoneID of the zone you want instanced (blackburrow would be 17)
type = 0 will flag only the requesting character
type = 1 will flag the requesting character’s group including that character
type = 2 will flag the requesting character’s raid including that character
setinstflagmanually(charID, originalZoneID, instFlag)
charID = character ID of the character requesting flag
originalZoneID = zoneID of the zone you want instanced (blackburrow would be 17)
instFlag = the instance flag you want to give the requesting character. Pick a number between 1000 and 1999. Try not to use the same one for different quests.

The setinstflagmanually will allow you to send characters to the same instance zone even if they are not in the same group or raid.

SQL changes
Code:
INSERT INTO variables VALUES ('curInstFlagNum', 2000, 'Determines what instance flag will be handed out next', '2008-09-05 04:46:47');
If you already inserted this into your database just change the value to 2000

Code changes
Get rid of my previous quest code. I combined the single, group, and raid flags into one quest function and added a way to manually set a character’s instance flag.

perparser.cpp
insert around line 1758
Code:
XS(XS__setinstflag);
XS(XS__setinstflag)
{
	dXSARGS;
	if (items != 3)
		Perl_croak(aTHX_ "Usage: setinstflag(charID, orginalZoneID, type)");

	int32	charID = (int)SvIV(ST(0));
	int32	orgZoneID = (int)SvIV(ST(1));
	int		type = (int)SvIV(ST(2));

	quest_manager.setinstflag(charID, orgZoneID, type);

	XSRETURN_EMPTY;
}
XS(XS__setinstflagmanually);
XS(XS__setinstflagmanually)
{
	dXSARGS;
	if (items != 3)
		Perl_croak(aTHX_ "Usage: setinstflagmanually(charID, orginalZoneID, instFlag)");

	int32	charID = (int)SvIV(ST(0));
	int32	orgZoneID = (int)SvIV(ST(1));
	int		instFlag = (int)SvIV(ST(2));

	quest_manager.setinstflagmanually(charID, orgZoneID, instFlag);

	XSRETURN_EMPTY;
}

Perlparser.cpp
Insert at the end around line 1916 (becomes line 1916 after previous insert of code into perparser.cpp)
Code:
newXS(strcpy(buf, "setinstflag"), XS__setinstflag, file);
newXS(strcpy(buf, "setinstflagmanually"), XS__setinstflagmanually, file);



questmgr.h
Insert around line 151
Code:
void setinstflag(int32 charID, int32 orgZoneID, int type);
void setinstflagmanually(int32 charID, int32 orgZoneID, int instFlag);
questmgr.cpp
Insert at the end
Code:
void QuestManager::setinstflag(int32 charID, int32 orgZoneID, int type)
{
	if (type == 0)
		database.setOneCharInstFlag(charID, orgZoneID);
	else if(type == 1)
		database.setGroupInstFlagNum(charID, orgZoneID);
	else if(type == 2)
		database.setRaidInstFlagNum(charID, orgZoneID);
}

void QuestManager::setinstflagmanually(int32 charID, int32 orgZoneID, int instFlag)
{
	database.setCharInstFlag(charID, orgZoneID, instFlag);
}
database.cpp
Insert at the end
Code:
void Database::setOneCharInstFlag(int32 charID, int32 orgZoneID)
{
	int instFlag = getCurInstFlagNum();
	
	// Set character's instZoneFlag
	setCharInstFlag(charID, orgZoneID, instFlag);

	// Increment the curInstFlagNum
	incrCurInstFlagNum(instFlag);

}

void Database::setGroupInstFlagNum(int32 charID, int32 orgZoneID)
{
	char errbuf[MYSQL_ERRMSG_SIZE];
    char *query = 0;
    MYSQL_RES *result;
    MYSQL_ROW row;
	int32 groupid = 0;
	int instFlag = getCurInstFlagNum();
	int numCharsInGroup = 0; // Used to count number of characters in group
	
	// Find out what group the character is in
	if (RunQuery(query, MakeAnyLenString(&query, "SELECT groupid from group_id where charid=%i", charID), errbuf, &result)) {
		if((row = mysql_fetch_row(result)))
		{
			if(row[0])
				groupid=atoi(row[0]);
		}
		else
			printf("Unable to get group id, char not found!\n");
		mysql_free_result(result);
	}
	else
			printf("Unable to get group id: %s\n",errbuf);
	safe_delete_array(query);
	// Find out how many other characters are in the group
	if (RunQuery(query, ("SELECT COUNT(charid) FROM group_id WHERE groupid=%i", groupid), errbuf, &result)) {
		safe_delete_array(query);
		row = mysql_fetch_row(result);
		if (row && row[0])
		{ 
			numCharsInGroup = atoi(row[0]);
			mysql_free_result(result);
		}
	}
	// Select the character IDs of the characters in the group
	if (RunQuery(query, MakeAnyLenString(&query, "SELECT charid from group_id where groupid='%i'", groupid), errbuf, &result))
	{
		int i = 0;
		// Set each group members instflag
		while ((i <= numCharsInGroup)) 
		{
			charID = atoi(row[i]);
			setCharInstFlag(charID, orgZoneID, instFlag);
			i++;
		}
			safe_delete_array(query);
			mysql_free_result(result);
	}
	// Increment the curInstFlagNum
	incrCurInstFlagNum(instFlag);
}

void Database::setRaidInstFlagNum(int32 charID, int32 orgZoneID)
{
	char errbuf[MYSQL_ERRMSG_SIZE];
    char *query = 0;
    MYSQL_RES *result;
    MYSQL_ROW row;
	int32 raidid = 0;
	int instFlag = getCurInstFlagNum();
	int numCharsInRaid = 0; // Used to count number of characters in raid

	// Find out what raid the character is in
	if (RunQuery(query, MakeAnyLenString(&query, "SELECT raidid from raid_members where charid=%i", charID), errbuf, &result)) {
		safe_delete_array(query);
		if((row = mysql_fetch_row(result)))
		{
			if(row[0])
				raidid=atoi(row[0]);
			mysql_free_result(result);
		}
		else
			printf("Unable to get raidid, char not found!\n");
		mysql_free_result(result);
	}
	else
			printf("Unable to get raid id: %s\n",errbuf);
	safe_delete_array(query);
	// Find out how many other characters are in the raid
	if (RunQuery(query, ("SELECT COUNT(charid) FROM raid_members WHERE raidid=%i", raidid), errbuf, &result)) {
		safe_delete_array(query);
		row = mysql_fetch_row(result);
		if (row && row[0])
		{ 
			numCharsInRaid = atoi(row[0]);
			mysql_free_result(result);
		}
	}
	// Select the character IDs of the characters in the raid
	if (RunQuery(query, MakeAnyLenString(&query, "SELECT charid from raid_members where raidid='%i'", raidid), errbuf, &result))
	{
		int i = 0;
		// Set each group members instflag
		while ((i <= numCharsInRaid)) 
		{
			charID = atoi(row[i]);
			setCharInstFlag(charID, orgZoneID, instFlag);
			i++;
		}
			safe_delete_array(query);
			mysql_free_result(result);
	}
	// Increment the curInstFlagNum
	incrCurInstFlagNum(instFlag);

}

void Database::incrCurInstFlagNum(int instFlag)
{
	char errbuf[MYSQL_ERRMSG_SIZE];
    char *query = 0;
    MYSQL_RES *result;
    MYSQL_ROW row;
	// Increment the curInstFlagNum
	instFlag++;
	if (instFlag > 9999)
		instFlag = 2000;

	if (RunQuery(query, MakeAnyLenString(&query, "UPDATE variables SET value=%i WHERE varname='curInstFlagNum'", instFlag), errbuf, &result))
	{
		safe_delete_array(query);
		mysql_free_result(result);
	}
	else {
		cerr << "Error in incrCurInstFlagNum query '" << query << "' " << errbuf << endl;
		safe_delete_array(query);
	}
}

int Database::getCurInstFlagNum()
{
	char errbuf[MYSQL_ERRMSG_SIZE];
    char *query = 0;
    MYSQL_RES *result;
    MYSQL_ROW row;
	int instFlag = 0;

	// Get the current instant flag number
	if (RunQuery(query, MakeAnyLenString(&query, "SELECT value FROM variables WHERE varname = 'curInstFlagNum'"), errbuf, &result))
	{
		safe_delete_array(query);
		if (mysql_num_rows(result) == 1) {
			row = mysql_fetch_row(result);
			instFlag = atoi(row[0]);
			mysql_free_result(result);
			return instFlag;
		}
		else{
			mysql_free_result(result);
			cerr << "Error in GetCurInstFlagNum query '" << query << "' " << errbuf << endl;
			safe_delete_array(query);
			return instFlag;
		}

	}
	else {
		cerr << "Error in GetCurInstFlagNum query '" << query << "' " << errbuf << endl;
		safe_delete_array(query);
		return instFlag;
	}
}
void Database::setCharInstFlag(int32 charID, int32 orgZoneID, int instFlag)
{
	char errbuf[MYSQL_ERRMSG_SIZE];
    char *query = 0;
    MYSQL_RES *result;
    MYSQL_ROW row;

	if (RunQuery(query, MakeAnyLenString(&query, "UPDATE character_ SET instZflagNum=%i, instZOrgID=%i WHERE id=%i", instFlag, orgZoneID, charID), errbuf, &result))
	{
		safe_delete_array(query);
		mysql_free_result(result);
	}
	else 
	{
		cerr << "Error in setCharInstFlagNum query '" << query << "' " << errbuf << endl;
		safe_delete_array(query);
	}
}

database.h
Insert at the end
Code:
	void	setOneCharInstFlag(int32 charID, int32 orgZoneID);
	void	setGroupInstFlagNum(int32 charID, int32 orgZoneID);
	void	setRaidInstFlagNum(int32 charID, int32 orgZoneID);
	void	incrCurInstFlagNum(int instFlag);
	int	getCurInstFlagNum();
	void	setCharInstFlag(int32 charID, int32  orgZoneID, int instFlag);
  #7  
Old 09-21-2008, 02:34 PM
cavedude's Avatar
cavedude
The PEQ Dude
 
Join Date: Apr 2003
Location: -
Posts: 1,988
Default

I haven't had a lot of time to play with this, but it looks like the group and raid types crash the zone when used. This happens whether you are in a group/raid or not. Here is the output:

Code:
#0  0x08155ec3 in Database::setGroupInstFlagNum (this=0x836ac24, charID=22,
    orgZoneID=223) at /usr/include/stdlib.h:336
#1  0x08248eee in QuestManager::setinstflag (this=0x836a920, charID=1,
    orgZoneID=0, type=1) at questmgr.cpp:1572
#2  0x08250883 in XS__setinstflag (my_perl=0x83c6f20, cv=0x8430954)
    at perlparser.cpp:2174
#3  0xb79d22dd in Perl_pp_entersub () from /usr/lib/libperl.so.5.8
#4  0xb79d0a8f in Perl_runops_standard () from /usr/lib/libperl.so.5.8
#5  0xb797108e in ?? () from /usr/lib/libperl.so.5.8
#6  0x083c6f20 in ?? ()
#7  0xb7a4f14e in ?? () from /usr/lib/libperl.so.5.8
#8  0x00000000 in ?? ()
Your line numbers will probably differ from mine, so if something doesn't line up, just ask. I can tell you though that questmgr.cpp:1572 is database.setGroupInstFlagNum(charID, orgZoneID);
in my source. The raid dump is the same, just with the raid code. If you want that, just let me know.

Another small problem, /goto doesn't seem to work in instances. The red text pops telling you who you're going to, but you don't actually move. This may be unrelated to your code, but /goto does indeed work in normal zones.

The single player function works perfectly, and the instances themselves from what I can tell work great as well. I had a couple of toons in two instances of the same zone, and the spawns and quests worked great in each instance. No overlapping at all. Very impressive.

Now some suggestions, since your system forces instances to be dynamic (static versions of the zone are ignored, and can only be accessed by players without an instance flag) is there anyway that you can add a rule that will allow server ops to keep the instances open for a certain amount of time after the last player left it? If the op sets the rule to 10 minutes, then the zone stays open for 10 minutes after it became empty of players.

Also, could raid type 2 be changed to flag group members as well? The idea behind this is so we could just set everything to type 2. If a group comes along that aren't in a raid, they can get flagged with this single function instead of having an extra elsif in the script to check for non-raid groups.

Can a variable be added to enable Perl to check if a player is already flagged for an instance? Also, can a new Perl function be added that will delete the flags from a player/group/raid (set both columns to 0?)

Finally, I'm not sure how your system handles this, but what happens to players that join a raid/group after they've been flagged? Can it be made so that they inherit those flags?

Last edited by cavedude; 09-21-2008 at 10:42 PM..
  #8  
Old 09-21-2008, 04:04 PM
Rocker8956
Hill Giant
 
Join Date: Sep 2007
Posts: 117
Default

I think I figured out where I messed up the group and raid instance flags. Database::setGroupInstFlagNum and Database::setRaidInstFlagNum will need replaced with the ones below.

Can you post, or send me, the quest script you are using to set these? I suck at quest writing so using yours would help me test them.

I like the idea of holding the zone open for a set amount of time. Also, I agree there needs to be ways to check if someone is already flagged, remove the flag, and inherit the flag of the group/raid leader. I also want to add a way to shutdown the zone after a certain amount of time (like ldons).

The only issue I could see with making the type 2 flag raids or groups is some server admins may want to limit how many people can be in the instance. Though I could make a type 3 that flags both.

It might take me a while to figure out why goto is not working in instances. But I will see.

Code:
void Database::setGroupInstFlagNum(int32 charID, int32 orgZoneID)
{
	char errbuf[MYSQL_ERRMSG_SIZE];
    char *query = 0;
    MYSQL_RES *result;
    MYSQL_ROW row;
	int32 groupid = 0;
	int instFlag = getCurInstFlagNum();
	int numCharsInGroup = 0; // Used to count number of characters in group
	
	// Find out what group the character is in
	if (RunQuery(query, MakeAnyLenString(&query, "SELECT groupid from group_id where charid=%i", charID), errbuf, &result)) {
		if (mysql_num_rows(result) == 1) {
				row = mysql_fetch_row(result);
				groupid=atoi(row[0]);
		}
		else
			printf("Unable to get group id, char not found!\n");
		mysql_free_result(result);
	}
	else
			printf("Unable to get group id: %s\n",errbuf);
	safe_delete_array(query);
	// Find out how many other characters are in the group
	if (RunQuery(query, ("SELECT COUNT(charid) FROM group_id WHERE groupid=%i", groupid), errbuf, &result)) {
		safe_delete_array(query);
		row = mysql_fetch_row(result);
		numCharsInGroup = atoi(row[0]);
		mysql_free_result(result);
	}
	// Select the character IDs of the characters in the group
	if (RunQuery(query, MakeAnyLenString(&query, "SELECT charid from group_id where groupid='%i'", groupid), errbuf, &result))
	{
		row = mysql_fetch_row(result);
		
		int i = 0;
		// Set each group members instflag
		while ((i <= numCharsInGroup)) 
		{
			charID = atoi(row[i]);
			setCharInstFlag(charID, orgZoneID, instFlag);
			i++;
		}
			safe_delete_array(query);
			mysql_free_result(result);
	}
	// Increment the curInstFlagNum
	incrCurInstFlagNum(instFlag);
}
Code:
void Database::setRaidInstFlagNum(int32 charID, int32 orgZoneID)
{
	char errbuf[MYSQL_ERRMSG_SIZE];
    char *query = 0;
    MYSQL_RES *result;
    MYSQL_ROW row;
	int32 raidid = 0;
	int instFlag = getCurInstFlagNum();
	int numCharsInRaid = 0; // Used to count number of characters in raid

	// Find out what raid the character is in
	if (RunQuery(query, MakeAnyLenString(&query, "SELECT raidid from raid_members where charid=%i", charID), errbuf, &result)) {
		safe_delete_array(query);
		if (mysql_num_rows(result) == 1) {
			row = mysql_fetch_row(result);
			raidid=atoi(row[0]);
			mysql_free_result(result);
		}
		else
			printf("Unable to get raidid, char not found!\n");
		mysql_free_result(result);
	}
	else
			printf("Unable to get raid id: %s\n",errbuf);
	safe_delete_array(query);
	// Find out how many other characters are in the raid
	if (RunQuery(query, ("SELECT COUNT(charid) FROM raid_members WHERE raidid=%i", raidid), errbuf, &result)) {
		row = mysql_fetch_row(result);
		numCharsInRaid = atoi(row[0]);
		mysql_free_result(result);
		safe_delete_array(query);
	}
	// Select the character IDs of the characters in the raid
	if (RunQuery(query, MakeAnyLenString(&query, "SELECT charid from raid_members where raidid='%i'", raidid), errbuf, &result))
	{
		int i = 0;
		row = mysql_fetch_row(result);
		// Set each group members instflag
		while ((i <= numCharsInRaid)) 
		{
			charID = atoi(row[i]);
			setCharInstFlag(charID, orgZoneID, instFlag);
			i++;
		}
			safe_delete_array(query);
			mysql_free_result(result);
	}
	// Increment the curInstFlagNum
	incrCurInstFlagNum(instFlag);
}
  #9  
Old 09-21-2008, 04:40 PM
trevius's Avatar
trevius
Developer
 
Join Date: Aug 2006
Location: USA
Posts: 5,946
Default

Actually, why not just make an option to keep all dynamic zones up for X amount of time after the last player leaves? I wouldn't mind having that for my dynamic zones as well
__________________
Trevazar/Trevius Owner of: Storm Haven
Everquest Emulator FAQ (Frequently Asked Questions) - Read It!
  #10  
Old 09-24-2008, 02:24 PM
cavedude's Avatar
cavedude
The PEQ Dude
 
Join Date: Apr 2003
Location: -
Posts: 1,988
Default

I'm not going to sticky this one yet, I am still getting a zone crash with the newest code regarding the raid and group types. Could you post a diff to make sure I am not merging incorrectly?
  #11  
Old 09-25-2008, 03:00 AM
Rocker8956
Hill Giant
 
Join Date: Sep 2007
Posts: 117
Default

I am fairly certainly you are merging it correctly. I just screwed up the code. Here are two I found this afternoon that need changed. Basically I had ‘%i’ when it should be %i
It is kinda hard to see but the %i is surrounded by two ‘

I will try to post a full diff by this weekend. I would do it sooner but work is killing me this week.

line 31 inside Database::setGroupInstFlagNum
Code:
// Select the character IDs of the characters in the group
	if (RunQuery(query, MakeAnyLenString(&query, "SELECT charid from group_id where groupid=%i", groupid), errbuf, &result))

line 33 inside Database::setRaidInstFlagNum
Code:
// Select the character IDs of the characters in the raid
	if (RunQuery(query, MakeAnyLenString(&query, "SELECT charid from raid_members where raidid=%i", raidid), errbuf, &result))

One side question though. Please don’t laugh to hard (this is my first time writing a quest) below is what I wrote for a quest to set these instance flags. It does not work. I know the quest::setinstflag($charid,18,0); is causing the problem since the says work. It never sets the flags in the database and just hangs at the setinstflag. I figured out it hangs there by swapping the quest::say and quest::setinstflag places. Any idea where I messed up the script? or is my code that wrong?
Code:
sub EVENT_SAY { 
$charid = 0;
$charid = $client->CharacterID(); 
if($text=~/Hail/i){ 
	quest::say("Greetings traveler, Do you want to go play in Blackburrow?"); }
if($text=~/yes/i){ 
	quest::say("Oh wonderful! Do you want to play by yourself, in a group, or in a raid?"); }
if($text=~/self/i){
	quest::say("You can now go play in your own little Blackburrow world.");
	quest::setinstflag($charid,17,0); }
if($text=~/group/i){
	quest::say("Your party can now go play in their own little Blackburrow world.");
	quest::setinstflag($charid,17,1); }
if($text=~/raid/i){
	quest::say("Your raid can now go play in their only little Blackburrow world.");
	quest::setinstflag($charid,17,2); }
if($text=~/setme/i){
	quest::say("Okay then GO PLAY!!!"); 
	quest::setinstflagmanually($charid,17,1500); } 
}
  #12  
Old 09-25-2008, 10:14 AM
Andrew80k
Dragon
 
Join Date: Feb 2007
Posts: 659
Default

Your quest script is fine. It's your code that you use to call setinstflag that's messed up. I'd put some debug statements in there and try to figure out where it's giving you grief. I've REALLY been wanting to mess around with this but I'm so limited on time right now....
  #13  
Old 09-25-2008, 01:24 PM
joligario's Avatar
joligario
Developer
 
Join Date: Mar 2003
Posts: 1,497
Default

Just out of curiosity, why are they int32 variables instead of just int? Could that make a difference when compiling between the different machines? Does it make a difference compiling on the different machines when typecasting an int -> int32?
  #14  
Old 09-26-2008, 07:06 PM
Rocker8956
Hill Giant
 
Join Date: Sep 2007
Posts: 117
Default

Well I got it working. I will try to post a diff tonight or tomorrow. The quest functions got an overhaul.

Quote:
Originally Posted by joligario View Post
Just out of curiosity, why are they int32 variables instead of just int? Could that make a difference when compiling between the different machines? Does it make a difference compiling on the different machines when typecasting an int -> int32?

I think most programming languages view int and int32 as the same thing. However, I took your suggestion and changed most of the int32 to int. Looks better and is easier to read even if it has little to no effect on the code.
  #15  
Old 09-26-2008, 07:23 PM
AndMetal
Developer
 
Join Date: Mar 2007
Location: Ohio
Posts: 648
Default

Quote:
Originally Posted by joligario View Post
Just out of curiosity, why are they int32 variables instead of just int? Could that make a difference when compiling between the different machines? Does it make a difference compiling on the different machines when typecasting an int -> int32?
To understand int32, we need to look at common/types.h:
Code:
typedef unsigned char		int8;
typedef unsigned char		byte;
typedef unsigned short		int16;
typedef unsigned int		int32;

typedef unsigned char		uint8;
typedef  signed  char		sint8;
typedef unsigned short		uint16;
typedef  signed  short		sint16;
typedef unsigned int		uint32;
typedef  signed  int		sint32;
As I understand, int in C++ assumes signed by default on most compilers:
Quote:
By default, if we do not specify either signed or unsigned most compiler settings will assume the type to be signed
You can certainly use int for 32-bit signed integers, but by using sint32 instead, you don't have to worry about compiler-specific assumptions, plus it can be easier to understand just browsing through the source.
__________________
GM-Impossible of 'A work in progress'
A non-legit PEQ DB server
How to create your own non-legit server

My Contributions to the Wiki
Closed Thread


Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump

   

All times are GMT -4. The time now is 07:57 PM.


 

Everquest is a registered trademark of Daybreak Game Company LLC.
EQEmulator is not associated or affiliated in any way with Daybreak Game Company LLC.
Except where otherwise noted, this site is licensed under a Creative Commons License.
       
Powered by vBulletin®, Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Template by Bluepearl Design and vBulletin Templates - Ver3.3