Go Back   EQEmulator Home > EQEmulator Forums > Development > Development::Development

Development::Development Forum for development topics and for those interested in EQEMu development. (Not a support forum)

Reply
 
Thread Tools Display Modes
  #1  
Old 10-28-2004, 11:16 AM
Cisyouc
Demi-God
 
Join Date: Jun 2004
Location: Heaven.
Posts: 1,260
Default Code: Player Flags (Perl and Command)

Hello all.
For awhile now I've been meaning to finish this command to restrict access to zones if you dont have a certain flag. After alot of reworks Ive got a working version.

It works very simply. Here is the schema:
Code:
DROP TABLE IF EXISTS qflags;
CREATE TABLE qflags (
  charid varchar(64) NOT NULL,
  zoneid int(11) NOT NULL default 0,
  UNIQUE KEY qflag (charid,zoneid)
) TYPE=MyISAM;

alter table zone add qflagreq int(2) NOT NULL default '0';
Below is the code, and below that will be the syntax for #qflag and quest::qflag();. How the code works is it checks qflagreq to see if the zone requires the client to have a flag to enter. If it is 0, it skips the qflag code. If it is 1, it will require a flag. It will then look up the user in the qflag table for that specific zone id. If the flag doesnt exist, the user will not be able to enter. If they do have a flag, the zone will process the user and send them off normally.

Database.cpp
FIND:
Code:
		cerr << "Error in GetLiveChar query '" << query << "' " << errbuf << endl;
		safe_delete_array(query);
	}
	
	return false;
}
ADD AFTER:
Code:
//Cisyouc: Begin qFlag Checks
bool Database::ControlqFlag(const char* name, uint32 zoneid, bool adding)
{
	char errbuf[MYSQL_ERRMSG_SIZE];
	char *query = 0;

	if(adding == TRUE)
	{
		if(!RunQuery(query, MakeAnyLenString(&query, "INSERT INTO qflags (charid, zoneid) VALUES ('%s','%i');",name,zoneid), errbuf))
		{
			safe_delete_array(query)
			return false;
		}
		else
		{
			safe_delete_array(query)
			return true;
		}
	}
	if(adding == FALSE)
	{
		if(!RunQuery(query, MakeAnyLenString(&query, "DELETE FROM qflags WHERE charid='%s' AND zoneid=%i;", name, zoneid), errbuf))
		{
			safe_delete_array(query)
			return false;
		}
		else
		{
			safe_delete_array(query)
			return true;
		}
	}
	return false;
}
bool Database::GetqFlag(const char* name, uint32 zoneid)
{
	char errbuf[MYSQL_ERRMSG_SIZE];
	char *query = 0;
	MYSQL_RES *result;
	MYSQL_ROW row;
	if(!RunQuery(query, MakeAnyLenString(&query, "SELECT zoneid FROM qflags WHERE charid='%s' AND zoneid=%i;",name,zoneid), errbuf, &result))
	{
		cerr << "[qFlag] Error connecting to db." << endl;
		return false;
	}
	else
	{
		row=mysql_fetch_row(result);
		if(mysql_num_rows(result) >= 1)
		{
			if(atoi(row[0]) == zoneid)
			{
				return true;
			}
			else
			{
				return false;
			}
		}
		else if(mysql_num_rows(result) == 0)
		{
			return false;
		}
		cerr << "[qFlag] An error has occured." << endl;
		return false;
	}
	return false;
}

bool Database::GetNeedqFlag(uint32 zoneid)
{
	char errbuf[MYSQL_ERRMSG_SIZE];
	char *query = 0;
	MYSQL_RES *result;
	MYSQL_ROW row;
	if(!RunQuery(query, MakeAnyLenString(&query, "SELECT qflagreq FROM zone WHERE zoneidnumber=%i;",zoneid), errbuf, &result))
	{
		cerr <<"[qFlag] Error Checking qFlag: " << errbuf << endl;
		return FALSE;
	}
	else
	{
		row=mysql_fetch_row(result);
			if(atoi(row[0]) == 1)
			{
				mysql_free_result(result);
				return TRUE;
				
			}
			else
			{
				mysql_free_result(result);
				return FALSE;
			}
		mysql_free_result(result);
		return FALSE;
	}
	return FALSE;
}
//Cisyouc: End qFlag Checks
Database.h
FIND:
Code:
	bool	UpdateLiveChar(char* charname,int32 lsaccount_id);
ADD AFTER:
Code:
	bool	ControlqFlag(const char* name, uint32 zoneid, bool adding = true);
	bool	GetqFlag(const char* name, uint32 zoneid);
	bool	GetNeedqFlag(uint32 zoneid);
client_process.cpp
FIND:
Code:
#ifdef RAIDADDICTS
					if (!raidaddicts.ZoneInCheck(zc->zoneID, this)) {
						myerror = ZONE_ERROR_NOEXPERIENCE;
						RAZone = false;
					}
#endif
ADD AFTER:
Code:
					//Cisyouc: Begin qFlag Additions
					if(database.GetNeedqFlag(zc->zoneID))
					{
					cerr << "[qFlag] Loading qFlags for zone: " << zc->zoneID << endl; 
						if(!database.GetqFlag(GetName(),zc->zoneID))
						{
							cout << "[qFlag] User " << GetName() << " denied entry." << endl;
							strcpy(target_zone,zone->GetShortName());
							tarx = GetX();
							tary = GetY();
							tarz = GetZ();
							zonesummon_x = 0;
							zonesummon_y = 0;
							zonesummon_z = 0;
							Message(15, "Your will is not sufficient to pass into this area.");	
						}
						else
						{
							cout << "[qFlag] " << GetName() << " has appropriate qflag for zone "<< zc->zoneID << endl;
						}
					}
					//Cisyouc: End qFlag Additions
command.cpp
FIND:
Code:
command_add("pf","- ",0,command_pf) ||
ADD AFTER:
Code:
		//Cisyouc: qflag implementation
		command_add("qflag","[add/delete/help(1,2,3)] [name] [zoneid]",80,command_qflag) ||
FIND:
Code:
	cd->unknown15[0] = sep->arg[4][0] ? atoi(sep->arg[4]) : 0;
	cd->unknown15[1] = sep->arg[5][0] ? atoi(sep->arg[5]) : 0;
	cd->unknown19 = sep->arg[6][0] ? atoi(sep->arg[6]) : 0;
	entity_list.QueueClients(c, outapp);
	safe_delete(outapp);
*/
}
ADD AFTER:
Code:
//Cisyouc: Begin qFlag Implementation
void command_qflag(Client *c, const Seperator *sep)
{
	if(atoi(sep->arg[1]) == 2)
	{
		bool result = database.ControlqFlag(sep->arg[2], atoi(sep->arg[3]), TRUE);
			if(result == false)
			{
				c->Message(13, "An error has occured inserting into database.");
			}
			else if(result = true)
			{
				if(sep->arg[1] == c->GetName())
				{
					c->Message(15, "You have recieved a character flag!");
				}
				else
				{
					c->Message(15, "Player recieves a character flag!");
				}
			}
			else
			{
				c->Message(13, "An unknown error has occured.");
			}
	}
	if(atoi(sep->arg[1]) == 3)
	{
		bool result = database.ControlqFlag(sep->arg[2], atoi(sep->arg[3]), FALSE);
		if(result == false)
		{
			c->Message(13, "An error has ocured inserting into database.");
		}
		else if(result = true)
		{
			if(sep->arg[1] == c->GetName())
			{
				c->Message(13, "You have had a character flag REVOKED!");
			}
			else
			{
				c->Message(13, "Player has had a character flag REVOKED!");
			}
		}
		else
		{
				c->Message(13, "An unknown error has occured.");
		}
	}
	if(atoi(sep->arg[1]) == 1)
	{
		if(atoi(sep->arg[2]) == 1)
		{
			c->Message(0, "To implement qFlag in quests, please use the PERL function,");
			c->Message(0, "quest::qflag([function], [zoneid]);");
			c->Message(0, "Functions: 1 = Add Flag, 2 = Delete Flag");
			c->Message(0, "Example: quest::qflag(1,202);");
			c->Message(0, "Flags user for poknowledge (202)");
		}
		else if(atoi(sep->arg[2]) == 2)
		{
			c->Message(0, "#qflag syntax:");
			c->Message(0, "#qflag [function] [charname] [zoneid]");
			c->Message(0, "Functions: 2 for ADD flag, 3 for DELETE flag.");
		}
		else
		{
		c->Message(0, "---Quest Flags by Cisyouc---");
		c->Message(0, "Help file syntax:");
		c->Message(0, "Quest Help: #qflag 1 1");
		c->Message(0, "Command Help: #qflag 1 2");
		}
	}
}
//Cisyouc: End qFlag Implementation
command.h
FIND:
Code:
void command_zcolor(Client *c, const Seperator *sep);
ADD AFTER:
Code:
//Cisyouc qflag command
void command_qflag(Client *c, const Seperator *sep);
FOR PERL IMPLEMENTATION:
embparser.cpp
Code:
"sub qflag{push(@cmd_queue,{func=>'qflag',args=>join(',',@_)});}"
parser.cpp
Code:
			 else if (!strcmp(command,"qflag")) {
				 /*
				 qFlag Implementation for Perl
				 By Cisyouc
				 Syntax: quest::qflag([function],[zoneid])
				 Functions:
					1 for FLAG
					2 for REMOVE FLAG
				 See example on EQEmulator.net
				 Be sure to source necessary sql file before use.
				 */
				
						char errbuf[MYSQL_ERRMSG_SIZE];
						char *query = 0;
						MYSQL_RES *result;
				
					if(atoi(arglist[0]) == 1)
					{
						if(!database.RunQuery(query, MakeAnyLenString(&query, "INSERT INTO qflags (charid, zoneid) VALUES ('%s','%s');",mob->CastToClient()->GetName(), arglist[1]), errbuf, &result))
						{
							cout << "[qFlag] Quest::qFlag Ran: " << mob->CastToClient()->GetName() << " has been flagged for " << atoi(arglist[1]) << endl;
							mob->Message(15, "You have recieved a character flag!");
						}

						else
						{
							cout << "[qFlag] Could not flag " << mob->CastToClient()->GetName() << " for " << atoi(arglist[1]) << "." << endl;
							cout << "[qFlag] Database Error: " << errbuf << endl;
							mob->Message(13, "An error has occured. Please contact a GM as soon as possible.");
						}
						mysql_free_result(result);
					}
					else if(atoi(arglist[0]) == 2)
					{
						if(!database.RunQuery(query, MakeAnyLenString(&query, "DELETE FROM qflags WHERE charid='%s' AND zoneid=%s;",mob->CastToClient()->GetName(), arglist[1]), errbuf, &result))
						{
							cout << "[qFlag] Quest::qFlag Ran: " << mob->CastToClient()->GetName() << " has had flag REVOKED for " << atoi(arglist[1]) << endl;
							mob->Message(13, "You have had a character flag REVOKED!");
						}

						else
						{
							cout << "[qFlag] Could not flag " << mob->CastToClient()->GetName() << " for " << atoi(arglist[1]) << "." << endl;
							cout << "[qFlag] Database Error: " << errbuf << endl;
							mob->Message(13, "An error has occured. Please contact a GM as soon as possible.");
						}
						mysql_free_result(result);
					}
			 }
Syntax:
Help: #qFlag 1 help
Help w/Quests: #qFlag 1 1
Help w/Commands: #qFlag 1 2
Flag Player: #qFlag 2 [charname] [zoneid]
De-Flag Player: #qFlag 3 [charname] [zoneid]

Perl Syntax:
Add Flag: quest::qflag(1, [zoneid]);
De-Flag: quest::qflag(2, [zoneid]);

So, again, to make a zone require a flag, do this mysql query:
Code:
UPDATE zone SET qflagreq='1' WHERE zoneidnumber='xxxx';
(Replacing xxx with the zone id)

Thanks to the guys at #perl for catching my stupid mistakes

Let me know what you think of this.
__________________
namespace retval { template <class T> class ReturnValueGen { private: T x; public: ReturnValueGen() { x = 0; }; T& Generator() { return x; }; }; } int main() { retval::ReturnValueGen<int> retvalue; return retvalue.Generator(); }
C++ is wonderful.
Reply With Quote
  #2  
Old 10-28-2004, 11:31 AM
Scorpx725
Discordant
 
Join Date: Feb 2003
Location: Wish I knew.
Posts: 251
Default

Very nice job, Cisyouc, glad I could help today.
__________________
* KingMort has left #eqemu
<Richardo> KingDrama has left #EQEMU
<Richardo> the rule my pants!
Reply With Quote
  #3  
Old 10-28-2004, 11:32 AM
RangerDown
Demi-God
 
Join Date: Mar 2004
Posts: 1,066
Default

Double check the primary key on your schema.

Under that schema, a character can be flagged for only one zone at a time.
__________________
<idleRPG> Rogean ate a plate of discounted, day-old sushi. This terrible calamity has slowed them 0 days, 15:13:51 from level 48.
Reply With Quote
  #4  
Old 10-28-2004, 11:36 AM
Cisyouc
Demi-God
 
Join Date: Jun 2004
Location: Heaven.
Posts: 1,260
Default

Quote:
Originally Posted by RangerDown
Double check the primary key on your schema.

Under that schema, a character can be flagged for only one zone at a time.
Whoops. Fixed.
__________________
namespace retval { template <class T> class ReturnValueGen { private: T x; public: ReturnValueGen() { x = 0; }; T& Generator() { return x; }; }; } int main() { retval::ReturnValueGen<int> retvalue; return retvalue.Generator(); }
C++ is wonderful.
Reply With Quote
  #5  
Old 10-28-2004, 02:12 PM
Cisyouc
Demi-God
 
Join Date: Jun 2004
Location: Heaven.
Posts: 1,260
Default

Bah. Also fixed a syntax error too, I just spotted.
__________________
namespace retval { template <class T> class ReturnValueGen { private: T x; public: ReturnValueGen() { x = 0; }; T& Generator() { return x; }; }; } int main() { retval::ReturnValueGen<int> retvalue; return retvalue.Generator(); }
C++ is wonderful.
Reply With Quote
  #6  
Old 10-28-2004, 07:14 PM
eq_addict_08
Hill Giant
 
Join Date: Nov 2003
Location: Drunk tank
Posts: 199
Default

Yea!! Will merge into my server asap. Man, I realy need to learn how to progam, would love to contribute something worthwhile.
Reply With Quote
  #7  
Old 10-29-2004, 02:08 AM
ajb20
Hill Giant
 
Join Date: Jul 2004
Posts: 106
Default

Code:
c:\documents and settings\adamxp\desktop\eqemucvs\source\common\database.cpp(1170) : warning C4715: 'Database::GetqFlag' : not all control paths return a value 



command.cpp(865) : warning C4805: '==' : unsafe mix of type 'char' and type 'bool' in operation
command.cpp(888) : warning C4805: '==' : unsafe mix of type 'char' and type 'bool' in operation
Other than that compiled great. Thanks Cisyouc. For those of you without a compiler, I added it here http://www.eqemulator.net/forums/viewtopic.php?t=17924
Reply With Quote
  #8  
Old 10-29-2004, 06:41 AM
Cisyouc
Demi-God
 
Join Date: Jun 2004
Location: Heaven.
Posts: 1,260
Default

Hmmm. I'm not getting those warnings, ajb. Regardless as long as #qFlag works its not worth worrying about =)
__________________
namespace retval { template <class T> class ReturnValueGen { private: T x; public: ReturnValueGen() { x = 0; }; T& Generator() { return x; }; }; } int main() { retval::ReturnValueGen<int> retvalue; return retvalue.Generator(); }
C++ is wonderful.
Reply With Quote
  #9  
Old 10-29-2004, 06:46 AM
cofruben
Old-EQEmu Developer
 
Join Date: Oct 2002
Location: Spain
Posts: 323
Default

nice work Cisyouc.Still helping .
Reply With Quote
  #10  
Old 10-29-2004, 07:42 AM
m0oni9
Hill Giant
 
Join Date: Dec 2003
Posts: 166
Default

Quote:
Originally Posted by Cisyouc
Hmmm. I'm not getting those warnings, ajb. Regardless as long as #qFlag works its not worth worrying about =)
Not to be a pedant, but it is good practice to fix warnings. Just because it works now does not guarantee it will work later on, or in another situation (ie: for someone else).
Reply With Quote
  #11  
Old 10-29-2004, 07:57 AM
Cisyouc
Demi-God
 
Join Date: Jun 2004
Location: Heaven.
Posts: 1,260
Default

Quote:
Originally Posted by m0oni9
Quote:
Originally Posted by Cisyouc
Hmmm. I'm not getting those warnings, ajb. Regardless as long as #qFlag works its not worth worrying about =)
Not to be a pedant, but it is good practice to fix warnings. Just because it works now does not guarantee it will work later on, or in another situation (ie: for someone else).
My lazyness at best.

-edit-
Syntax fixed.
__________________
namespace retval { template <class T> class ReturnValueGen { private: T x; public: ReturnValueGen() { x = 0; }; T& Generator() { return x; }; }; } int main() { retval::ReturnValueGen<int> retvalue; return retvalue.Generator(); }
C++ is wonderful.
Reply With Quote
Reply


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 06:14 AM.


 

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