2021-04-14 01:28:23 +00:00
class MskGsVoteCollector extends KFVoteCollector
dependson ( MapStats ) ;
var string SortPolicy ;
var bool bEnableMapStats ;
var bool bOfficialNextMapOnly ;
var bool bRandomizeNextMap ;
var private array < string > ActiveMapCycle ;
2021-02-20 10:30:45 +00:00
2021-06-22 21:58:28 +00:00
var public array < UniqueNetId > KickProtectedList ;
2021-02-20 10:30:45 +00:00
2021-06-22 21:58:28 +00:00
var private array < KFPlayerController > KickWarningList ;
var private array < KFPlayerController > KickPunishList ;
function NotifyLogout ( Controller Exiting )
{
KickWarningList . RemoveItem ( KFPlayerController ( Exiting ) ) ;
KickPunishList . RemoveItem ( KFPlayerController ( Exiting ) ) ;
}
function PunishmentTick ( )
2021-02-20 10:30:45 +00:00
{
local KFGameReplicationInfo KFGRI ;
local KFGameInfo KFGI ;
local KFPlayerController KFPC ;
2021-06-22 21:58:28 +00:00
local KFInventoryManager KFIM ;
local array < KFPlayerController > LocalKickPunishList ;
2021-02-20 10:30:45 +00:00
2021-06-22 21:58:28 +00:00
if ( KickPunishList . Length == 0 )
{
ClearTimer ( nameof ( PunishmentTick ) ) ;
2021-02-20 10:30:45 +00:00
return ;
2021-06-22 21:58:28 +00:00
}
2021-02-20 10:30:45 +00:00
KFGRI = KFGameReplicationInfo ( WorldInfo . GRI ) ;
KFGI = KFGameInfo ( WorldInfo . Game ) ;
2021-06-22 21:58:28 +00:00
LocalKickPunishList = KickPunishList ;
foreach LocalKickPunishList ( KFPC )
2021-02-20 10:30:45 +00:00
{
if ( KFGRI . bMatchHasBegun )
{
2021-06-22 21:58:28 +00:00
if ( KFPC . Pawn . Health <= 1 )
{
KFPC . Suicide ( ) ;
KickPunishList . RemoveItem ( KFPC ) ;
KickWarningList . RemoveItem ( KFPC ) ;
}
else
{
KFPC . Pawn . Health -- ;
if ( KFPawn _Human ( KFPC . Pawn ) . Armor > 0 )
KFPawn _Human ( KFPC . Pawn ) . Armor -- ;
if ( KFPC . Pawn . InvManager != None )
{
KFIM = KFInventoryManager ( KFPC . Pawn . InvManager ) ;
if ( KFIM != None )
{
KFIM . ThrowMoney ( ) ;
}
}
}
2021-02-20 10:30:45 +00:00
}
else if ( KFGI . AccessControl != none )
{
2021-06-22 21:58:28 +00:00
KickPunishList . RemoveItem ( KFPC ) ;
KickWarningList . RemoveItem ( KFPC ) ;
2021-02-20 10:30:45 +00:00
KFAccessControl ( KFGI . AccessControl ) . ForceKickPlayer ( KFPC , KFGI . AccessControl . KickedMsg ) ;
KFGI . BroadcastLocalized ( KFGI , class 'KFLocalMessage' , LMT _KickVoteSucceeded , CurrentKickVote . PlayerPRI ) ;
}
}
}
2021-06-22 21:58:28 +00:00
function bool IsPlayerKickProtected ( PlayerReplicationInfo PRI _Kickee )
{
return ( KickProtectedList . Find ( 'Uid' , PRI _Kickee . UniqueId . Uid ) != - 1 ) ;
}
function bool IsKickerWarned ( KFPlayerController KFPC )
{
return ( KickWarningList . Find ( KFPC ) != - 1 ) ;
}
function bool IsKickerPunishListed ( KFPlayerController KFPC )
{
return ( KickPunishList . Find ( KFPC ) != - 1 ) ;
}
function WarnKicker ( PlayerReplicationInfo PRI _Kickee , PlayerReplicationInfo PRI _Kicker )
{
local KFPlayerController KFPC _Kicker ;
KFPC _Kicker = KFPlayerController ( PRI _Kicker . Owner ) ;
if ( ! IsKickerWarned ( KFPC _Kicker ) )
{
KickWarningList . AddItem ( KFPC _Kicker ) ;
2021-10-17 03:35:32 +00:00
WorldInfo . Game . Broadcast ( KFPC _Kicker , PRI _Kicker . PlayerName @ "tried to kick" @ PRI _Kickee . PlayerName$ ". If he tries to do it again, the hand of God will punish him" ) ;
2021-06-22 21:58:28 +00:00
}
}
function PunishKicker ( PlayerReplicationInfo PRI _Kicker )
2021-02-20 10:30:45 +00:00
{
local KFPlayerController KFPC _Kicker ;
2021-02-25 23:55:43 +00:00
2021-06-22 21:58:28 +00:00
KFPC _Kicker = KFPlayerController ( PRI _Kicker . Owner ) ;
if ( ! IsKickerPunishListed ( KFPC _Kicker ) )
2021-02-20 10:30:45 +00:00
{
2021-06-22 21:58:28 +00:00
KickPunishList . AddItem ( KFPC _Kicker ) ;
WorldInfo . Game . Broadcast ( KFPC _Kicker , PRI _Kicker . PlayerName @ "seems to be feeling bad..." ) ;
if ( ! IsTimerActive ( nameof ( PunishmentTick ) ) )
2021-02-20 10:30:45 +00:00
{
2021-06-22 21:58:28 +00:00
SetTimer ( 0.5 f , true , nameof ( PunishmentTick ) , self ) ;
2021-02-20 10:30:45 +00:00
}
}
}
function ServerStartVoteKick ( PlayerReplicationInfo PRI _Kickee , PlayerReplicationInfo PRI _Kicker )
{
local int i ;
local array < KFPlayerReplicationInfo > PRIs ;
local KFGameInfo KFGI ;
local KFPlayerController KFPC , KickeePC ;
KFGI = KFGameInfo ( WorldInfo . Game ) ;
KFPC = KFPlayerController ( PRI _Kicker . Owner ) ;
KickeePC = KFPlayerController ( PRI _Kickee . Owner ) ;
2021-06-22 21:58:28 +00:00
if ( KFGI . bDisableKickVote ) // Kick voting is disabled
2021-02-20 10:30:45 +00:00
{
KFPC . ReceiveLocalizedMessage ( class 'KFLocalMessage' , LMT _KickVoteDisabled ) ;
return ;
}
2021-06-22 21:58:28 +00:00
if ( PRI _Kicker . bOnlySpectator ) // Spectators aren't allowed to vote
2021-02-20 10:30:45 +00:00
{
KFPC . ReceiveLocalizedMessage ( class 'KFLocalMessage' , LMT _KickVoteNoSpectators ) ;
return ;
}
2021-06-22 21:58:28 +00:00
if ( KFGI . NumPlayers <= 2 ) // Not enough players to start a vote
2021-02-20 10:30:45 +00:00
{
KFPC . ReceiveLocalizedMessage ( class 'KFLocalMessage' , LMT _KickVoteNotEnoughPlayers ) ;
return ;
}
2021-06-22 21:58:28 +00:00
if ( KickedPlayers >= 2 ) // Maximum number of players kicked per match has been reached
2021-02-20 10:30:45 +00:00
{
KFPC . ReceiveLocalizedMessage ( class 'KFLocalMessage' , LMT _KickVoteMaxKicksReached ) ;
return ;
}
2021-06-22 21:58:28 +00:00
if ( IsPlayerKickProtected ( PRI _Kickee ) ) // Bottling
2021-02-20 10:30:45 +00:00
{
2021-06-22 21:58:28 +00:00
if ( IsKickerWarned ( KFPC ) )
{
PunishKicker ( PRI _Kicker ) ;
}
else
{
WarnKicker ( PRI _Kickee , PRI _Kicker ) ;
}
2021-02-20 10:30:45 +00:00
return ;
}
2021-06-22 21:58:28 +00:00
if ( KFGI . AccessControl != none ) // Can't kick admins
2021-02-20 10:30:45 +00:00
{
2021-06-22 21:58:28 +00:00
if ( KFGI . AccessControl . IsAdmin ( KickeePC ) )
2021-02-20 10:30:45 +00:00
{
KFPC . ReceiveLocalizedMessage ( class 'KFLocalMessage' , LMT _KickVoteAdmin ) ;
return ;
}
}
2021-06-22 21:58:28 +00:00
if ( bIsFailedVoteTimerActive ) // Last vote failed, must wait until failed vote cooldown before starting a new vote
2021-02-20 10:30:45 +00:00
{
KFPC . ReceiveLocalizedMessage ( class 'KFLocalMessage' , LMT _KickVoteRejected ) ;
return ;
}
2021-12-09 16:44:32 +00:00
if ( bIsSkipTraderVoteInProgress || bIsPauseGameVoteInProgress ) // A kick vote is not allowed while another vote is active
2021-02-20 10:30:45 +00:00
{
KFPC . ReceiveLocalizedMessage ( class 'KFLocalMessage' , LMT _OtherVoteInProgress ) ;
return ;
}
2021-06-22 21:58:28 +00:00
if ( ! bIsKickVoteInProgress )
2021-02-20 10:30:45 +00:00
{
// Clear voter array
PlayersThatHaveVoted . Length = 0 ;
// Cache off these values in case player leaves before vote ends -- no cheating!
CurrentKickVote . PlayerID = PRI _Kickee . UniqueId ;
CurrentKickVote . PlayerPRI = PRI _Kickee ;
CurrentKickVote . PlayerIPAddress = KickeePC . GetPlayerNetworkAddress ( ) ;
bIsKickVoteInProgress = true ;
GetKFPRIArray ( PRIs ) ;
for ( i = 0 ; i < PRIs . Length ; i ++ )
{
PRIs [ i ] . ShowKickVote ( PRI _Kickee , VoteTime , ! ( PRIs [ i ] == PRI _Kicker || PRIs [ i ] == PRI _Kickee ) ) ;
}
KFGI . BroadcastLocalized ( KFGI , class 'KFLocalMessage' , LMT _KickVoteStarted , CurrentKickVote . PlayerPRI ) ;
WorldInfo . Game . Broadcast ( KFPC , PRI _Kicker . PlayerName @ "starts voting for kick" @ PRI _Kickee . PlayerName ) ;
2021-06-22 21:58:28 +00:00
SetTimer ( VoteTime , false , nameof ( ConcludeVoteKick ) , self ) ;
2021-02-20 10:30:45 +00:00
// Cast initial vote
RecieveVoteKick ( PRI _Kicker , true ) ;
}
2021-06-22 21:58:28 +00:00
else if ( PRI _Kickee == CurrentKickVote . PlayerPRI )
2021-02-20 10:30:45 +00:00
{
RecieveVoteKick ( PRI _Kicker , false ) ;
}
else
{
// Can't start a new vote until current one is over
KFPlayerController ( PRI _Kicker . Owner ) . ReceiveLocalizedMessage ( class 'KFLocalMessage' , LMT _KickVoteInProgress ) ;
}
}
reliable server function RecieveVoteKick ( PlayerReplicationInfo PRI , bool bKick )
{
local KFPlayerController KFPC ;
if ( PlayersThatHaveVoted . Find ( PRI ) == INDEX _NONE )
{
//accept their vote
PlayersThatHaveVoted . AddItem ( PRI ) ;
if ( bKick )
{
yesVotes ++ ;
}
else
{
noVotes ++ ;
}
KFPC = KFPlayerController ( PRI . Owner ) ;
if ( KFPC != none )
{
if ( bKick )
{
KFPC . ReceiveLocalizedMessage ( class 'KFLocalMessage' , LMT _KickVoteYesReceived , CurrentKickVote . PlayerPRI ) ;
WorldInfo . Game . Broadcast ( KFPC , PRI . PlayerName @ "vote: Yes" ) ;
}
else
{
KFPC . ReceiveLocalizedMessage ( class 'KFLocalMessage' , LMT _KickVoteNoReceived , CurrentKickVote . PlayerPRI ) ;
WorldInfo . Game . Broadcast ( KFPC , PRI . PlayerName @ "vote: No" ) ;
}
}
if ( ShouldConcludeKickVote ( ) )
{
ConcludeVoteKick ( ) ;
}
else
{
ReplicateKickVotes ( ) ;
}
}
}
2021-04-14 01:28:23 +00:00
function LoadActiveMapCycle ( )
{
local KFGameInfo KFGI ;
if ( ActiveMapCycle . Length > 0 ) return ;
KFGI = KFGameInfo ( WorldInfo . Game ) ;
if ( WorldInfo . NetMode == NM _Standalone )
ActiveMapCycle = Maplist ;
else if ( KFGI != None )
ActiveMapCycle = KFGI . GameMapCycles [ KFGI . ActiveMapCycle ] . Maps ;
}
function bool IsOfficialMap ( string MapName )
{
local KFMapSummary MapData ;
MapData = class 'KFUIDataStore_GameResource' . static . GetMapSummaryFromMapName ( MapName ) ;
if ( MapData == None ) return False ;
return ( MapData . MapAssociation != EAI _Custom ) ;
}
function int GetNextMapIndex ( )
2021-02-20 10:30:45 +00:00
{
local KFGameInfo KFGI ;
local array < string > AviableMaps ;
local string Map ;
2021-04-14 01:28:23 +00:00
local int CurrentMapIndex ;
KFGI = KFGameInfo ( WorldInfo . Game ) ;
if ( KFGI == None ) return INDEX _NONE ;
2021-02-20 10:30:45 +00:00
2021-04-14 01:28:23 +00:00
LoadActiveMapCycle ( ) ;
if ( bRandomizeNextMap )
2021-02-20 10:30:45 +00:00
{
2021-04-14 01:28:23 +00:00
foreach ActiveMapCycle ( Map )
{
if ( bOfficialNextMapOnly && ! IsOfficialMap ( Map ) )
continue ;
if ( KFGI . IsMapAllowedInCycle ( Map ) )
AviableMaps . AddItem ( Map ) ;
}
if ( AviableMaps . Length > 0 )
return ActiveMapCycle . Find ( AviableMaps [ Rand ( AviableMaps . Length ) ] ) ;
2021-02-20 10:30:45 +00:00
}
2021-04-14 01:28:23 +00:00
else if ( ActiveMapCycle . Length > 0 )
2021-02-20 10:30:45 +00:00
{
2021-04-14 01:28:23 +00:00
// I don't use KFGameInfo.GetNextMap() because
// it uses and changes global KFGameInfo.MapCycleIndex variable
CurrentMapIndex = ActiveMapCycle . Find ( WorldInfo . GetMapName ( true ) ) ;
if ( CurrentMapIndex != INDEX _NONE )
{
for ( CurrentMapIndex ++ ; CurrentMapIndex < ActiveMapCycle . Length ; CurrentMapIndex ++ )
{
if ( bOfficialNextMapOnly && ! IsOfficialMap ( ActiveMapCycle [ CurrentMapIndex ] ) )
continue ;
if ( KFGI . IsMapAllowedInCycle ( ActiveMapCycle [ CurrentMapIndex ] ) )
return CurrentMapIndex ;
}
}
return 0 ;
}
return INDEX _NONE ;
}
2021-02-20 10:30:45 +00:00
2021-04-14 01:28:23 +00:00
function int GetNextMap ( )
{
local int MapIndex ;
2021-02-20 10:30:45 +00:00
2021-04-14 01:28:23 +00:00
if ( MapVoteList . Length > 0 )
MapIndex = MapVoteList [ 0 ] . MapIndex ;
else
MapIndex = GetNextMapIndex ( ) ;
2021-02-20 10:30:45 +00:00
2021-04-14 01:28:23 +00:00
if ( bEnableMapStats )
{
if ( MapIndex == INDEX _NONE )
{
` log("[MskGsMut] Warn: MapIndex == INDEX_NONE, stats not saved");
}
else
{
LoadActiveMapCycle ( ) ;
class 'MapStats' . static . IncMapStat ( ActiveMapCycle [ MapIndex ] , SortPolicy ) ;
}
2021-02-20 10:30:45 +00:00
}
2021-04-14 01:28:23 +00:00
return MapIndex ;
2021-02-20 10:30:45 +00:00
}
DefaultProperties
{
}