PDA

View Full Version : Vote Kick Player!


thepoetwarrior
01-15-2014, 10:27 PM
Created a system to allow vote kick player off the server for 1 hour.

This is a way of giving dealing with trolls without giving someone 100% power to perma ban or suspend accounts. And its entertaining way of dealing with trolls, cause people love to vote!

Must be $status > 0 to initiate a vote kick on a player, and can't vote against a player with $status > 0 too.

Currently requires 5 player vote within 15 minutes. (Can be edited)

Players get to vote once per 15 min and per toon getting voted to be kicked. This is limited by both IP and character name.

Once a vote is succeeded then the player and ALL accounts linked by IP will get immediately disconnected and suspended for 60 minutes.

The code goes into your global_player.pl so anyone in any zone can vote.

Requires telnet for disconnecting the player, unless there is easier way to remotely disconnect someone. The telnet code is there, so just need to edit the name/pass to reflect the same added to account table.

You can find the few places that require editing by searching for <EDIT HERE> in the code.

There are no plugins required, this code is 100% complete all in one file.

Requires 1 custom table named '_vote_kick' (sql to create this table is provided).

Probably reinvented the wheel on a few things, and stuff could be done more efficiently. So feel free to post suggestions, tweaks, feedback, etc.

(Code posted below)

thepoetwarrior
01-15-2014, 10:30 PM
this goes in global_player.pl

http://pastebin.com/zYAhtSdz (Link for easier viewing, or see code posted below)

################################################## ################################################## ##
################################################## ################################################## ##
###
### FILE NAME : global_player.pl
### VERSION : 1.0.0
### UPDATED : Jan 15, 2014
### QUEST : Vote Kick Players
### PLUGINS REQURIED : NONE
###
### EDITS : YOU CAN SEARCH BELOW FOR SAME TEXT IN THESE COMMENTS, SEARCH FOR <EDIT HERE>
###
### MUST EDIT TELNET!! : my $ACCOUNT_NAME = "TELNET ACCOUNT"; # <--- <EDIT HERE> Make sure its unique!
### my $ACCOUNT_PASS = "PASSWORD1234"; # <--- <EDIT HERE> Add Numbers, and make sure not too long else seems to fail
###
### OPTIONAL EDITS : quest::setglobal("$QVOTE_IP","$GET_QTIME","7","S900"); # <------- <EDIT HERE>
### quest::setglobal("$QVOTE_NAME","$GET_QTIME","7","S900"); # <------- <EDIT HERE>
### my $GET_TIME_SUSPENDED = 3600; # <------- <EDIT HERE>
###
################################################## ################################################## ##
################################################## ################################################## ##

sub EVENT_SAY
{
if ($text =~/^Vote Kick$/i)
{
$client->Message(7, "Syntax: Vote Kick <name>");
}

if ($text =~/^Vote Kick /i)
{
VOTE_KICK($text);
}

if ($status > 0)
{
if ($text =~/^#Vote Kick$/i)
{
$client->Message(7, "Syntax: #Vote Kick <name> <reason>");
}
if ($text =~/^#Vote Kick /i)
{
VOTE_KICK_START($text);
}
}
}


################################################## #
################################################## #
###
### PLAYER VOTE KICK
###
################################################## #
################################################## #
sub VOTE_KICK
{

my @values = split(' ', CLEAN_TEXT_ALL($_[0]));
my $VOTE_NAME;
my @GET_STATUS;

# IF 3 VALUES THEN GET NAME
if ($values[2])
{
$VOTE_NAME = $values[2];
}

# IF WE HAVE NAME, GET ID, Proper Name, and $status
if ($VOTE_NAME)
{
my $GET_CHAR_ID = GET_ID_BY_CHARACTER($VOTE_NAME);
$VOTE_NAME = GET_CHARACTER_BY_ID($GET_CHAR_ID);
@GET_STATUS = GET_PLAYER_STATUS($VOTE_NAME);
}

my @GET_IP_ADDRESS = GET_PLAYER_STATUS($name); # 0-Status, 1-IP, 2-LoginCount
my $QVOTE_IP = "$GET_IP_ADDRESS[1]" . "_VOTED_$VOTE_NAME";
my $QVOTE_NAME = "$name" . "_VOTED_$VOTE_NAME";

my $GET_QVOTE_IP = GET_QGLOBAL_EXPIRE($QVOTE_IP);
my $GET_QVOTE_NAME = GET_QGLOBAL_EXPIRE($QVOTE_NAME);
my $GET_QTIME = time();
my $CHECK_TIME = time();

# IF PLAYER VOTED, DONT ALLOW AGAIN, UNLESS $status > 200
if ($GET_QVOTE_IP && $GET_QVOTE_IP > $CHECK_TIME && $status < 200 ||
$GET_QVOTE_NAME && $GET_QVOTE_NAME > $CHECK_TIME && $status < 200 )
{
$client->Message(7, "You already voted for $VOTE_NAME in the last 15 minutes!");
}
# ELSE SET GLOBAL AND DO VOTE
else
{
# If Guide or GM then don't allow their name to be vote kicked
if ($GET_STATUS[0] > 0)
{
$client->Message(7, "You can NOT vote kick $VOTE_NAME!");
}

# Else everyone else can be vote kicked
elsif ($VOTE_NAME)
{
$connect = LoadMySQLConnection(); # global (not 'my') cause we're going to call sub routines with while loops
my $query_handle;
my $query;
my $REQUIRED_VOTES = 5;
my $CURRENT_TIME = time();

################################################## ################################
# START CHECK FOR CURRENT VOTE
$query = " SELECT kick_name, vote_count, start_vote_time
FROM _vote_kick
WHERE kick_name LIKE '$VOTE_NAME'
AND vote_count < '$REQUIRED_VOTES'
AND start_vote_time > '$CURRENT_TIME'
";
# quest::gmsay("$query", 18, 0);
$query_handle = $connect->prepare($query);
$query_handle->execute();
# IF THERE IS CURRENT VOTING THEN ADD +1 COUNT
# START GET 1 RECORD
if ($query_handle->rows)
{
my $ref = $query_handle->fetchrow_hashref();
my $GET_KICK_NAME = $ref->{'kick_name'};
my $GET_VOTE_COUNT = $ref->{'vote_count'};
my $GET_VOTE_TIME = time() - $ref->{'start_vote_time'};

$GET_VOTE_COUNT++;
quest::we(15, "$name voted to kick $GET_KICK_NAME ($GET_VOTE_COUNT / $REQUIRED_VOTES Votes Required)");
quest::setglobal("$QVOTE_IP","$GET_QTIME","7","S900"); # <------- <EDIT HERE> TIME IN SECONDS TO MAKE ANOTHER VOTE
quest::setglobal("$QVOTE_NAME","$GET_QTIME","7","S900"); # <------- <EDIT HERE> TIME IN SECONDS TO MAKE ANOTHER VOTE

if ($GET_VOTE_COUNT >= $REQUIRED_VOTES)
{
my $GET_TIME_SUSPENDED = 3600; # <------- <EDIT HERE> TIME IN SECONDS TO BE SUSPENDED
my $GET_SUSPEND_TIME = (time + $GET_TIME_SUSPENDED);
my @GET_NAMES = WHO_IS_PLAYER_LIST($GET_KICK_NAME); # Get all characters linked by account and IP.
quest::we(7, "$GET_KICK_NAME has been kicked for $GET_TIME_SUSPENDED seconds!");

my $i = 0;
while ($GET_NAMES[$i])
{
SUSPEND_PLAYER_NAME($GET_NAMES[$i], $GET_SUSPEND_TIME);
quest::gmsay("GM: $GET_NAMES[$i] has been suspended! (VOTE_KICK)", 13, 1);
$i++;
}
$i--;
quest::gmsay("GM: $i characters has been suspended! (VOTE_KICK)", 13, 1);

# DISCONNECT ALL CHARACTERS LINKED BY IP IMMEDIATELY!
KICK_PLAYER_NAME(\@GET_NAMES);

}

$query = " UPDATE _vote_kick
SET vote_count = '$GET_VOTE_COUNT'
WHERE kick_name LIKE '$GET_KICK_NAME'
";
# quest::gmsay("$query", 18, 0);
$query_handle = $connect->prepare($query);
$query_handle->execute();

}
# END CHECK FOR CURRENT VOTE
################################################## ################################
# ELSE NO VOTE STARTED YET
else
{
$client->Message(7, "Voting for $VOTE_NAME has not started yet.");
}
$query_handle->finish();
$connect->disconnect();
}
else
{
$client->Message(7, "Syntax: Vote Kick <name>");
}
} # End Else Not Voted Yet
return 1;
} # End VOTE_KICK


################################################## #
################################################## #
###
### GM AND GUIDE VOTE KICK
###
################################################## #
################################################## #
sub VOTE_KICK_START
{
my @values = split(' ', CLEAN_TEXT_ALL($_[0]));
my $VOTE_NAME;
my $VOTE_REASON;
my @GET_STATUS;

# IF 3 VALUES THEN GET NAME
if ($values[2])
{
$VOTE_NAME = $values[2];
}

if ($VOTE_NAME)
{
my $GET_CHAR_ID = GET_ID_BY_CHARACTER($VOTE_NAME);
$VOTE_NAME = GET_CHARACTER_BY_ID($GET_CHAR_ID);
@GET_STATUS = GET_PLAYER_STATUS($VOTE_NAME);
}

# If Guide or GM then don't allow their name to be vote kicked
if ($GET_STATUS[0] > 0)
{
$client->Message(7, "You can NOT vote kick $VOTE_NAME!");
}

# Else everyone else can be vote kicked
elsif ($VOTE_NAME)
{
my $connect = LoadMySQLConnection();
my $query_handle;
my $query;
my $REQUIRED_VOTES = 5;
my $CURRENT_TIME = time();

################################################## ################################
# START CHECK FOR CURRENT VOTE
$query = " SELECT kick_name, vote_count, start_vote_time
FROM _vote_kick
WHERE kick_name LIKE '$VOTE_NAME'
AND vote_count < '$REQUIRED_VOTES'
AND start_vote_time > '$CURRENT_TIME'
";
# quest::gmsay("$query", 18, 0);
$query_handle = $connect->prepare($query);
$query_handle->execute();
# IF CURRENT VOTING, DONT MAKE NEW ONE
if ($query_handle->rows)
{
my $ref = $query_handle->fetchrow_hashref();
my $GET_KICK_NAME = $ref->{'kick_name'};
my $GET_VOTE_COUNT = $ref->{'vote_count'};
my $GET_VOTE_TIME = time() - $ref->{'start_vote_time'};
$client->Message(7, "$GET_KICK_NAME already has $GET_VOTE_COUNT votes and expires in $GET_VOTE_TIME seconds.");
}
# END CHECK FOR CURRENT VOTE
################################################## ################################
# ELSE NO CURRENT VOTE, LETS MAKE ONE
else
{
my $GET_DATETIME = CUSTOM_DATE_TIME(time());
my $GET_VOTE_COUNT = 0;
my $GET_REASON = "";

# IF 4+ VALUES THEN GET REASON FOR KICK
if ($values[3])
{
# Add (concat) all words to the reason
my $i = 3;
while ($values[$i])
{
if ($i > 3)
{
$GET_REASON .= " ";
}
$GET_REASON .= "$values[$i]";
$i++;
}
}
# ELSE NO REASON GIVEN FOR KICK
else
{
$GET_REASON = "None Given";
}
my $GET_START = time() + 900;

my $query = " REPLACE INTO _vote_kick (datetime, mod_name, kick_name, vote_count, reason, start_vote_time)
VALUES ('$GET_DATETIME', '$name', '$VOTE_NAME', '$GET_VOTE_COUNT', '$GET_REASON', '$GET_START')";
# quest::gmsay("$query", 18, 0);
$query_handle = $connect->prepare($query);
$query_handle->execute();

$client->Message(7, "Vote Kick $VOTE_NAME Started!");
quest::we(15, "/say Vote Kick $VOTE_NAME (Reason: $GET_REASON)");
}
$query_handle->finish();
$connect->disconnect();
}
else
{
$client->Message(7, "Syntax: #Vote Kick <name> <reason>");
}

return 1;

} # End VOTE_KICK_START


# GET ACCOUNT ID VIA PLAYER NAME
sub GET_PLAYER_ACCOUNT_ID
{
my $FIND_TOON_NAME = CLEAN_TEXT_ALL($_[0]);
my $GET_ID = 0;
my $connect = LoadMySQLConnection();
my $query = " SELECT DISTINCT a.id
FROM account a
INNER JOIN character_ c ON c.account_id = a.id
WHERE c.name LIKE '$FIND_TOON_NAME'
LIMIT 1";
my $query_handle = $connect->prepare($query);
$query_handle->execute();
if ($query_handle->rows)
{
my $ref = $query_handle->fetchrow_hashref();
$GET_ID = $ref->{'id'};
}
$query_handle->finish();
$connect->disconnect();
return $GET_ID;
} # End GET_PLAYER_ACCOUNT_ID


sub SUSPEND_PLAYER_NAME
{
# If at least 2 parameters (Name + Time)
if ($_[1])
{
my $GET_NAME = $_[0];
my $GET_TIME = SUSPEND_DATE(CLEAN_NUMBER($_[1]));
my $GET_ACCOUNT_ID = GET_PLAYER_ACCOUNT_ID($GET_NAME);

if ($GET_ACCOUNT_ID)
{
# SET SUSPENSION TIME
# my $connect = LoadMySQLConnection(); # DONE BY PARENT ROUTINE
my $query = " UPDATE account SET suspendeduntil = '$GET_TIME' WHERE id = '$GET_ACCOUNT_ID'";
# quest::gmsay("$query", 18, 1);
$query_handle = $connect->prepare($query);
$query_handle->execute();
$query_handle->finish();
# $connect->disconnect(); # DONE BY PARENT ROUTINE
}
else
{
quest::gmsay("SUSPEND_PLAYER_NAME ERROR! NO ACCOUNT ID FOR $_[0]", 18, 1);
}
}
else
{
quest::gmsay("SUSPEND_PLAYER_NAME ERROR! DOES NOT HAVE 2ND PARAMETER! $_[0] $_[1]", 18, 1);
}

return 1;
} # End SUSPEND_PLAYER_NAME


# Special Date/Time format for suspenduntil field in account table
sub SUSPEND_DATE
{
my $CONVERT_TIME = 0;

if ($_[0])
{
$CONVERT_TIME = $_[0];
}
else
{
$CONVERT_TIME = time();
}

my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isd st) = localtime($CONVERT_TIME);
$mon++; # Required

$mon = sprintf("%02d", $mon);
$mday = sprintf("%02d", $mday);
$year = sprintf("%02d", $year % 100) + 2000;

$hour = sprintf("%02d", $hour);
$min = sprintf("%02d", $min);
$sec = sprintf("%02d", $sec);

# RETURN FORMAT: 2014-12-31 23:59:59
my $RETURN_DATE = "$year" . "-" . "$mon" . "-" . "$mday" . " " . " $hour:$min:$sec";
return $RETURN_DATE;
} # End SUSPEND_DATE()


# CUSTOM FORMATTED DATE AND TIME
sub CUSTOM_DATE_TIME
{
my $CONVERT_TIME = 0;

if ($_[0])
{
$CONVERT_TIME = $_[0];
}
else
{
$CONVERT_TIME = time();
}

my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isd st) = localtime($CONVERT_TIME);
$mon++; # Required

$mon = sprintf("%02d", $mon);
$mday = sprintf("%02d", $mday);
$year = sprintf("%02d", $year % 100);

$hour = sprintf("%02d", $hour);
$min = sprintf("%02d", $min);
$sec = sprintf("%02d", $sec);

# RETURN FORMAT: 01-31-14 23:59:59
my $ez_time = "$mon" . "-" . "$mday" . "-" . "$year" . " $hour:$min:$sec";
return $ez_time;
} # End CUSTOM_DATE_TIME()


# Instantly kick player offline by logging in with Telnet
sub KICK_PLAYER_NAME
{
my @GET_NAMES = @{$_[0]};
use Net::Telnet();
my $telnet;
$telnet = new Net::Telnet (Timeout=>10, Port=>'9000', Prompt=>'/\> $/');
$telnet->open("localhost");

################################################## ########################
# I NOTICED LOGIN CAN BE PICKY
# ACCOUNT NAME : LIKE TO USE A SPACE IN THE ACCOUT NAME
# PASSWORD : PASSWORD1234 SEEMS TO WORK,
# BUT NOT PASSWORD12345678, MAYBE TOO LONG?
# MAKE SURE THE ACCOUNT NAME HAS 255 STATUS IN ACCOUNT TABLE
################################################## ########################
my $ACCOUNT_NAME = "TELNET ACCOUNT"; # <--- <EDIT HERE> Make sure its unique!
my $ACCOUNT_PASS = "PASSWORD1234"; # <--- <EDIT HERE> Add Numbers, and make sure not too long else seems to fail
$telnet->login("$ACCOUNT_NAME", "$ACCOUNT_PASS");

my $i = 0;
while ($GET_NAMES[$i])
{
$telnet->cmd("kick $GET_NAMES[$i]");
quest::gmsay("GM: $GET_NAMES[$i] has been kicked! (KICK_PLAYER_NAME)", 4, 1);
$i++;
}

$i--;
quest::gmsay("GM: $i characters has been kicked! (KICK_PLAYER_NAME)", 4, 1);

exit;
} # End KICK_PLAYER_NAME


sub WHO_IS_PLAYER_LIST
{
# my $connect = LoadMySQLConnection(); # CREATED BY PARENT ROUTINE
my $FIND_TOON_NAME = $_[0];
my @LIST_OF_TOONS;

my $query = " SELECT DISTINCT a_ip.ip
FROM account a
INNER JOIN account_ip a_ip ON a_ip.accid = a.id
INNER JOIN character_ c ON c.account_id = a.id
WHERE c.name LIKE '$FIND_TOON_NAME'
ORDER BY a_ip.lastused DESC
LIMIT 1";
# quest::gmsay("$query", 18, 0);
my $query_handle = $connect->prepare($query);
$query_handle->execute();

# START GET 1 RECORD
if ($query_handle->rows)
{
my $ref = $query_handle->fetchrow_hashref();
my $GET_IP = $ref->{'ip'};

my $query2 = " SELECT DISTINCT c.name
FROM account a
INNER JOIN account_ip a_ip ON a_ip.accid = a.id
INNER JOIN character_ c ON c.account_id = a.id
WHERE a_ip.ip LIKE '$GET_IP'
ORDER BY c.name ASC
LIMIT 200";
# quest::gmsay("$query2", 18, 0);
my $query_handle2 = $connect->prepare($query2);
$query_handle2->execute();

my $place_count = 0;
while(my $ref2 = $query_handle2->fetchrow_hashref)
{
my $SHOW_NAME = $ref2->{'name'};
push (@LIST_OF_TOONS, $SHOW_NAME);
$place_count++;
}
$place_count--;
quest::gmsay("GM: WHO_IS_PLAYER_LIST Results : $place_count Toons Total.", 18, 1);
$query_handle2->finish();
}
else
{
quest::gmsay("GM: WHO_IS_PLAYER_LIST LIST : $FIND_TOON_NAME NOT FOUND!", 18, 1);
}
# END GET 1 RECORD

$query_handle->finish();
# $connect->disconnect(); # DONE BY PARENT ROUTINE
return @LIST_OF_TOONS;
} # End WHO_IS_PLAYER_LIST()


# Very Simple: Get Qglobal `expdate` of `name` and Return it
sub GET_QGLOBAL_EXPIRE
{
my $connect = LoadMySQLConnection();
my $qglobal_name = $_[0];
my $a_name = "NULL";
my $b_value = "0";
my $query = "SELECT name, expdate FROM quest_globals WHERE name = '$qglobal_name' LIMIT 1";
my $query_handle = $connect->prepare($query);
$query_handle->execute();
if ($query_handle->rows)
{
my $ref = $query_handle->fetchrow_hashref();
$a_name = $ref->{'name'};
$b_value = $ref->{'expdate'};
}
$query_handle->finish();
$connect->disconnect();
return $b_value;
} # End GET_QGLOBAL_EXPIRE()


### RETURN CHARACTERS NAME
sub GET_CHARACTER_BY_ID
{
if ($_[0])
{
my $connect = LoadMySQLConnection();
my $CHECK_CHARID = $_[0];
my $RETURN_NAME = "";
my $query = "SELECT name FROM character_ WHERE id = '$CHECK_CHARID' LIMIT 1";
my $query_handle = $connect->prepare($query);
$query_handle->execute();

if ($query_handle->rows)
{
my $ref = $query_handle->fetchrow_hashref();
$RETURN_NAME = $ref->{'name'};
}

$query_handle->finish();
$connect->disconnect();
return $RETURN_NAME;
}
} # End GET_CHARACTER_BY_ID()


### RETURN CHARACTERS ID
sub GET_ID_BY_CHARACTER
{
if ($_[0])
{
my $connect = LoadMySQLConnection();
my $CHECK_CHAR_NAME = $_[0];
my $RETURN_ID = 0;
my $query = "SELECT id FROM character_ WHERE name LIKE '$CHECK_CHAR_NAME' LIMIT 1";
my $query_handle = $connect->prepare($query);
$query_handle->execute();

if ($query_handle->rows)
{
my $ref = $query_handle->fetchrow_hashref();
$RETURN_ID = $ref->{'id'};
}

$query_handle->finish();
$connect->disconnect();
return $RETURN_ID;
}
} # End GET_ID_BY_CHARACTER()


sub GET_PLAYER_STATUS
{
my $GET_NAME = $_[0];
my @GET_STATUS;

my $connect = LoadMySQLConnection();

my $query = " SELECT DISTINCT a.status, a_ip.ip, SUM(a_ip.count)
FROM account a
INNER JOIN account_ip a_ip ON a_ip.accid = a.id
INNER JOIN character_ c ON c.account_id = a.id
WHERE c.name LIKE '$GET_NAME'
ORDER BY a_ip.lastused DESC
LIMIT 1";

my $query_handle = $connect->prepare($query);
$query_handle->execute();

# START GET 1 RECORD
if ($query_handle->rows)
{
# quest::gmsay("GM: HAS STATUS", 18, 0);
my $ref = $query_handle->fetchrow_hashref();
my $GET_ACCOUNT_STATUS = $ref->{'status'};
my $GET_IP_ADDRESS = $ref->{'ip'};
my $LOGIN_COUNT = $ref->{'SUM(a_ip.count)'}; # For another GM tool I have.

# Get $status value from account table
if (defined($GET_ACCOUNT_STATUS))
{
push(@GET_STATUS, $GET_ACCOUNT_STATUS);
}
else
{
push(@GET_STATUS, "NA");
}

# Get IP address from account_ip table
if ($GET_IP_ADDRESS)
{
push(@GET_STATUS, $GET_IP_ADDRESS);
}
else
{
push(@GET_STATUS, "NA");
}

# Get number of times logged in total by IP from account_ip table
if (defined($LOGIN_COUNT))
{
push(@GET_STATUS, $LOGIN_COUNT);
# quest::gmsay("GM: LOGIN COUNT: $LOGIN_COUNT", 18, 0);
}
else
{
push(@GET_STATUS, "NA");
}
}
# END GET 1 RECORD
else
{
# quest::gmsay("GM: $GET_NAME HAS -NO- STATUS", 18, 0);
push(@GET_STATUS, "NA");
push(@GET_STATUS, "NA");
push(@GET_STATUS, "NA");
}

$query_handle->finish();
$connect->disconnect();

return @GET_STATUS;

} # End GET_PLAYER_STATUS


sub CLEAN_TEXT_ALL
{
local $_ = shift;
s/[^a-zA-Z0-9(). ]+//g;
return $_;
}


sub CLEAN_TEXT
{
local $_ = shift;
s/[^a-zA-Z]+//g;
return $_;
}


sub CLEAN_NUMBER
{
local $_ = shift;
s/[^0-9]+//g;
return $_;
}


### Establish a Connection with password from Config File
sub LoadMySQLConnection
{
use DBI;
use DBD::mysql;
my $confile = "eqemu_config.xml"; #default config file in server folder has user and pass
open(F, "<$confile") or quest::gmsay("GM: sub LoadMySQLConnection() 'open' FAILED !!!!", 15, 1);
my $indb = 0;

while(<F>)
{
s/\r//g;
if(/<database>/i) { $indb = 1; }
next unless($indb == 1);
if(/<\/database>/i) { $indb = 0; last; }
if(/<host>(.*)<\/host>/i) { $host = $1; }
elsif(/<username>(.*)<\/username>/i) { $user = $1; }
elsif(/<password>(.*)<\/password>/i) { $pass = $1; }
elsif(/<db>(.*)<\/db>/i) { $db = $1; }
}

my $dsn = "dbi:mysql:$db:localhost:3306";
my $connect = DBI->connect($dsn, $user, $pass) or quest::gmsay("GM: sub LoadMySQLConnection() 'connect' FAILED !!!!", 15, 1);

return $connect;
} # End LoadMySQLConnection()



this creates the table required

CREATE TABLE `_vote_kick` (
`datetime` text NOT NULL,
`mod_name` varchar(65) NOT NULL DEFAULT '',
`kick_name` varchar(65) NOT NULL DEFAULT '',
`vote_count` int(11) NOT NULL DEFAULT '0',
`reason` text NOT NULL,
`start_vote_time` int(11) NOT NULL DEFAULT '0',
PRIMARY KEY (`kick_name`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

Kingly_Krab
01-16-2014, 12:56 AM
This is pretty cool, although I don't believe you can use a # in a Perl script in the newer revisions of the source, as it comes up as unrecognized command. Here's the C++ for what I'm talking about.
I have personally tried #commands for my server and it doesn't work due to this code.
case 8:
{ // /say
if(message[0] == COMMAND_CHAR)
{
if(command_dispatch(this, message) == -2)
{
if(parse->PlayerHasQuestSub(EVENT_COMMAND))
{
int i = parse->EventPlayer(EVENT_COMMAND, this, message, 0);
if(i != 0)
{
Message(13, "Command '%s' not recognized.", message);
}
}
else
{
Message(13, "Command '%s' not recognized.", message);
}
}
break;
}
Mob* sender = this;
if (GetPet() && GetPet()->FindType(SE_VoiceGraft))
sender = GetPet();

entity_list.ChannelMessage(sender, chan_num, language, lang_skill, message);
parse->EventPlayer(EVENT_SAY, this, message, language);

if (sender != this)
break;

if(quest_manager.ProximitySayInUse())
entity_list.ProcessProximitySay(message, this, language);

if (GetTarget() != 0 && GetTarget()->IsNPC())
{
if(!GetTarget()->CastToNPC()->IsEngaged())
{
CheckLDoNHail(GetTarget());
CheckEmoteHail(GetTarget(), message);

if(DistNoRootNoZ(*GetTarget()) <= 200)
{
NPC *tar = GetTarget()->CastToNPC();
parse->EventNPC(EVENT_SAY, tar->CastToNPC(), this, message, language);
if(RuleB(TaskSystem, EnableTaskSystem))
{
if(UpdateTasksOnSpeakWith(tar->GetNPCTypeID()))
{
tar->DoQuestPause(this);
}
}
}
}
else
{
if (DistNoRootNoZ(*GetTarget()) <= 200)
{
parse->EventNPC(EVENT_AGGRO_SAY, GetTarget()->CastToNPC(), this, message, language);
}
}
}
break;
}

Akkadius
01-16-2014, 01:08 AM
This is pretty cool, although I don't believe you can use a # in a Perl script in the newer revisions of the source, as it comes up as unrecognized command. Here's the C++ for what I'm talking about.
I have personally tried #commands for my server and it doesn't work due to this code.
case 8:
{ // /say
if(message[0] == COMMAND_CHAR)
{
if(command_dispatch(this, message) == -2)
{
if(parse->PlayerHasQuestSub(EVENT_COMMAND))
{
int i = parse->EventPlayer(EVENT_COMMAND, this, message, 0);
if(i != 0)
{
Message(13, "Command '%s' not recognized.", message);
}
}
else
{
Message(13, "Command '%s' not recognized.", message);
}
}
break;
}
Mob* sender = this;
if (GetPet() && GetPet()->FindType(SE_VoiceGraft))
sender = GetPet();

entity_list.ChannelMessage(sender, chan_num, language, lang_skill, message);
parse->EventPlayer(EVENT_SAY, this, message, language);

if (sender != this)
break;

if(quest_manager.ProximitySayInUse())
entity_list.ProcessProximitySay(message, this, language);

if (GetTarget() != 0 && GetTarget()->IsNPC())
{
if(!GetTarget()->CastToNPC()->IsEngaged())
{
CheckLDoNHail(GetTarget());
CheckEmoteHail(GetTarget(), message);

if(DistNoRootNoZ(*GetTarget()) <= 200)
{
NPC *tar = GetTarget()->CastToNPC();
parse->EventNPC(EVENT_SAY, tar->CastToNPC(), this, message, language);
if(RuleB(TaskSystem, EnableTaskSystem))
{
if(UpdateTasksOnSpeakWith(tar->GetNPCTypeID()))
{
tar->DoQuestPause(this);
}
}
}
}
else
{
if (DistNoRootNoZ(*GetTarget()) <= 200)
{
parse->EventNPC(EVENT_AGGRO_SAY, GetTarget()->CastToNPC(), this, message, language);
}
}
}
break;
}

Some doucher must have removed it, I had # comands trickle-down into EVENT_SAY given there was no found command.

I'll have to check it out.

Kingly_Krab
01-16-2014, 01:10 AM
Cool, thanks Akkadius, it would be great to get that functionality back. I've been told anything with a # in front of it isn't sent to the chat, is that true? So like #test would not be seen by anyone around me, but I'd get the functionality? I've used it before the code was changed a couple of months ago, I just never paid attention to whether or not others could tell.

Kingly_Krab
01-16-2014, 02:00 AM
Okay, so the coders are working on this currently, hopefully it's fixed soon.

thepoetwarrior
01-16-2014, 04:57 AM
I guess remove the # in front of the command if your current source won't allow it.

I didn't realize they removed that, our source was last updated in Sept.

KLS
01-16-2014, 05:14 PM
Okay! Was asked to look into this and I did.

I use the following test script in my global_player.pl successfully:
sub EVENT_SAY
{
if ($text =~/^Vote Kick$/i)
{
$client->Message(7, "Syntax: Vote Kick <name>");
}

if ($text =~/^Vote Kick /i)
{
$client->Message(0, "Vote kick: $text");
}

if ($status > 0)
{
if ($text =~/^#Vote Kick$/i)
{
$client->Message(7, "Syntax: #Vote Kick <name> <reason>");
}
if ($text =~/^#Vote Kick /i)
{
$client->Message(0, "Vote kick start: $text");
}
}
return 1;
}

I made a minor change to the source to reverse how the "command not found" message is displayed via return to make it play better between multiple scripts. It doesn't actually do anything if displayed though and you can remove it by returning 1 from the command handler if it's found with latest git master.

Akkadius
01-16-2014, 05:24 PM
Thank you KLS for addressing this.

I am working on a Wiki where things like these can be shared in common place.

thepoetwarrior
01-17-2014, 07:44 PM
If its just a simple "Command not found" being displayed, then yeah I've gotten that too sometimes when trying to do #reloadquest to test a script. Seems the zone is bugged at that point and a simple reboot fixes it.

Source we're using is from September.

We can still use custom #commands in /say though, just sometimes require server reboot if we make a new command.

Kingly_Krab
01-18-2014, 06:02 AM
That doesn't seem to work. I have the following code in my global and I still get the error.
sub EVENT_SAY
{
if($text=~/#Test/i)
{
quest::shout("TEST!");
return 1;
}
}
http://i.imgur.com/wDFh4md.png

sub EVENT_SAY
{
if($text=~/#Test/i)
{
quest::shout("TEST!");
}
return 1;
}

http://i.imgur.com/FtYktpx.png

thepoetwarrior
01-18-2014, 10:58 PM
Not working for me too, certain zones and #commands seem to get that error message.

For now you can always remove the # in the command, and just make it /say test instead of /say #test

demonstar55
01-18-2014, 11:44 PM
Works here, #reloadquest seems to clobber it though

thepoetwarrior
01-19-2014, 06:27 AM
Works here, #reloadquest seems to clobber it though

Yes, I noticed that too.

Then after server reboots, and don't use #reloadquest, then it seems to work fine.