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.