here are the changes in the HLSTATS_SERVER.PM
2 removals
915 lines
7 additions
921 lines
package HLstats_Server;
package HLstats_Server;
# HLstatsX Community Edition - Real-time player and clan rankings and statistics
# HLstatsX Community Edition - Real-time player and clan rankings and statistics
# Copyleft (L) 2008-20XX Nicholas Hastings (nshastings@gmail.com)
# Copyleft (L) 2008-20XX Nicholas Hastings (nshastings@gmail.com)
# http://www.hlxcommunity.com
# http://www.hlxcommunity.com
#
#
# HLstatsX Community Edition is a continuation of
# HLstatsX Community Edition is a continuation of
# ELstatsNEO - Real-time player and clan rankings and statistics
# ELstatsNEO - Real-time player and clan rankings and statistics
# Copyleft (L) 2008-20XX Malte Bayer (steam@neo-soft.org)
# Copyleft (L) 2008-20XX Malte Bayer (steam@neo-soft.org)
# http://ovrsized.neo-soft.org/
# http://ovrsized.neo-soft.org/
#
#
# ELstatsNEO is an very improved & enhanced - so called Ultra-Humongus Edition of HLstatsX
# ELstatsNEO is an very improved & enhanced - so called Ultra-Humongus Edition of HLstatsX
# HLstatsX - Real-time player and clan rankings and statistics for Half-Life 2
# HLstatsX - Real-time player and clan rankings and statistics for Half-Life 2
# http://www.hlstatsx.com/
# http://www.hlstatsx.com/
# Copyright (C) 2005-2007 Tobias Oetzel (Tobi@hlstatsx.com)
# Copyright (C) 2005-2007 Tobias Oetzel (Tobi@hlstatsx.com)
#
#
# HLstatsX is an enhanced version of HLstats made by Simon Garner
# HLstatsX is an enhanced version of HLstats made by Simon Garner
# HLstats - Real-time player and clan rankings and statistics for Half-Life
# HLstats - Real-time player and clan rankings and statistics for Half-Life
# http://sourceforge.net/projects/hlstats/
# http://sourceforge.net/projects/hlstats/
# Copyright (C) 2001 Simon Garner
# Copyright (C) 2001 Simon Garner
#
#
# This program is free software; you can redistribute it and/or
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
# of the License, or (at your option) any later version.
#
#
# This program is distributed in the hope that it will be useful,
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# GNU General Public License for more details.
#
#
# You should have received a copy of the GNU General Public License
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
#
# For support and installation notes visit http://www.hlxcommunity.com
# For support and installation notes visit http://www.hlxcommunity.com
use POSIX;
use POSIX;
use IO::Socket;
use IO::Socket;
use Socket;
use Socket;
use Encode;
use Encode;
use Syntax::Keyword::Try;
use Syntax::Keyword::Try;
do "$::opt_libdir/HLstats_GameConstants.plib";
do "$::opt_libdir/HLstats_GameConstants.plib";
sub new
sub new
{
{
my ($class_name, $serverId, $address, $port, $server_name, $rcon_pass, $game, $publicaddress, $gameengine, $realgame, $maxplayers) = @_;
my ($class_name, $serverId, $address, $port, $server_name, $rcon_pass, $game, $publicaddress, $gameengine, $realgame, $maxplayers) = @_;
my ($self) = {};
my ($self) = {};
bless($self, $class_name);
bless($self, $class_name);
$self->{id} = $serverId;
$self->{id} = $serverId;
$self->{address} = $address;
$self->{address} = $address;
$self->{port} = $port;
$self->{port} = $port;
$self->{game} = $game;
$self->{game} = $game;
$self->{rcon} = $rcon_pass;
$self->{rcon} = $rcon_pass;
$self->{srv_players} = ();
$self->{srv_players} = ();
# Game Engine
# Game Engine
# HL1 - 1
# HL1 - 1
# HL2 (original) - 2
# HL2 (original) - 2
# HL2ep2 ("OrangeBox") - 3
# HL2ep2 ("OrangeBox") - 3
$self->{game_engine} = $gameengine;
$self->{game_engine} = $gameengine;
$self->{rcon_obj} = undef;
$self->{rcon_obj} = undef;
$self->{name} = $server_name;
$self->{name} = $server_name;
$self->{auto_ban} = 0;
$self->{auto_ban} = 0;
$self->{contact} = "";
$self->{contact} = "";
$self->{hlstats_url} = "";
$self->{hlstats_url} = "";
$self->{publicaddress} = $publicaddress;
$self->{publicaddress} = $publicaddress;
$self->{play_game} = -1;
$self->{play_game} = -1;
$self->{last_event} = 0;
$self->{last_event} = 0;
$self->{last_check} = 0;
$self->{last_check} = 0;
$self->{lines} = 0;
$self->{lines} = 0;
$self->{map} = "";
$self->{map} = "";
$self->{numplayers} = 0;
$self->{numplayers} = 0;
$self->{numhumans} = 0;
$self->{num_trackable_players} = 0;
$self->{num_trackable_players} = 0;
$self->{minplayers} = 6;
$self->{minplayers} = 6;
$self->{maxplayers} = $maxplayers;
$self->{maxplayers} = $maxplayers;
$self->{difficulty} = 0;
$self->{difficulty} = 0;
$self->{players} = 0;
$self->{players} = 0;
$self->{rounds} = 0;
$self->{rounds} = 0;
$self->{kills} = 0;
$self->{kills} = 0;
$self->{suicides} = 0;
$self->{suicides} = 0;
$self->{headshots} = 0;
$self->{headshots} = 0;
$self->{ct_shots} = 0;
$self->{ct_shots} = 0;
$self->{ct_hits} = 0;
$self->{ct_hits} = 0;
$self->{ts_shots} = 0;
$self->{ts_shots} = 0;
$self->{ts_hits} = 0;
$self->{ts_hits} = 0;
$self->{bombs_planted} = 0;
$self->{bombs_planted} = 0;
$self->{bombs_defused} = 0;
$self->{bombs_defused} = 0;
$self->{ct_wins} = 0;
$self->{ct_wins} = 0;
$self->{ts_wins} = 0;
$self->{ts_wins} = 0;
$self->{map_started} = time();
$self->{map_started} = time();
$self->{map_changes} = 0;
$self->{map_changes} = 0;
$self->{map_rounds} = 0;
$self->{map_rounds} = 0;
$self->{map_ct_wins} = 0;
$self->{map_ct_wins} = 0;
$self->{map_ts_wins} = 0;
$self->{map_ts_wins} = 0;
$self->{map_ct_shots} = 0;
$self->{map_ct_shots} = 0;
$self->{map_ct_hits} = 0;
$self->{map_ct_hits} = 0;
$self->{map_ts_shots} = 0;
$self->{map_ts_shots} = 0;
$self->{map_ts_hits} = 0;
$self->{map_ts_hits} = 0;
# team balancer
# team balancer
$self->{ba_enabled} = 0;
$self->{ba_enabled} = 0;
$self->{ba_ct_wins} = 0;
$self->{ba_ct_wins} = 0;
$self->{ba_ts_win} = 0;
$self->{ba_ts_win} = 0;
$self->{ba_ct_frags} = 0;
$self->{ba_ct_frags} = 0;
$self->{ba_ts_frags} = 0;
$self->{ba_ts_frags} = 0;
$self->{ba_winner} = ();
$self->{ba_winner} = ();
$self->{ba_map_rounds} = 0;
$self->{ba_map_rounds} = 0;
$self->{ba_last_swap} = 0;
$self->{ba_last_swap} = 0;
$self->{ba_player_switch} = 0; # player switched on his own
$self->{ba_player_switch} = 0; # player switched on his own
# Messaging commands
# Messaging commands
$self->{show_stats} = 0;
$self->{show_stats} = 0;
$self->{broadcasting_events} = 0;
$self->{broadcasting_events} = 0;
$self->{broadcasting_player_actions} = 0;
$self->{broadcasting_player_actions} = 0;
$self->{broadcasting_command} = "";
$self->{broadcasting_command} = "";
$self->{broadcasting_command_announce} = "say";
$self->{broadcasting_command_announce} = "say";
$self->{player_events} = 1;
$self->{player_events} = 1;
$self->{player_command} = "say";
$self->{player_command} = "say";
$self->{player_command_osd} = "";
$self->{player_command_osd} = "";
$self->{player_command_hint} = "";
$self->{player_command_hint} = "";
$self->{player_admin_command} = 0;
$self->{player_admin_command} = 0;
$self->{default_display_events} = 1;
$self->{default_display_events} = 1;
$self->{browse_command} = "";
$self->{browse_command} = "";
$self->{swap_command} = "";
$self->{swap_command} = "";
$self->{exec_command} = "";
$self->{exec_command} = "";
$self->{global_chat_command} = "say";
$self->{global_chat_command} = "say";
# Message format operators
# Message format operators
$self->{format_color} = "";
$self->{format_color} = "";
$self->{format_action} = "";
$self->{format_action} = "";
$self->{format_actionend} = "";
$self->{format_actionend} = "";
$self->{total_kills} = 0;
$self->{total_kills} = 0;
$self->{total_headshots} = 0;
$self->{total_headshots} = 0;
$self->{total_suicides} = 0;
$self->{total_suicides} = 0;
$self->{total_rounds} = 0;
$self->{total_rounds} = 0;
$self->{total_shots} = 0;
$self->{total_shots} = 0;
$self->{total_hits} = 0;
$self->{total_hits} = 0;
$self->{track_server_load} = 0;
$self->{track_server_load} = 0;
$self->{track_server_timestamp} = 0;
$self->{track_server_timestamp} = 0;
$self->{ignore_nextban} = ();
$self->{ignore_nextban} = ();
$self->{use_browser} = 0;
$self->{use_browser} = 0;
$self->{round_status} = 0;
$self->{round_status} = 0;
$self->{min_players_rank} = 1;
$self->{min_players_rank} = 1;
$self->{admins} = ();
$self->{admins} = ();
$self->{ignore_bots} = 1;
$self->{ignore_bots} = 1;
$self->{tk_penalty} = 0;
$self->{tk_penalty} = 0;
$self->{suicide_penalty} = 0;
$self->{suicide_penalty} = 0;
$self->{skill_mode} = 0;
$self->{skill_mode} = 0;
$self->{game_type} = 0;
$self->{game_type} = 0;
$self->{bonusroundignore} = 0;
$self->{bonusroundignore} = 0;
$self->{bonusroundtime} = 0;
$self->{bonusroundtime} = 0;
$self->{bonusroundtime_ts} = 0;
$self->{bonusroundtime_ts} = 0;
$self->{bonusroundtime_state} = 0;
$self->{bonusroundtime_state} = 0;
$self->{lastdisabledbonus} = $::ev_unixtime;
$self->{lastdisabledbonus} = $::ev_unixtime;
$self->{mod} = "";
$self->{mod} = "";
$self->{switch_admins} = 0;
$self->{switch_admins} = 0;
$self->{public_commands} = 1;
$self->{public_commands} = 1;
$self->{connect_announce} = 0;
$self->{connect_announce} = 0;
$self->{update_hostname} = 0;
$self->{update_hostname} = 0;
$self->{lastblueflagdefend} = 0;
$self->{lastblueflagdefend} = 0;
$self->{lastredflagdefend} = 0;
$self->{lastredflagdefend} = 0;
# location hax
# location hax
$self->{nextkillx} = "";
$self->{nextkillx} = "";
$self->{nextkilly} = "";
$self->{nextkilly} = "";
$self->{nextkillz} = "";
$self->{nextkillz} = "";
$self->{nextkillvicx} = "";
$self->{nextkillvicx} = "";
$self->{nextkillvicy} = "";
$self->{nextkillvicy} = "";
$self->{nextkillvicz} = "";
$self->{nextkillvicz} = "";
$self->{nextkillheadshot} = 0;
$self->{nextkillheadshot} = 0;
$self->{next_timeout} = 0;
$self->{next_timeout} = 0;
$self->{next_flush} = 0;
$self->{next_flush} = 0;
$self->{next_plyr_flush} = 0;
$self->{next_plyr_flush} = 0;
$self->{needsupdate} = 0;
$self->{needsupdate} = 0;
$self->set_play_game($realgame);
$self->set_play_game($realgame);
if ($self->{rcon})
if ($self->{rcon})
{
{
$self->init_rcon();
$self->init_rcon();
}
}
$self->updateDB();
$self->updateDB();
$self->update_server_loc();
$self->update_server_loc();
return $self;
return $self;
}
}
sub set_play_game
sub set_play_game
{
{
my ($self, $realgame) = @_;
my ($self, $realgame) = @_;
if (exists($gamecode_to_game{$realgame}))
if (exists($gamecode_to_game{$realgame}))
{
{
$self->{play_game} = $gamecode_to_game{$realgame};
$self->{play_game} = $gamecode_to_game{$realgame};
}
}
}
}
sub is_admin
sub is_admin
{
{
my($self, $steam_id) = @_;
my($self, $steam_id) = @_;
for (@{$self->{admins}}) {
for (@{$self->{admins}}) {
if ($_ eq $steam_id) {
if ($_ eq $steam_id) {
return 1;
return 1;
}
}
}
}
return 0;
return 0;
}
}
sub get_game_mod_opts
sub get_game_mod_opts
{
{
# Runs immediately after server object is created and options are loaded.
# Runs immediately after server object is created and options are loaded.
my($self) = @_;
my($self) = @_;
if ($self->{mod} ne "") {
if ($self->{mod} ne "") {
my $mod = $self->{mod};
my $mod = $self->{mod};
if ($mod eq "SOURCEMOD") {
if ($mod eq "SOURCEMOD") {
$self->{browse_command} = "hlx_sm_browse";
$self->{browse_command} = "hlx_sm_browse";
$self->{swap_command} = "hlx_sm_swap";
$self->{swap_command} = "hlx_sm_swap";
$self->{global_chat_command} = "hlx_sm_psay";
$self->{global_chat_command} = "hlx_sm_psay";
$self->setHlxCvars();
$self->setHlxCvars();
} elsif ($mod eq "MANI") {
} elsif ($mod eq "MANI") {
$self->{browse_command} = "ma_hlx_browse";
$self->{browse_command} = "ma_hlx_browse";
$self->{swap_command} = "ma_swapteam";
$self->{swap_command} = "ma_swapteam";
$self->{exec_command} = "ma_cexec";
$self->{exec_command} = "ma_cexec";
$self->{global_chat_command} = "ma_psay";
$self->{global_chat_command} = "ma_psay";
} elsif ($mod eq "AMXX") {
} elsif ($mod eq "AMXX") {
$self->{browse_command} = "hlx_amx_browse";
$self->{browse_command} = "hlx_amx_browse";
$self->{swap_command} = "hlx_amx_swap";
$self->{swap_command} = "hlx_amx_swap";
$self->{global_chat_command} = "hlx_amx_psay";
$self->{global_chat_command} = "hlx_amx_psay";
$self->setHlxCvars();
$self->setHlxCvars();
} elsif ($mod eq "BEETLE") {
} elsif ($mod eq "BEETLE") {
$self->{browse_command} = "hlx_browse";
$self->{browse_command} = "hlx_browse";
$self->{swap_command} = "hlx_swap";
$self->{swap_command} = "hlx_swap";
$self->{exec_command} = "hlx_exec";
$self->{exec_command} = "hlx_exec";
$self->{global_chat_command} = "admin_psay";
$self->{global_chat_command} = "admin_psay";
} elsif ($mod eq "MINISTATS") {
} elsif ($mod eq "MINISTATS") {
$self->{browse_command} = "ms_browse";
$self->{browse_command} = "ms_browse";
$self->{swap_command} = "ms_swap";
$self->{swap_command} = "ms_swap";
$self->{global_chat_command} = "ms_psay";
$self->{global_chat_command} = "ms_psay";
}
}
# Turn on color and add game-specific color modifiers for when using hlx:ce sourcemod plugin
# Turn on color and add game-specific color modifiers for when using hlx:ce sourcemod plugin
if (($self->{mod} eq "SOURCEMOD" &&
if (($self->{mod} eq "SOURCEMOD" &&
(
(
$self->{play_game} == CSS()
$self->{play_game} == CSS()
|| $self->{play_game} == TF()
|| $self->{play_game} == TF()
|| $self->{play_game} == INSURGENCY()
|| $self->{play_game} == L4D()
|| $self->{play_game} == L4D()
|| $self->{play_game} == DODS()
|| $self->{play_game} == DODS()
|| $self->{play_game} == HL2MP()
|| $self->{play_game} == HL2MP()
|| $self->{play_game} == AOC()
|| $self->{play_game} == AOC()
|| $self->{play_game} == ZPS()
|| $self->{play_game} == ZPS()
|| $self->{play_game} == FF()
|| $self->{play_game} == FF()
|| $self->{play_game} == GES()
|| $self->{play_game} == GES()
|| $self->{play_game} == FOF()
|| $self->{play_game} == FOF()
|| $self->{play_game} == PVKII()
|| $self->{play_game} == PVKII()
|| $self->{play_game} == CSP()
|| $self->{play_game} == CSP()
|| $self->{play_game} == NUCLEARDAWN()
|| $self->{play_game} == NUCLEARDAWN()
|| $self->{play_game} == DDD()
|| $self->{play_game} == DDD()
)
)
)
)
|| ($self->{mod} eq "AMXX"
|| ($self->{mod} eq "AMXX"
&& $self->{play_game} == CSTRIKE())
&& $self->{play_game} == CSTRIKE())
) {
) {
$self->{format_color} = " 1";
$self->{format_color} = " 1";
if ($self->{play_game} == ZPS() || $self->{play_game} == GES()) {
if ($self->{play_game} == ZPS() || $self->{play_game} == GES()) {
$self->{format_action} = "\x05";
$self->{format_action} = "\x05";
} elsif ($self->{play_game} == FF()) {
} elsif ($self->{play_game} == FF()) {
$self->{format_action} = "^4";
$self->{format_action} = "^4";
} else {
} else {
$self->{format_action} = "\x04";
$self->{format_action} = "\x04";
}
}
if ($self->{play_game} == FF()) {
if ($self->{play_game} == FF()) {
$self->{format_actionend} = "^0";
$self->{format_actionend} = "^0";
} else {
} else {
$self->{format_actionend} = "\x01";
$self->{format_actionend} = "\x01";
}
}
}
}
# Insurgency can only do one solid color afaik. The rest is handled in the plugin
# Insurgency can only do one solid color afaik. The rest is handled in the plugin
if ($self->{mod} eq "SOURCEMOD" && $self->{play_game} == INSMOD()) {
if ($self->{mod} eq "SOURCEMOD" && $self->{play_game} == INSMOD()) {
$self->{format_color} = " 1";
$self->{format_color} = " 1";
}
}
}
}
}
}
sub format_userid {
sub format_userid {
my($self, $userid) = @_;
my($self, $userid) = @_;
if ($self->{mod} eq "AMXX") {
if ($self->{mod} eq "AMXX") {
return "#".$userid;
return "#".$userid;
}
}
return "\"".$userid."\"";
return "\"".$userid."\"";
}
}
sub quoteparam {
sub quoteparam {
my($self, $message) = @_;
my($self, $message) = @_;
$message =~ s/'/ ' /g;
$message =~ s/'/ ' /g;
$message =~ s/"/ '' /g;
$message =~ s/"/ '' /g;
if (($self->{game_engine} != 2 || $self->{mod} eq "SOURCEMOD") && $self->{mod} ne "MANI") {
if (($self->{game_engine} != 2 || $self->{mod} eq "SOURCEMOD") && $self->{mod} ne "MANI") {
return "\"".$message."\"";
return "\"".$message."\"";
}
}
return $message;
return $message;
}
}
#
#
# Set property 'key' to 'value'
# Set property 'key' to 'value'
#
#
sub set
sub set
{
{
my ($self, $key, $value) = @_;
my ($self, $key, $value) = @_;
if (defined($self->{$key}))
if (defined($self->{$key}))
{
{
if ($self->{$key} eq $value)
if ($self->{$key} eq $value)
{
{
if ($::g_debug > 2)
if ($::g_debug > 2)
{
{
&::printNotice("Hlstats_Server->set ignored: Value of \"$key\" is already \"$value\"");
&::printNotice("Hlstats_Server->set ignored: Value of \"$key\" is already \"$value\"");
}
}
return 0;
return 0;
}
}
$self->{$key} = $value;
$self->{$key} = $value;
if ($key eq "hlstats_url") {
if ($key eq "hlstats_url") {
# so ingame browsing will work correctly
# so ingame browsing will work correctly
$self->{ingame_url} = $value;
$self->{ingame_url} = $value;
$self->{ingame_url} =~ s/\/hlstats.php//i;
$self->{ingame_url} =~ s/\/hlstats.php//i;
$self->{ingame_url} =~ s/\/$//;
$self->{ingame_url} =~ s/\/$//;
&::printEvent("SERVER", "Ingame-URL: ".$self->{ingame_url}, 1);
&::printEvent("SERVER", "Ingame-URL: ".$self->{ingame_url}, 1);
}
}
return 1;
return 1;
}
}
else
else
{
{
warn("HLstats_Server->set: \"$key\" is not a valid property name\n");
warn("HLstats_Server->set: \"$key\" is not a valid property name\n");
return 0;
return 0;
}
}
}
}
#
#
# Increment (or decrement) the value of 'key' by 'amount' (or 1 by default)
# Increment (or decrement) the value of 'key' by 'amount' (or 1 by default)
#
#
sub increment
sub increment
{
{
my ($self, $key, $amount) = @_;
my ($self, $key, $amount) = @_;
if ($amount) {
if ($amount) {
$amount = int($amount);
$amount = int($amount);
} else {
} else {
$amount = 1
$amount = 1
}
}
my $value = $self->{$key};
my $value = $self->{$key};
$self->set($key, $value + $amount);
$self->set($key, $value + $amount);
}
}
sub init_rcon
sub init_rcon
{
{
my ($self) = @_;
my ($self) = @_;
my $server_ip = $self->{address};
my $server_ip = $self->{address};
my $server_port = $self->{port};
my $server_port = $self->{port};
my $rcon_pass = $self->{rcon};
my $rcon_pass = $self->{rcon};
my $game = $self->{game};
my $game = $self->{game};
if ($::g_rcon && $rcon_pass) {
if ($::g_rcon && $rcon_pass) {
if ($self->{game_engine} == 1) {
if ($self->{game_engine} == 1) {
$self->{rcon_obj} = new BASTARDrcon($self);
$self->{rcon_obj} = new BASTARDrcon($self);
} else {
} else {
$self->{rcon_obj} = new TRcon($self);
$self->{rcon_obj} = new TRcon($self);
}
}
}
}
if ($self->{rcon_obj}) {
if ($self->{rcon_obj}) {
&::printEvent ("SERVER", "Connecting to rcon on $server_ip:$server_port ... ok");
&::printEvent ("SERVER", "Connecting to rcon on $server_ip:$server_port ... ok");
#&::printEvent("SERVER", "Server running game: ".$self->{play_game}, 1);
#&::printEvent("SERVER", "Server running game: ".$self->{play_game}, 1);
&::printEvent("SERVER", "Server running map: ".$self->get_map(), 1);
&::printEvent("SERVER", "Server running map: ".$self->get_map(), 1);
if ($::g_mode eq "LAN") {
if ($::g_mode eq "LAN") {
$self->get_lan_players();
$self->get_lan_players();
}
}
}
}
}
}
sub dorcon
sub dorcon
{
{
my ($self, $command) = @_;
my ($self, $command) = @_;
my $result;
my $result;
my $rcon_obj = $self->{rcon_obj};
my $rcon_obj = $self->{rcon_obj};
if (($rcon_obj) && ($::g_rcon == 1) && ($self->{rcon} ne "")) {
if (($rcon_obj) && ($::g_rcon == 1) && ($self->{rcon} ne "")) {
# replace ; to avoid executing multiple rcon commands.
# replace ; to avoid executing multiple rcon commands.
$command =~ s/;//g;
$command =~ s/;//g;
&::printNotice("RCON", $command, 1);
&::printNotice("RCON", $command, 1);
$result = $rcon_obj->execute($command);
$result = $rcon_obj->execute($command);
} else {
} else {
&::printNotice("Rcon error: No Object available");
&::printNotice("Rcon error: No Object available");
}
}
return $result;
return $result;
}
}
sub dorcon_multi
sub dorcon_multi
{
{
my ($self, @commands) = @_;
my ($self, @commands) = @_;
my $result;
my $result;
my $rcon_obj = $self->{rcon_obj};
my $rcon_obj = $self->{rcon_obj};
if (($rcon_obj) && ($::g_rcon == 1) && ($self->{rcon} ne "")) {
if (($rcon_obj) && ($::g_rcon == 1) && ($self->{rcon} ne "")) {
if ($self->{game_engine} > 1)
if ($self->{game_engine} > 1)
{
{
my $fullcmd = "";
my $fullcmd = "";
foreach (@commands)
foreach (@commands)
{
{
# replace ; to avoid executing multiple rcon commands.
# replace ; to avoid executing multiple rcon commands.
my $cmd = $_;
my $cmd = $_;
$cmd =~ s/;//g;
$cmd =~ s/;//g;
$fullcmd .="$cmd;";
$fullcmd .="$cmd;";
}
}
&::printNotice("RCON", $fullcmd, 1);
&::printNotice("RCON", $fullcmd, 1);
$result = $rcon_obj->execute($fullcmd);
$result = $rcon_obj->execute($fullcmd);
}
}
else
else
{
{
foreach (@commands)
foreach (@commands)
{
{
&::printNotice("RCON", $_, 1);
&::printNotice("RCON", $_, 1);
$result = $rcon_obj->execute($_);
$result = $rcon_obj->execute($_);
}
}
}
}
} else {
} else {
&::printNotice("Rcon error: No Object available");
&::printNotice("Rcon error: No Object available");
}
}
return $result;
return $result;
}
}
sub rcon_getaddress
sub rcon_getaddress
{
{
my ($self, $uniqueid) = @_;
my ($self, $uniqueid) = @_;
my $result;
my $result;
my $rcon_obj = $self->{rcon_obj};
my $rcon_obj = $self->{rcon_obj};
if (($rcon_obj) && ($::g_rcon == 1) && ($self->{rcon} ne ""))
if (($rcon_obj) && ($::g_rcon == 1) && ($self->{rcon} ne ""))
{
{
$result = $rcon_obj->getPlayer($uniqueid);
$result = $rcon_obj->getPlayer($uniqueid);
}
}
else
else
{
{
&::printNotice("Rcon error: No Object available");
&::printNotice("Rcon error: No Object available");
}
}
return $result;
return $result;
}
}
sub rcon_getStatus
sub rcon_getStatus
{
{
my ($self) = @_;
my ($self) = @_;
my $rcon_obj = $self->{rcon_obj};
my $rcon_obj = $self->{rcon_obj};
my $map_result = "";
my $map_result = "";
my $max_player_result = -1;
my $max_player_result = -1;
my $servhostname = "";
my $servhostname = "";
my $difficulty = 0;
my $difficulty = 0;
if (($rcon_obj) && ($::g_rcon == 1) && ($self->{rcon} ne "")) {
if (($rcon_obj) && ($::g_rcon == 1) && ($self->{rcon} ne "")) {
($servhostname, $map_result, $max_player_result, $difficulty) = $rcon_obj->getServerData();
($servhostname, $map_result, $max_player_result, $difficulty) = $rcon_obj->getServerData();
($visible_maxplayers) = $rcon_obj->getVisiblePlayers();
($visible_maxplayers) = $rcon_obj->getVisiblePlayers();
if (($visible_maxplayers != -1) && ($visible_maxplayers < $max_player_result)) {
if (($visible_maxplayers != -1) && ($visible_maxplayers < $max_player_result)) {
$max_player_result = $visible_maxplayers;
$max_player_result = $visible_maxplayers;
}
}
} else {
} else {
&::printNotice("Rcon error: No Object available");
&::printNotice("Rcon error: No Object available");
}
}
return ($map_result, $max_player_result, $servhostname, $difficulty);
return ($map_result, $max_player_result, $servhostname, $difficulty);
}
}
sub rcon_getplayers
sub rcon_getplayers
{
{
my ($self) = @_;
my ($self) = @_;
my %result;
my %result;
my $rcon_obj = $self->{rcon_obj};
my $rcon_obj = $self->{rcon_obj};
if (($rcon_obj) && ($::g_rcon == 1) && ($self->{rcon} ne ""))
if (($rcon_obj) && ($::g_rcon == 1) && ($self->{rcon} ne ""))
{
{
%result = $rcon_obj->getPlayers();
%result = $rcon_obj->getPlayers();
} else {
} else {
&::printNotice("Rcon error: No Object available");
&::printNotice("Rcon error: No Object available");
}
}
return %result;
return %result;
}
}
sub track_server_load
sub track_server_load
{
{
my ($self) = @_;
my ($self) = @_;
if (($::g_stdin == 0) && ($self->{track_server_load} > 0))
if (($::g_stdin == 0) && ($self->{track_server_load} > 0))
{
{
my $last_timestamp = $self->{track_server_timestamp};
my $last_timestamp = $self->{track_server_timestamp};
my $new_timestamp = time();
my $new_timestamp = time();
if ($last_timestamp > 0)
if ($last_timestamp > 0)
{
{
if ($last_timestamp+299 < $new_timestamp)
if ($last_timestamp+299 < $new_timestamp)
{
{
# fetch fps and uptime via rcon
# fetch fps and uptime via rcon
# Old style stats output:
# Old style stats output:
#$string = " 0.00 0.00 0.00 54 1 249.81 0 dhjdsk";
#$string = " 0.00 0.00 0.00 54 1 249.81 0 dhjdsk";
# New style stats output:
# New style stats output:
#CPU In (KB/s) Out (KB/s) Uptime Map changes FPS Players Connects
#CPU In (KB/s) Out (KB/s) Uptime Map changes FPS Players Connects
#0.00 0.00 0.00 0 0 00.00 0 0
#0.00 0.00 0.00 0 0 00.00 0 0
$string = $self->dorcon("stats");
$string = $self->dorcon("stats");
# Remove first line of output
# Remove first line of output
$string =~ /CPU.*\n(.*)\n*L{0,1}.*\Z/;
$string =~ /CPU.*\n(.*)\n*L{0,1}.*\Z/;
$string = $1;
$string = $1;
# Grab FPS and Uptime from the output
# Grab FPS and Uptime from the output
$string =~ /([^ ]+)\s+([^ ]+)\s+([^ ]+)\s+([^ ]+)\s+([^ ]+)\s+([^ ]+)\s+([^ ]+)\s*([^ ]*)/;
$string =~ /([^ ]+)\s+([^ ]+)\s+([^ ]+)\s+([^ ]+)\s+([^ ]+)\s+([^ ]+)\s+([^ ]+)\s*([^ ]*)/;
$uptime = $4;
$uptime = $4;
$fps = $6;
$fps = $6;
my $act_players = $self->{numplayers};
my $act_players = $self->{numplayers};
my $max_players = $self->{maxplayers};
my $max_players = $self->{maxplayers};
if ($max_players > 0) {
if ($max_players > 0) {
if ($act_players > $max_players) {
if ($act_players > $max_players) {
$act_players = $max_players;
$act_players = $max_players;
}
}
}
}
&::execCached("flush_server_load",
&::execCached("flush_server_load",
"INSERT IGNORE INTO hlstats_server_load
"INSERT IGNORE INTO hlstats_server_load
SET
SET
server_id=?,
server_id=?,
timestamp=?,
timestamp=?,
act_players=?,
act_players=?,
min_players=?,
min_players=?,
max_players=?,
max_players=?,
map=?,
map=?,
uptime=?,
uptime=?,
fps=?",
fps=?",
$self->{id},
$self->{id},
$new_timestamp,
$new_timestamp,
$act_players,
$act_players,
$self->{minplayers},
$self->{minplayers},
$max_players,
$max_players,
$self->{map},
$self->{map},
(($uptime)?$uptime:0),
(($uptime)?$uptime:0),
(($fps)?$fps:0)
(($fps)?$fps:0)
);
);
$self->set("track_server_timestamp", $new_timestamp);
$self->set("track_server_timestamp", $new_timestamp);
&::printEvent("SERVER", "Insert new server load timestamp", 1);
&::printEvent("SERVER", "Insert new server load timestamp", 1);
}
}
} else {
} else {
$self->set("track_server_timestamp", $new_timestamp);
$self->set("track_server_timestamp", $new_timestamp);
}
}
}
}
}
}
sub dostats
sub dostats
{
{
my ($self) = @_;
my ($self) = @_;
my $rcon_obj = $self->{rcon_obj};
my $rcon_obj = $self->{rcon_obj};
$rcmd = $self->{broadcasting_command_announce};
$rcmd = $self->{broadcasting_command_announce};
if (($::g_stdin == 0) && ($rcon_obj) && ($self->{rcon} ne ""))
if (($::g_stdin == 0) && ($rcon_obj) && ($self->{rcon} ne ""))
{
{
if ($self->{broadcasting_events} == 1)
if ($self->{broadcasting_events} == 1)
{
{
my $hpk = sprintf("%.0f", 0);
my $hpk = sprintf("%.0f", 0);
if ($self->{total_kills} > 0) {
if ($self->{total_kills} > 0) {
$hpk = sprintf("%.2f", (100/$self->{total_kills})*$self->{total_headshots});
$hpk = sprintf("%.2f", (100/$self->{total_kills})*$self->{total_headshots});
}
}
if ($rcmd ne "") {
if ($rcmd ne "") {
$self->dorcon("$rcmd ".$self->quoteparam("HLstatsX:CE - Tracking ".&::number_format($self->{players})." players with ".&::number_format($self->{total_kills})." kills and ".&::number_format($self->{total_headshots})." headshots ($hpk%)"));
$self->dorcon("$rcmd ".$self->quoteparam("HLstatsX:CE - Tracking ".&::number_format($self->{players})." players with ".&::number_format($self->{total_kills})." kills and ".&::number_format($self->{total_headshots})." headshots ($hpk%)"));
} else {
} else {
$self->messageAll("HLstatsX:CE - Tracking ".&::number_format($self->{players})." players with ".&::number_format($self->{total_kills})." kills and ".&::number_format($self->{total_headshots})." headshots ($hpk%)");
$self->messageAll("HLstatsX:CE - Tracking ".&::number_format($self->{players})." players with ".&::number_format($self->{total_kills})." kills and ".&::number_format($self->{total_headshots})." headshots ($hpk%)");
}
}
}
}
}
}
}
}
sub get_map
sub get_map
{
{
my ($self, $fromupdate) = @_;
my ($self, $fromupdate) = @_;
if ($::g_stdin == 0) {
if ($::g_stdin == 0) {
if ((time() - $self->{last_check})>120) {
if ((time() - $self->{last_check})>120) {
$self->{last_check} = time();
$self->{last_check} = time();
&::printNotice("get_rcon_status");
&::printNotice("get_rcon_status");
my $temp_map = "";
my $temp_map = "";
my $temp_maxplayers = -1;
my $temp_maxplayers = -1;
my $servhostname = "";
my $servhostname = "";
my $difficulty = 0;
my $difficulty = 0;
my $update = 0;
my $update = 0;
if ($self->{rcon_obj})
if ($self->{rcon_obj})
{
{
($temp_map, $temp_maxplayers, $servhostname, $difficulty) = $self->rcon_getStatus();
($temp_map, $temp_maxplayers, $servhostname, $difficulty) = $self->rcon_getStatus();
if ($temp_map eq "") {
if ($temp_map eq "") {
goto STATUSFAIL;
goto STATUSFAIL;
}
}
if ($self->{map} ne $temp_map) {
if ($self->{map} ne $temp_map) {
$self->{map} = $temp_map;
$self->{map} = $temp_map;
$update++;
$update++;
}
}
if (($temp_maxplayers != -1) && ($temp_maxplayers > 0) && ($temp_maxplayers ne "")) {
if (($temp_maxplayers != -1) && ($temp_maxplayers > 0) && ($temp_maxplayers ne "")) {
if ($self->{maxplayers} != $temp_maxplayers) {
if ($self->{maxplayers} != $temp_maxplayers) {
$self->{maxplayers} = $temp_maxplayers;
$self->{maxplayers} = $temp_maxplayers;
$update++;
$update++;
}
}
}
}
if (($difficulty > 0) && ($self->{play_game} == L4D())) {
if (($difficulty > 0) && ($self->{play_game} == L4D())) {
$self->{difficulty} = $difficulty;
$self->{difficulty} = $difficulty;
}
}
if (($self->{update_hostname} > 0) && ($self->{name} ne $servhostname) && ($servhostname ne "")) {
if (($self->{update_hostname} > 0) && ($self->{name} ne $servhostname) && ($servhostname ne "")) {
$self->{name} = $servhostname;
$self->{name} = $servhostname;
$update++;
$update++;
}
}
}
}
else
else
{ # no rcon or status command failed
{ # no rcon or status command failed
STATUSFAIL:
STATUSFAIL:
my ($querymap, $queryhost, $querymax) = &::queryServer($self->{address}, $self->{port}, 'mapname', 'hostname', 'maxplayers');
my ($querymap, $queryhost, $querymax) = &::queryServer($self->{address}, $self->{port}, 'mapname', 'hostname', 'maxplayers');
if ($querymap ne "") {
if ($querymap ne "") {
$self->{map} = $querymap;
$self->{map} = $querymap;
$update++;
$update++;
#if map is blank, query likely failed as a whole
#if map is blank, query likely failed as a whole
if (($querymax != -1) && ($querymax > 0)) {
if (($querymax != -1) && ($querymax > 0)) {
if ($self->{maxplayers} != $querymax) {
if ($self->{maxplayers} != $querymax) {
$self->{maxplayers} = $querymax;
$self->{maxplayers} = $querymax;
$update++;
$update++;
}
}
}
}
if ($self->{update_hostname} > 0 && $queryhost ne "" && $self->{name} ne $queryhost) {
if ($self->{update_hostname} > 0 && $queryhost ne "" && $self->{name} ne $queryhost) {
$self->{name} = $queryhost;
$self->{name} = $queryhost;
$update++;
$update++;
}
}
}
}
}
}
if ($update > 0 && $fromupdate == 0) {
if ($update > 0 && $fromupdate == 0) {
$self->updateDB();
$self->updateDB();
}
}
&::printNotice("get_rcon_status successfully");
&::printNotice("get_rcon_status successfully");
}
}
}
}
return $self->{map};
return $self->{map};
}
}
sub update_players_pings
sub update_players_pings
{
{
my ($self) = @_;
my ($self) = @_;
if ($self->{num_trackable_players} < $self->{minplayers})
if ($self->{num_trackable_players} < $self->{minplayers})
{
{
&::printNotice("(IGNORED) NOTMINPLAYERS: Update_player_pings");
&::printNotice("(IGNORED) NOTMINPLAYERS: Update_player_pings");
}
}
else
else
{
{
&::printNotice("update_player_pings");
&::printNotice("update_player_pings");
&::printEvent("RCON", "Update Player pings", 1);
&::printEvent("RCON", "Update Player pings", 1);
my %players = $self->rcon_getplayers();
my %players = $self->rcon_getplayers();
while ( my($pl, $player) = each(%{$self->{srv_players}}) )
while ( my($pl, $player) = each(%{$self->{srv_players}}) )
{
{
my $uniqueid = $player->{uniqueid};
my $uniqueid = $player->{uniqueid};
if (defined($players{$uniqueid}))
if (defined($players{$uniqueid}))
{
{
if ($player->{is_bot} == 0 && $player->{userid} > 0) {
if ($player->{is_bot} == 0 && $player->{userid} > 0) {
my $ping = $players{$uniqueid}->{"Ping"};
my $ping = $players{$uniqueid}->{"Ping"};
$player->set("ping", $ping);
$player->set("ping", $ping);
if ($ping > 0) {
if ($ping > 0) {
&::recordEvent(
&::recordEvent(
"Latency", 0,
"Latency", 0,
$player->{playerid},
$player->{playerid},
$ping
$ping
);
);
}
}
}
}
}
}
}
}
&::printNotice("update_player_pings successfully");
&::printNotice("update_player_pings successfully");
}
}
}
}
sub get_lan_players
sub get_lan_players
{
{
my ($self) = @_;
my ($self) = @_;
if ($::g_mode eq "LAN") {
if ($::g_mode eq "LAN") {
&::printNotice("get_lan_players");
&::printNotice("get_lan_players");
&::printEvent("RCON", "Get LAN players", 1);
&::printEvent("RCON", "Get LAN players", 1);
my %players = $self->rcon_getplayers();
my %players = $self->rcon_getplayers();
while ( my($p_uid, $p_obj) = each(%players) )
while ( my($p_uid, $p_obj) = each(%players) )
{
{
my $srv_addr = $self->{address}.":".$self->{port};
my $srv_addr = $self->{address}.":".$self->{port};
my $userid = $p_obj->{"UserID"};
my $userid = $p_obj->{"UserID"};
my $name = $p_obj->{"Name"};
my $name = $p_obj->{"Name"};
my $address = $p_obj->{"Address"};
my $address = $p_obj->{"Address"};
::g_lan_noplayerinfo->{"$srv_addr/$userid/$name"} = {
::g_lan_noplayerinfo->{"$srv_addr/$userid/$name"} = {
ipaddress => $address,
ipaddress => $address,
userid => $userid,
userid => $userid,
name => $name,
name => $name,
server => $srv_addr
server => $srv_addr
};
};
}
}
&::printNotice("get_lan_players successfully");
&::printNotice("get_lan_players successfully");
}
}
}
}
sub clear_winner
sub clear_winner
{
{
my ($self) = @_;
my ($self) = @_;
&::printNotice("clear_winner");
&::printNotice("clear_winner");
@{$self->{winner}} = ();
@{$self->{winner}} = ();
}
}
sub add_round_winner
sub add_round_winner
{
{
my ($self, $team) = @_;
my ($self, $team) = @_;
&::printNotice("add_round_winner");
&::printNotice("add_round_winner");
$self->{winner}[($self->{map_rounds} % 7)] = $team;
$self->{winner}[($self->{map_rounds} % 7)] = $team;
$self->increment("ba_map_rounds");
$self->increment("ba_map_rounds");
$self->increment("map_rounds");
$self->increment("map_rounds");
$self->increment("rounds");
$self->increment("rounds");
$self->increment("total_rounds");
$self->increment("total_rounds");
$self->{ba_ct_wins} = 0;
$self->{ba_ct_wins} = 0;
$self->{ba_ts_wins} = 0;
$self->{ba_ts_wins} = 0;
for (@{$self->{winner}})
for (@{$self->{winner}})
{
{
if ($_ eq "ct") {
if ($_ eq "ct") {
$self->increment("ba_ct_wins");
$self->increment("ba_ct_wins");
} elsif ($_ eq "ts") {
} elsif ($_ eq "ts") {
$self->increment("ba_ts_wins");
$self->increment("ba_ts_wins");
}
}
}
}
}
}
sub switch_player
sub switch_player
{
{
my ($self, $playerid, $name) = @_;
my ($self, $playerid, $name) = @_;
my $rcmd = $self->{player_command_hint};
my $rcmd = $self->{player_command_hint};
$self->dorcon($self->{swap_command}." ".$self->format_userid($playerid));
$self->dorcon($self->{swap_command}." ".$self->format_userid($playerid));
if ($self->{player_command_hint} eq "") {
if ($self->{player_command_hint} eq "") {
$rcmd = $self->{player_command};
$rcmd = $self->{player_command};
}
}
$self->dorcon(sprintf("%s %s %s", $rcmd, $self->format_userid($playerid), $self->quoteparam("HLstatsX:CE - You were switched to balance teams")));
$self->dorcon(sprintf("%s %s %s", $rcmd, $self->format_userid($playerid), $self->quoteparam("HLstatsX:CE - You were switched to balance teams")));
if ($self->{player_admin_command} ne "") {
if ($self->{player_admin_command} ne "") {
$self->dorcon(sprintf("%s %s",$self->{player_admin_command}, $self->quoteparam("HLstatsX:CE - $name was switched to balance teams")));
$self->dorcon(sprintf("%s %s",$self->{player_admin_command}, $self->quoteparam("HLstatsX:CE - $name was switched to balance teams")));
}
}
}
}
sub analyze_teams
sub analyze_teams
{
{
my ($self) = @_;
my ($self) = @_;
if (($::g_stdin == 0) && ($self->{num_trackable_players} < $self->{minplayers}))
if (($::g_stdin == 0) && ($self->{num_trackable_players} < $self->{minplayers}))
{
{
&::printNotice("(IGNORED) NOTMINPLAYERS: analyze_teams");
&::printNotice("(IGNORED) NOTMINPLAYERS: analyze_teams");
}
}
elsif (($::g_stdin == 0) && ($self->{ba_enabled} > 0))
elsif (($::g_stdin == 0) && ($self->{ba_enabled} > 0))
{
{
&::printNotice("analyze_teams");
&::printNotice("analyze_teams");
my $ts_skill = 0;
my $ts_skill = 0;
my $ts_avg_skill = 0;
my $ts_avg_skill = 0;
my $ts_count = 0;
my $ts_count = 0;
my $ts_wins = $self->{ba_ts_wins};
my $ts_wins = $self->{ba_ts_wins};
my $ts_kills = 0;
my $ts_kills = 0;
my $ts_deaths = 0;
my $ts_deaths = 0;
my $ts_diff = 0;
my $ts_diff = 0;
my @ts_players = ();
my @ts_players = ();
my $ct_skill = 0;
my $ct_skill = 0;
my $ct_avg_skill = 0;
my $ct_avg_skill = 0;
my $ct_count = 0;
my $ct_count = 0;
my $ct_wins = $self->{ba_ct_wins};
my $ct_wins = $self->{ba_ct_wins};
my $ct_kills = 0;
my $ct_kills = 0;
my $ct_deaths = 0;
my $ct_deaths = 0;
my $ct_diff = 0;
my $ct_diff = 0;
my @ct_players = ();
my @ct_players = ();
my $server_id = $self->{id};
my $server_id = $self->{id};
while ( my($pl, $player) = each(%{$self->{srv_players}}) )
while ( my($pl, $player) = each(%{$self->{srv_players}}) )
{
{
my @Player = ( $player->{name}, #0
my @Player = ( $player->{name}, #0
$player->{uniqueid}, #1
$player->{uniqueid}, #1
$player->{skill}, #2
$player->{skill}, #2
$player->{team}, #3
$player->{team}, #3
$player->{map_kills}, #4
$player->{map_kills}, #4
$player->{map_deaths}, #5
$player->{map_deaths}, #5
($player->{map_kills}-$player->{map_deaths}), #6
($player->{map_kills}-$player->{map_deaths}), #6
$player->{is_dead}, #7
$player->{is_dead}, #7
$player->{userid}, #8
$player->{userid}, #8
);
);
if ($Player[3] eq "TERRORIST")
if ($Player[3] eq "TERRORIST")
{
{
push(@{$ts_players[$ts_count]}, @Player);
push(@{$ts_players[$ts_count]}, @Player);
$ts_skill += $Player[2];
$ts_skill += $Player[2];
$ts_count += 1;
$ts_count += 1;
$ts_kills += $Player[4];
$ts_kills += $Player[4];
$ts_deaths += $Player[5];
$ts_deaths += $Player[5];
}
}
elsif ($Player[3] eq "CT")
elsif ($Player[3] eq "CT")
{
{
push(@{$ct_players[$ct_count]}, @Player);
push(@{$ct_players[$ct_count]}, @Player);
$ct_skill += $Player[2];
$ct_skill += $Player[2];
$ct_count += 1;
$ct_count += 1;
$ct_kills += $Player[4];
$ct_kills += $Player[4];
$ct_deaths += $Player[5];
$ct_deaths += $Player[5];
}
}
}
}
@ct_players = sort { $b->[6] <=> $a->[6]} @ct_players;
@ct_players = sort { $b->[6] <=> $a->[6]} @ct_players;
@ts_players = sort { $b->[6] <=> $a->[6]} @ts_players;
@ts_players = sort { $b->[6] <=> $a->[6]} @ts_players;
&::printEvent("TEAM", "Checking Teams", 1);
&::printEvent("TEAM", "Checking Teams", 1);
$admin_msg = "AUTO-TEAM BALANCER: CT ($ct_count) $ct_kills:$ct_deaths [$ct_wins - $ts_wins] $ts_kills:$ts_deaths ($ts_count) TS";
$admin_msg = "AUTO-TEAM BALANCER: CT ($ct_count) $ct_kills:$ct_deaths [$ct_wins - $ts_wins] $ts_kills:$ts_deaths ($ts_count) TS";
if ($self->{player_events} == 1)
if ($self->{player_events} == 1)
{
{
if ($self->{player_admin_command} ne "") {
if ($self->{player_admin_command} ne "") {
$cmd_str = $self->{player_admin_command}." $admin_msg";
$cmd_str = $self->{player_admin_command}." $admin_msg";
$self->dorcon($cmd_str);
$self->dorcon($cmd_str);
}
}
}
}
$self->messageAll("HLstatsX:CE - ATB - Checking Teams", 0, 1);
$self->messageAll("HLstatsX:CE - ATB - Checking Teams", 0, 1);
if ($self->{ba_map_rounds} >= 2) # need all players for numerical balacing, at least 2 for getting all players
if ($self->{ba_map_rounds} >= 2) # need all players for numerical balacing, at least 2 for getting all players
{
{
my $action_done = 0;
my $action_done = 0;
if ($self->{ba_last_swap} > 0)
if ($self->{ba_last_swap} > 0)
{
{
$self->{ba_last_swap}--;
$self->{ba_last_swap}--;
}
}
if ($ct_count + 1 < $ts_count) # ct need players
if ($ct_count + 1 < $ts_count) # ct need players
{
{
$needed_players = floor( ($ts_count - $ct_count) / 2);
$needed_players = floor( ($ts_count - $ct_count) / 2);
if ($ct_wins < 2)
if ($ct_wins < 2)
{
{
@ts_players = sort { $b->[7] <=> $a->[7]} @ts_players;
@ts_players = sort { $b->[7] <=> $a->[7]} @ts_players;
}
}
else
else
{
{
@ts_players = sort { $a->[7] <=> $b->[7]} @ts_players;
@ts_players = sort { $a->[7] <=> $b->[7]} @ts_players;
}
}
foreach my $entry (@ts_players)
foreach my $entry (@ts_players)
{
{
if ($needed_players > 0) # how many we need to make teams even (only numerical)
if ($needed_players > 0) # how many we need to make teams even (only numerical)
{
{
if (@{$entry}[7] == 1) # only dead players!!
if (@{$entry}[7] == 1) # only dead players!!
{
{
if (($self->{switch_admins} == 1) || (($self->{switch_admins} == 0) && ($self->is_admin(@{$entry}[1]) == 0))) {
if (($self->{switch_admins} == 1) || (($self->{switch_admins} == 0) && ($self->is_admin(@{$entry}[1]) == 0))) {
$self->switch_player(@{$entry}[8], @{$entry}[0]);
$self->switch_player(@{$entry}[8], @{$entry}[0]);
$action_done++;
$action_done++;
$needed_players--;
$needed_players--;
}
}
}
}
}
}
}
}
}
}
elsif ($ts_count + 1 < $ct_count) # ts need players
elsif ($ts_count + 1 < $ct_count) # ts need players
{
{
$needed_players = floor( ($ct_count - $ts_count) / 2);
$needed_players = floor( ($ct_count - $ts_count) / 2);
if ($ts_wins < 2)
if ($ts_wins < 2)
{
{
@ct_players = sort { $b->[6] <=> $a->[6]} @ct_players; # best player
@ct_players = sort { $b->[6] <=> $a->[6]} @ct_players; # best player
}
}
else
else
{
{
@ct_players = sort { $a->[6] <=> $b->[6]} @ct_players; # worst player
@ct_players = sort { $a->[6] <=> $b->[6]} @ct_players; # worst player
}
}
foreach my $entry (@ct_players)
foreach my $entry (@ct_players)
{
{
if ($needed_players > 0) # how many we need to make teams even (only numerical)
if ($needed_players > 0) # how many we need to make teams even (only numerical)
{
{
if (@{$entry}[7] == 1) # only dead players!!
if (@{$entry}[7] == 1) # only dead players!!
{
{
if (($self->{switch_admins} == 1) || (($self->{switch_admins} == 0) && ($self->is_admin(@{$entry}[1]) == 0))) {
if (($self->{switch_admins} == 1) || (($self->{switch_admins} == 0) && ($self->is_admin(@{$entry}[1]) == 0))) {
$self->switch_player(@{$entry}[8], @{$entry}[0]);
$self->switch_player(@{$entry}[8], @{$entry}[0]);
$action_done++;
$action_done++;
$needed_players--;
$needed_players--;
}
}
}
}
}
}
}
}
}
}
if (($action_done == 0) && ($self->{ba_last_swap} == 0) && ($self->{ba_map_rounds} >= 7) && ($self->{ba_player_switch} == 0)) # frags balancing (last swap 3 rounds before
if (($action_done == 0) && ($self->{ba_last_swap} == 0) && ($self->{ba_map_rounds} >= 7) && ($s