Comparing sensitive data, confidential files or internal emails?

Most legal and privacy policies prohibit uploading sensitive data online. Diffchecker Desktop ensures your confidential information never leaves your computer. Work offline and compare documents securely.

here are the changes in the HLSTATS_SERVER.PM

Created Diff never expires
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