rott/kf_sources/ScrnBalanceSrv/Classes/ScrnBalanceVoting.uc
2026-07-14 20:27:09 +07:00

932 lines
35 KiB
Ucode

class ScrnBalanceVoting extends ScrnVotingOptions;
var ScrnBalance Mut;
const VOTE_PERKLOCK = 0;
const VOTE_PERKUNLOCK = 1;
const VOTE_PAUSE = 2;
const VOTE_ENDTRADE = 3;
const VOTE_BLAME = 4;
const VOTE_KICK = 5;
const VOTE_BORING = 6;
const VOTE_SPAWN = 7;
const VOTE_ENDWAVE = 8;
const VOTE_SPEC = 9;
const VOTE_READY = 10;
const VOTE_UNREADY = 11;
const VOTE_TEAMLOCK = 12;
const VOTE_TEAMUNLOCK = 13;
const VOTE_INVITE = 14;
const VOTE_FF = 15;
const VOTE_MAPRESTART = 16;
const VOTE_FAKEDPLAYERS = 17;
const VOTE_FAKEDCOUNT = 18;
const VOTE_FAKEDHEALTH = 19;
const VOTE_DIFF = 20;
const VOTE_RKILL = 100;
var localized string strCantEndTrade;
var localized string strTooLate;
var localized string strGamePaused, strSecondsLeft, strGameUnPaused, strPauseTraderOnly;
var localized string viResume, viEndTrade, viDifficulty;
var localized string strZedSpawnsDoubled;
var localized string strSquadNotFound, strCantSpawnSquadNow, strSquadList;
var localized string strNotInStoryMode, strNotInTSC;
var localized string strCantEndWaveNow, strEndWavePenalty;
var localized string strRCommands;
//variables for GamePaused state
var int PauseTime;
var transient bool bPauseable;
var transient string msgPause;
var string Reason; // reason why voting was started (e.g. kick player for being noob)
var transient float LastBlameVoteTime;
function class<ScrnVeterancyTypes> FindPerkByName(PlayerController Sender, string VeterancyNameOrIndex)
{
local int i;
local ClientPerkRepLink L;
local class<ScrnVeterancyTypes> Perk;
local string s1, s2;
// log("FindPerkByName("$Sender$", "$VeterancyNameOrIndex$")", 'ScrnBalance');
if ( Sender == none || VeterancyNameOrIndex == "" || SRStatsBase(Sender.SteamStatsAndAchievements) == none )
return none;
L = SRStatsBase(Sender.SteamStatsAndAchievements).Rep;
if ( L == none )
return none;
i = int(VeterancyNameOrIndex);
if ( i > 0 && i <= L.CachePerks.Length )
return class<ScrnVeterancyTypes>(L.CachePerks[i-1].PerkClass);
// log("CachePerks.Length="$L.CachePerks.Length, 'ScrnBalance');
for ( i = 0; i < L.CachePerks.Length; ++i ) {
Perk = class<ScrnVeterancyTypes>(L.CachePerks[i].PerkClass);
if ( Perk != none ) {
// log(GetItemName(String(Perk.class)) @ Perk.default.VeterancyNameOrIndex, 'ScrnBalance');
if ( GetItemName(String(Perk.class)) ~= VeterancyNameOrIndex || Perk.default.VeterancyName ~= VeterancyNameOrIndex
|| (Divide(Perk.default.VeterancyName, " ", s1, s2) && (VeterancyNameOrIndex ~= s1 || VeterancyNameOrIndex ~= s2)) )
return Perk;
}
}
return none;
}
function SendSquadList(PlayerController Sender)
{
local int i;
local string s;
if ( Mut.Squads.Length == 0 ) {
Sender.ClientMessage(strOptionDisabled);
return;
}
s = strSquadList @ Mut.Squads[0].SquadName;
for ( i=1; i<Mut.Squads.Length; ++i ) {
s = s $ ", " $ Mut.Squads[i].SquadName;
}
Sender.ClientMessage(s);
}
static function bool TryStrToInt(string str, out int val)
{
val = int(str);
return val != 0 || str == "0";
}
function int GetVoteIndex(PlayerController Sender, string Key, out string Value, out string VoteInfo)
{
local int result, v;
local class<ScrnVeterancyTypes> Perk;
if ( Key == "LOCKPERK" ) {
if ( !Mut.bAllowLockPerkVote ) {
Sender.ClientMessage(strOptionDisabled);
return VOTE_NOEFECT;
}
Perk = FindPerkByName(Sender, Value);
if ( Perk == none )
return VOTE_ILLEGAL;
if ( Perk.default.bLocked )
return VOTE_NOEFECT;
result = VOTE_PERKLOCK;
Value = Perk.default.VeterancyName;
}
else if ( Key == "UNLOCKPERK" ) {
Perk = FindPerkByName(Sender, Value);
if ( Perk == none )
return VOTE_ILLEGAL;
if ( !Perk.default.bLocked )
return VOTE_NOEFECT;
result = VOTE_PERKUNLOCK;
Value = Perk.default.VeterancyName;
}
else if ( Key == "PAUSE" || (Level.Pauser != none && Key == "RESUME") ) {
if ( !Mut.bAllowPauseVote ) {
Sender.ClientMessage(strOptionDisabled);
return VOTE_NOEFECT;
}
if ( Mut.bPauseTraderOnly && !Mut.KF.bTradingDoorsOpen && Mut.KF.IsInState('MatchInProgress') ) {
Sender.ClientMessage(strPauseTraderOnly);
return VOTE_NOEFECT;
}
result = VOTE_PAUSE;
if ( Value == "" )
Value = "60";
else {
v = int(Value);
if ( v <= 0 )
v = 60;
Value = string(v);
}
if ( Level.Pauser != none )
VoteInfo = viResume;
}
else if ( Key == "ENDTRADE" || (Key == "END" && Value == "TRADE") ) {
if ( Mut.bStoryMode ) {
Sender.ClientMessage(strNotInStoryMode);
return VOTE_NOEFECT;
}
if ( Mut.KF.bWaveInProgress|| Mut.KF.WaveCountDown < 10 || Mut.SkippedTradeTimeMult < 0 ) {
Sender.ClientMessage(strCantEndTrade);
return VOTE_NOEFECT;
}
result = VOTE_ENDTRADE;
Value = "";
VoteInfo = viEndTrade;
}
else if ( Key == "BLAME" ) {
if ( !Mut.bAllowBlameVote ) {
Sender.ClientMessage(strOptionDisabled);
return VOTE_NOEFECT;
}
if ( Level.TimeSeconds - LastBlameVoteTime < Mut.BlameVoteCoolDown ) {
Sender.ClientMessage(strNotAvaliableATM);
return VOTE_LOCAL;
}
if ( Value == "" ) {
SendPlayerList(Sender);
return VOTE_LOCAL;
}
Reason = "";
if ( Left(Value, 1) == "\"" ) {
// don't look for player in quoted string - just blame it :)
VotingHandler.VotedPlayer = none;
Value = Mid(Value, 1);
Divide(Value, "\"", Value, Reason);
VotingHandler.VotedPlayer = none;
}
else {
Divide(Value, " ", Value, Reason);
if ( Value ~= "ALL" || Value ~= "TEAM" ) {
Value = "TEAM";
VoteInfo = "Blame Team";
VotingHandler.VotedPlayer = none;
}
else {
if ( Value ~= "ME" )
VotingHandler.VotedPlayer = Sender;
else
VotingHandler.VotedPlayer = FindPlayer(Value);
if ( VotingHandler.VotedPlayer == none ) {
Sender.ClientMessage(strPlayerNotFound);
SendPlayerList(Sender);
return VOTE_ILLEGAL;
}
Value = Mut.ColoredPlayerName(VotingHandler.VotedPlayer.PlayerReplicationInfo);
VoteInfo = "Blame " $ Value;
}
}
LastBlameVoteTime = Level.TimeSeconds;
result = VOTE_BLAME;
}
else if ( Key == "SPEC" ) {
if ( Level.Game.AccessControl == none
|| Level.Game.NumSpectators > Level.Game.MaxSpectators
|| (!Mut.bAllowKickVote && !Sender.PlayerReplicationInfo.bAdmin) )
{
Sender.ClientMessage(strOptionDisabled);
return VOTE_NOEFECT;
}
if ( Value == "" ) {
SendPlayerList(Sender);
return VOTE_LOCAL;
}
Reason = "";
Divide(Value, " ", Value, Reason);
VotingHandler.VotedPlayer = FindPlayer(Value);
if ( VotingHandler.VotedPlayer == none ) {
Sender.ClientMessage(strPlayerNotFound);
SendPlayerList(Sender);
return VOTE_ILLEGAL;
}
Value = Mut.ColoredPlayerName(VotingHandler.VotedPlayer.PlayerReplicationInfo);
VoteInfo = "Spectate " $ Value;
result = VOTE_SPEC;
}
else if ( Key == "KICK" ) {
if ( Level.Game.AccessControl == none || (!Mut.bAllowKickVote && !Sender.PlayerReplicationInfo.bAdmin) ) {
Sender.ClientMessage(strOptionDisabled);
return VOTE_NOEFECT;
}
if ( Value == "" ) {
SendPlayerList(Sender);
return VOTE_LOCAL;
}
Reason = "";
Divide(Value, " ", Value, Reason);
VotingHandler.VotedPlayer = FindPlayer(Value);
if ( VotingHandler.VotedPlayer == none ) {
Sender.ClientMessage(strPlayerNotFound);
SendPlayerList(Sender);
return VOTE_ILLEGAL;
}
Value = Mut.ColoredPlayerName(VotingHandler.VotedPlayer.PlayerReplicationInfo);
VoteInfo = "Kick " $ Value;
result = VOTE_KICK;
}
else if ( Key == "INVITE" ) {
if ( !Mut.CheckScrnGT(Sender) )
return VOTE_LOCAL;
if ( Value == "" ) {
SendPlayerList(Sender);
return VOTE_LOCAL;
}
Reason = "";
Divide(Value, " ", Value, Reason);
VotingHandler.VotedPlayer = FindPlayer(Value);
if ( VotingHandler.VotedPlayer == none ) {
Sender.ClientMessage(strPlayerNotFound);
SendPlayerList(Sender);
return VOTE_ILLEGAL;
}
else if ( Mut.ScrnGT.IsInvited(VotingHandler.VotedPlayer) ) {
VotingHandler.VotedPlayer = none;
return VOTE_NOEFECT;
}
Value = Mut.ColoredPlayerName(VotingHandler.VotedPlayer.PlayerReplicationInfo);
VoteInfo = "Invite " $ Value;
result = VOTE_INVITE;
}
else if ( Key == "BORING" ) {
if ( Mut.bStoryMode ) {
Sender.ClientMessage(strNotInStoryMode);
return VOTE_LOCAL;
}
else if ( !Mut.bAllowBoringVote && !Sender.PlayerReplicationInfo.bAdmin ) {
Sender.ClientMessage(strOptionDisabled);
return VOTE_LOCAL;
}
else if ( Mut.KF.bTradingDoorsOpen || Mut.KF.KFLRules.WaveSpawnPeriod < 0.5 ) {
Sender.ClientMessage(strNotAvaliableATM);
return VOTE_LOCAL;
}
Value = "";
VoteInfo = "Game is BORING";
result = VOTE_BORING;
}
else if ( Key == "SPAWN" ) {
if ( Mut.bStoryMode && !Mut.bBeta ) {
Sender.ClientMessage(strNotInStoryMode);
return VOTE_NOEFECT;
}
if ( Mut.Squads.Length == 0 ) {
Sender.ClientMessage(strOptionDisabled);
return VOTE_NOEFECT;
}
if ( Value == "" ) {
SendSquadList(Sender);
return VOTE_LOCAL;
}
if ( Mut.FindSquad(Value) == -1 ) {
Sender.ClientMessage(strSquadNotFound);
return VOTE_ILLEGAL;
}
if ( Mut.KF.TotalMaxMonsters < 10 ) {
Sender.ClientMessage(strCantSpawnSquadNow);
return VOTE_NOEFECT;
}
result = VOTE_SPAWN;
}
else if ( Key == "ENDWAVE" || (Key == "END" && Value == "WAVE") ) {
VotingHandler.VotedTeam = Sender.PlayerReplicationInfo.Team;
if ( VotingHandler.VotedTeam == none )
return VOTE_ILLEGAL;
if ( Mut.KF.NumMonsters == 0 )
return VOTE_NOEFECT;
if ( Mut.MaxVoteKillMonsters == 0 ) {
Sender.ClientMessage(strOptionDisabled);
return VOTE_NOEFECT;
}
if ( Mut.KF.TotalMaxMonsters > 0 || Mut.KF.NumMonsters > Mut.MaxVoteKillMonsters
|| Mut.GameRules.bFinalWave || !CanEndWave() )
{
Sender.ClientMessage(strCantEndWaveNow);
return VOTE_NOEFECT;
}
return VOTE_ENDWAVE;
}
else if ( Key == "READY" ) {
if ( !Level.Game.bWaitingToStartMatch )
return VOTE_NOEFECT;
return VOTE_READY;
}
else if ( Key == "UNREADY" ) {
if ( !Level.Game.bWaitingToStartMatch )
return VOTE_NOEFECT;
return VOTE_UNREADY;
}
else if ( Key == "LOCKTEAM" || Key == "LOCKTEAMS" ) {
if ( !Mut.CheckScrnGT(Sender) )
return VOTE_LOCAL;
else if ( Mut.bTeamsLocked )
return VOTE_NOEFECT;
else if ( !Sender.PlayerReplicationInfo.bAdmin && (Mut.ScrnGT.WaveNum+1) < Mut.ScrnGT.RelativeWaveNum(Mut.LockTeamMinWave) ) {
Sender.ClientMessage(strNotAvaliableATM);
return VOTE_LOCAL;
}
return VOTE_TEAMLOCK;
}
else if ( Key == "UNLOCKTEAM" || Key == "UNLOCKTEAMS" ) {
if ( !Mut.CheckScrnGT(Sender) )
return VOTE_LOCAL;
else if ( !Mut.bTeamsLocked )
return VOTE_NOEFECT;
return VOTE_TEAMUNLOCK;
}
else if ( Key == "FF" ) {
if ( Mut.bTSCGame ) {
Sender.ClientMessage(strNotInTSC);
return VOTE_NOEFECT;
}
if ( Level.GRI.bMatchHasBegun ) {
Sender.ClientMessage(strNotAvaliableATM);
return VOTE_LOCAL;
}
if ( right(Value, 1) == "%" )
Value = left(Value, len(Value)-1);
if ( !TryStrToInt(Value, v) || v < Mut.MinVoteFF || v > Mut.MaxVoteFF )
return VOTE_ILLEGAL;
if ( v == int(Mut.KF.FriendlyFireScale*100) )
return VOTE_NOEFECT;
if ( v == 0 )
VoteInfo = "Friendly Fire OFF";
else
VoteInfo = "Friendly Fire "$v$"%";
return VOTE_FF;
}
else if ( Key == "MAP" && Value == "RESTART" ) {
result = VOTE_MAPRESTART;
}
else if ( Key == "FAKED" || Key == "FAKEDPLAYERS" ) {
if ( !Mut.CheckScrnGT(Sender) )
return VOTE_LOCAL;
if ( !TryStrToInt(Value, v) || v < 0 || v > 32 )
return VOTE_ILLEGAL;
if ( Mut.ScrnGT.ScrnGRI.FakedPlayers == v && Mut.ScrnGT.ScrnGRI.FakedAlivePlayers == v )
return VOTE_NOEFECT;
if ( v <= 1 )
VoteInfo = "Faked Players OFF";
else
VoteInfo = v $ " Faked Players";
return VOTE_FAKEDPLAYERS;
}
else if ( Key == "FAKEDCOUNT" ) {
if ( !Mut.CheckScrnGT(Sender) )
return VOTE_LOCAL;
if ( !TryStrToInt(Value, v) || v < 0 || v > 32 )
return VOTE_ILLEGAL;
if ( Mut.ScrnGT.ScrnGRI.FakedPlayers == v )
return VOTE_NOEFECT;
if ( v <= 1 )
VoteInfo = "Faked Zed Count OFF";
else
VoteInfo = v $ "p Faked Zed Count";
return VOTE_FAKEDCOUNT;
}
else if ( Key == "FAKEDHEALTH" ) {
if ( !Mut.CheckScrnGT(Sender) )
return VOTE_LOCAL;
if ( !TryStrToInt(Value, v) || v < 0 || v > 32 )
return VOTE_ILLEGAL;
if ( Mut.ScrnGT.ScrnGRI.FakedAlivePlayers == v )
return VOTE_NOEFECT;
if ( v <= 1 )
VoteInfo = "Faked Zed Health OFF";
else
VoteInfo = v $ "p Faked Zed Health";
return VOTE_FAKEDHEALTH;
}
else if ( Key == "DIFF" || Key == "DIFFICULTY" ) {
if ( Value == "" ) {
Sender.ClientMessage("Usage: MVOTE DIFF DEFAULT|NORMAL|HARD|SUI|SUI+|HOE|HOE+");
return VOTE_LOCAL;
}
v = GetDifficulty(Value);
if ( v != 0 && v < Mut.MinVoteDifficulty || v > 8 )
return VOTE_ILLEGAL;
if ( v == Mut.Persistence.Difficulty )
return VOTE_NOEFECT;
VoteInfo = Value @ viDifficulty;
Value = string(v);
return VOTE_DIFF;
}
else if ( Key == "R_KILL" ) {
if ( !Sender.PlayerReplicationInfo.bAdmin || Mut.SrvTourneyMode == 0 ) {
Sender.ClientMessage(strRCommands);
return VOTE_LOCAL;
}
if ( Value == "" ) {
SendPlayerList(Sender);
return VOTE_LOCAL;
}
Reason = "";
Divide(Value, " ", Value, Reason);
VotingHandler.VotedPlayer = FindPlayer(Value);
if ( VotingHandler.VotedPlayer == none ) {
Sender.ClientMessage(strPlayerNotFound);
SendPlayerList(Sender);
return VOTE_ILLEGAL;
}
Value = Mut.ColoredPlayerName(VotingHandler.VotedPlayer.PlayerReplicationInfo);
VoteInfo = "Referee KILL " $ Value;
result = VOTE_RKILL;
}
else
return VOTE_UNKNOWN;
return result;
}
function ApplyVoteValue(int VoteIndex, string VoteValue)
{
local class<ScrnVeterancyTypes> Perk;
local ScrnCustomPRI ScrnPRI;
switch ( VoteIndex ) {
case VOTE_PERKLOCK: case VOTE_PERKUNLOCK:
Perk = FindPerkByName(VotingHandler.VoteInitiator, VoteValue);
if ( Perk != none ) {
Mut.LockPerk(Perk, VoteIndex == VOTE_PERKLOCK);
}
break;
case VOTE_PAUSE:
if (Level.Pauser == none ) {
//pause game
if ( Mut.bPauseTraderOnly && !Mut.KF.bTradingDoorsOpen && Mut.KF.IsInState('MatchInProgress') ) {
VotingHandler.BroadcastMessage(strPauseTraderOnly);
return;
}
PauseTime = int(VoteValue);
if ( PauseTime <= 0 )
PauseTime = 60;
GotoState('GamePaused', 'Begin');
//Enable('Tick');
}
else {
//resume game
Level.Pauser = none;
VotingHandler.BroadcastMessage(strGameUnpaused);
//Disable('Tick');
}
break;
case VOTE_ENDTRADE:
if ( Mut.KF.bWaveInProgress || Mut.KF.WaveCountDown < 6 ) {
VotingHandler.BroadcastMessage(strTooLate);
return;
}
Mut.TradeTimeAddSeconds = max(float(Mut.KF.WaveCountDown - 5) * Mut.SkippedTradeTimeMult, 0);
Mut.KF.WaveCountDown = 6; // need to left at least 6 to execute kfgametype.timer() events
break;
case VOTE_BLAME:
if ( VotingHandler.VotedPlayer != none )
VoteValue = Mut.ColoredPlayerName(VotingHandler.VotedPlayer.PlayerReplicationInfo);
LastBlameVoteTime = Level.TimeSeconds;
if ( Reason == "" )
VotingHandler.BroadcastMessage(VoteValue $ " blamed");
else
VotingHandler.BroadcastMessage(VoteValue $ " blamed for " $Reason);
//achievement
if ( IsGoodReason(Reason) && VotingHandler.VoteInitiator != none
&& SRStatsBase(VotingHandler.VoteInitiator.SteamStatsAndAchievements) != none )
{
class'ScrnBalanceSrv.ScrnAchievements'.static.ProgressAchievementByID(
SRStatsBase(VotingHandler.VoteInitiator.SteamStatsAndAchievements).Rep, 'Blame55p', 1);
if ( VotingHandler.VotedPlayer == VotingHandler.VoteInitiator )
class'ScrnBalanceSrv.ScrnAchievements'.static.ProgressAchievementByID(
SRStatsBase(VotingHandler.VoteInitiator.SteamStatsAndAchievements).Rep, 'BlameMe', 1);
else if ( ScrnPlayerController(VotingHandler.VotedPlayer) != none && ScrnPlayerController(VotingHandler.VotedPlayer).BeggingForMoney >= 3 )
{
class'ScrnBalanceSrv.ScrnAchievements'.static.ProgressAchievementByID(
SRStatsBase(VotingHandler.VoteInitiator.SteamStatsAndAchievements).Rep, 'SellCrap', 1);
VotingHandler.VotedPlayer.ReceiveLocalizedMessage(class'ScrnBalanceSrv.ScrnFakedAchMsg', 1);
ScrnPlayerController(VotingHandler.VotedPlayer).BeggingForMoney = 0;
}
}
if ( VotingHandler.VotedPlayer != none ) {
ScrnPRI = class'ScrnCustomPRI'.static.FindMe(VotingHandler.VotedPlayer.PlayerReplicationInfo);
if ( ScrnPRI != none ) {
VotingHandler.VotedPlayer.ReceiveLocalizedMessage(class'ScrnBalanceSrv.ScrnBlamedMsg', ScrnPRI.BlameCounter++); // more blame = bigger shit
//achievement
if ( ScrnPRI.BlameCounter == 5
&& SRStatsBase(VotingHandler.VotedPlayer.SteamStatsAndAchievements) != none )
class'ScrnBalanceSrv.ScrnAchievements'.static.ProgressAchievementByID(
SRStatsBase(VotingHandler.VotedPlayer.SteamStatsAndAchievements).Rep, 'MaxBlame', 1);
}
else
VotingHandler.VotedPlayer.ReceiveLocalizedMessage(class'ScrnBalanceSrv.ScrnBlamedMsg');
}
if ( VoteValue ~= "TEAM" || VoteValue ~= "ALL" ) {
BlameAll();
//achievement
if ( IsGoodReason(Reason) && VotingHandler.VoteInitiator != none
&& SRStatsBase(VotingHandler.VoteInitiator.SteamStatsAndAchievements) != none )
class'ScrnBalanceSrv.ScrnAchievements'.static.ProgressAchievementByID(
SRStatsBase(VotingHandler.VoteInitiator.SteamStatsAndAchievements).Rep, 'BlameTeam', 1);
}
else if ( VoteValue ~= "Baron" || (VotingHandler.VotedPlayer != none && VotingHandler.VotedPlayer.GetPlayerIDHash() == "76561198006289592") ) {
Mut.BroadcastFakedAchievement(0); // blame Baron :)
// blame the one who blamed baron
if ( VotingHandler.VoteInitiator != none && VotingHandler.VotedPlayer != VotingHandler.VoteInitiator ) {
VotingHandler.VotedPlayer = VotingHandler.VoteInitiator;
Reason = "Blaming Baron";
ApplyVoteValue(VoteIndex, VoteValue);
}
}
else if ( VoteValue ~= "TWI" || VoteValue ~= "Tripwire" ) {
Mut.BroadcastFakedAchievement(3); // blame Tripwire :)
}
else
BlameMonster(VoteValue);
break;
case VOTE_SPEC:
if ( VotingHandler.VotedPlayer != none && !VotingHandler.VotedPlayer.PlayerReplicationInfo.bAdmin ) {
if ( Mut.ScrnGT != none )
Mut.ScrnGT.UninvitePlayer(VotingHandler.VotedPlayer);
VotingHandler.VotedPlayer.BecomeSpectator();
}
break;
case VOTE_KICK:
if ( VotingHandler.VotedPlayer != none && !VotingHandler.VotedPlayer.PlayerReplicationInfo.bAdmin && NetConnection(VotingHandler.VotedPlayer.Player)!=None ) {
if ( Mut.ScrnGT != none )
Mut.ScrnGT.UninvitePlayer(VotingHandler.VotedPlayer);
if ( Reason == "" ) {
VotingHandler.BroadcastMessage(VoteValue $ " kicked");
VotingHandler.VotedPlayer.ClientNetworkMessage("AC_Kicked", "Team Vote");
}
else {
VotingHandler.BroadcastMessage(VoteValue $ " kicked for " $Reason);
VotingHandler.VotedPlayer.ClientNetworkMessage("AC_Kicked", Reason);
}
if (VotingHandler.VotedPlayer.Pawn != none && Vehicle(VotingHandler.VotedPlayer.Pawn) == none)
VotingHandler.VotedPlayer.Pawn.Destroy();
if (VotingHandler.VotedPlayer != None)
VotingHandler.VotedPlayer.Destroy();
}
break;
case VOTE_BORING:
Mut.KF.KFLRules.WaveSpawnPeriod *= 0.5;
VotingHandler.BroadcastMessage(strZedSpawnsDoubled $ " ("$Mut.KF.KFLRules.WaveSpawnPeriod$")");
break;
case VOTE_SPAWN:
Mut.SpawnSquad(VoteValue);
break;
case VOTE_ENDWAVE:
if ( Mut.KF.TotalMaxMonsters > 0 || Mut.KF.NumMonsters > Mut.MaxVoteKillMonsters
|| Mut.GameRules.bFinalWave )
{
return;
}
DoEndWave();
break;
case VOTE_READY:
SetReady(VotingHandler.VotedTeam.TeamIndex, true);
break;
case VOTE_UNREADY:
SetReady(VotingHandler.VotedTeam.TeamIndex, false);
break;
case VOTE_TEAMLOCK:
Mut.ScrnGT.LockTeams();
break;
case VOTE_TEAMUNLOCK:
Mut.ScrnGT.UnlockTeams();
break;
case VOTE_INVITE:
Mut.ScrnGT.InvitePlayer(VotingHandler.VotedPlayer);
break;
case VOTE_FF:
Mut.KF.FriendlyFireScale = float(VoteValue)/100.0;
if ( TSCGame(Mut.KF) != none )
TSCGame(Mut.KF).HdmgScale = Mut.KF.FriendlyFireScale;
break;
case VOTE_MAPRESTART:
Level.ServerTravel("?restart",false);
break;
case VOTE_FAKEDPLAYERS:
Mut.ScrnGT.ScrnGRI.FakedPlayers = byte(VoteValue);
Mut.ScrnGT.ScrnGRI.FakedAlivePlayers = byte(VoteValue);
break;
case VOTE_FAKEDCOUNT:
Mut.ScrnGT.ScrnGRI.FakedPlayers = byte(VoteValue);
break;
case VOTE_FAKEDHEALTH:
Mut.ScrnGT.ScrnGRI.FakedAlivePlayers = byte(VoteValue);
break;
case VOTE_DIFF:
Mut.Persistence.Difficulty = byte(VoteValue);
Mut.Persistence.SaveConfig();
break;
case VOTE_RKILL:
if ( VotingHandler.VotedPlayer != none && VotingHandler.VotedPlayer.Pawn != none ) {
VotingHandler.VotedPlayer.Pawn.Suicide();
if ( Reason == "" ) {
VotingHandler.BroadcastMessage(VoteValue $ " killed by referee");
}
else {
VotingHandler.BroadcastMessage(VoteValue $ " killed by referee for " $Reason);
}
}
break;
}
}
function SetReady(byte TeamIndex, bool bReady)
{
local Controller C;
for ( C = Level.ControllerList; C != None; C = C.NextController )
{
if ( C.PlayerReplicationInfo != none && C.bIsPlayer && PlayerController(C) != none
&& C.PlayerReplicationInfo.Team != none
&& C.PlayerReplicationInfo.bWaitingPlayer && !C.PlayerReplicationInfo.bOnlySpectator )
{
C.PlayerReplicationInfo.bReadyToPlay = bReady;
}
}
}
function class<KFMonster> Str2Monster(string MonsterName)
{
MonsterName = caps(MonsterName);
if ( MonsterName == "CLOT" )
return class'ZombieClot';
if ( MonsterName == "CRAWLER" )
return class'ZombieCrawler';
if ( MonsterName == "STALKER" )
return class'ZombieStalker';
if ( MonsterName == "BLOAT" )
return class'ZombieBloat';
if ( MonsterName == "GOREFAST" )
return class'ZombieGorefast';
if ( MonsterName == "SIREN" )
return class'ZombieSiren';
if ( MonsterName == "HUSK" )
return class'ZombieHusk';
if ( MonsterName == "SCRAKE" || MonsterName == "SC" )
return class'ZombieScrake';
if ( MonsterName == "FLESHPOUND" || MonsterName == "FP" )
return class'ZombieFleshpound';
if ( MonsterName == "PAT" || MonsterName == "PATRIARCH" || MonsterName == "BOSS" )
return class'ZombieBoss';
return none;
}
function BlameAll()
{
local Controller P;
local ScrnPlayerController Player;
local ScrnCustomPRI ScrnPRI;
for ( P = Level.ControllerList; P != none; P = P.nextController ) {
Player = ScrnPlayerController(P);
if ( Player != none ) {
ScrnPRI = class'ScrnCustomPRI'.static.FindMe(Player.PlayerReplicationInfo);
if ( ScrnPRI != none ) {
Player.ReceiveLocalizedMessage(class'ScrnBalanceSrv.ScrnBlamedMsg', ScrnPRI.BlameCounter++); // more blame = bigger shit
if ( Player.PlayerReplicationInfo != none && Player.PlayerReplicationInfo.PlayerName ~= "Baron" )
Mut.BroadcastFakedAchievement(0); // blame Baron :)
}
}
}
}
// returns false if monster not found or can't be blamed
function bool BlameMonster(String MonsterName)
{
local class<KFMonster> MC;
local Controller P;
local ScrnPlayerController Player;
MC = Str2Monster(MonsterName);
// don't blame Stalkers and Patriarch, because shit on their head could reveal
// their positions
if ( MC == none || MC == class'ZombieStalker' || MC == class'ZombieBoss' )
return false;
for ( P = Level.ControllerList; P != none; P = P.nextController ) {
Player = ScrnPlayerController(P);
if ( Player != none ) {
Player.ClientMonsterBlamed(MC);
}
}
return true;
}
static function bool IsGoodReason(string Reason)
{
local string a, b;
// good reason contains from at least 2 words, one of them is at least 6 character long
// "n00b" and "screw you" aren't good reasons :)
return Divide(Reason, " ", a, b) && ( len(a) >= 6 || len(b) >= 6);
}
function bool CanEndWave()
{
local Controller C;
local MonsterController MC;
local Monster M;
local KFHumanPawn P;
local int TotalHP;
for ( C = Level.ControllerList; C != None; C = C.NextController ) {
MC = MonsterController(C);
M = Monster(C.Pawn);
if ( MC==none || M == none )
continue;
TotalHP += M.default.Health;
if ( Mut.bVoteKillCheckVisibility ) {
foreach VisibleCollidingActors(class'KFHumanPawn', P, 1000) {
if ( P.Health > 0 && P.Controller != none && P.Controller.bIsPlayer && KF_StoryNPC(P) == none && MC.CanSee(P) )
return false;
}
}
}
return TotalHP <= Mut.MaxVoteKillHP;
}
function DoEndWave()
{
local Monster M;
local int Penalty, TotalPenalty;
foreach DynamicActors(class'Monster', M) {
Penalty = max(M.ScoringValue * Mut.VoteKillPenaltyMult, 0);
VotingHandler.VotedTeam.Score -= Penalty;
TotalPenalty += Penalty;
M.KilledBy(M);
}
if ( TotalPenalty > 0 )
VotingHandler.BroadcastMessage(strEndWavePenalty $ TotalPenalty);
}
function byte GetDifficulty(out string DiffStr)
{
if ( DiffStr == "0" || DiffStr == "DEFAULT" || DiffStr == "OFF" ) {
DiffStr = "Default";
return 2;
}
else if ( DiffStr == "2" || DiffStr == "NORMAL" ) {
DiffStr = "Normal";
return 2;
}
else if ( DiffStr == "4" || DiffStr == "HARD" ) {
DiffStr = "Hard";
return 4;
}
else if ( DiffStr == "5" || DiffStr == "SUICIDAL" || DiffStr == "SUI" ) {
DiffStr = "Suicidal";
return 5;
}
else if ( DiffStr == "6" || DiffStr == "SUICIDAL+" || DiffStr == "SUI+" ) {
DiffStr = "Suicidal+";
return 6;
}
else if ( DiffStr == "7" || DiffStr == "HELLONEARTH" || DiffStr == "HOE" ) {
DiffStr = "HoE";
return 7;
}
else if ( DiffStr == "8" || DiffStr == "HELLONEARTH+" || DiffStr == "HOE+" ) {
DiffStr = "HoE+";
return 8;
}
return 255;
}
state GamePaused
{
Begin:
Level.Pauser = VotingHandler.VoteInitiator.PlayerReplicationInfo;
if ( Level.Pauser != none ) {
// tell players that game is paused
msgPause = strGamePaused;
ReplaceText(msgPause, "%s", string(PauseTime));
VotingHandler.BroadcastMessage(msgPause);
// wait for pause time ends or game resumes by other source (e.g. admin)
while ( PauseTime > 0 && Level.Pauser != none ) {
if ( PauseTime <= 5 )
VotingHandler.BroadcastMessage(String(PauseTime));
else if ( (PauseTime%30 == 0) || (PauseTime < 30 && PauseTime%10 == 0) )
VotingHandler.BroadcastMessage(PauseTime @ strSecondsLeft);
//log(Level.TimeSeconds @ "Sleep", 'ScrnBalance');
sleep(1.0);
PauseTime--;
}
// resume game after pause time ends
if ( Level.Pauser != none ) {
Level.Pauser = none;
VotingHandler.BroadcastMessage(strGameUnpaused);
}
}
GotoState('');
}
defaultproperties
{
strCantEndTrade="Can not end trade time at the current moment"
strTooLate="Too late"
strGamePaused="Game paused for %s seconds"
strSecondsLeft="seconds left"
strGameUnPaused="Game resumed"
strPauseTraderOnly="Game can be paused only during trader time!"
viResume="RESUME GAME"
viEndTrade="END TRADER TIME"
viDifficulty="Difficulty"
strZedSpawnsDoubled="ZED spawn rate doubled!"
strSquadNotFound="Monster squad with a given name not found"
strCantSpawnSquadNow="Can not spawn monsters at this moment"
strSquadList="Avaliable Squads:"
strNotInStoryMode="Not avaliable in Story Mode"
strNotInTSC="Not avaliable in TSC"
strCantEndWaveNow="Can't end the wave now"
strEndWavePenalty="Team charged for premature wave end with $"
strRCommands="R_* commands can be executed only by Referee (Admin rights + Tourney Mode)"
HelpInfo(0)="%gLOCKPERK%w|%gUNLOCKPERK %y<perk_name> %w Disables/Enables perk at the end of the wave"
HelpInfo(1)="%gLOCKTEAM%w|%gUNLOCKTEAM %w Locks/Unlocks teams. Only invited players may join locked team."
HelpInfo(2)="%gPAUSE %yX %w Pause the game for X seconds"
HelpInfo(3)="%gEND TRADE %w Immediately end current trader time and start next wave"
HelpInfo(4)="%gEND WAVE %w Kills last stuck zeds to end the wave"
HelpInfo(5)="%gBLAME %y<player_name> %b[<reason>] %w Blame player [for the <reason>]"
HelpInfo(6)="%gSPEC %y<player_name> %b[<reason>] %w Move player to spectators"
HelpInfo(7)="%gKICK %y<player_name> %b[<reason>] %w Kick player [for the <reason>]"
HelpInfo(8)="%gINVITE %y<player_name> %w Invite player to join locked team."
HelpInfo(9)="%gBORING %w Doubles ZED spawn rate"
HelpInfo(10)="%gSPAWN %y<squad_name> %w Spawns zed squad"
HelpInfo(11)="%gREADY%w|%gUNREADY %w Makes everybody ready/unready to play"
HelpInfo(12)="%gFF %yX %w Set Friendly Fire to X%"
HelpInfo(13)="%gMAP RESTART %w Restarts current map"
HelpInfo(14)="%gFAKED %yX %w Set Faked Players to X (FAKEDCOUNT+FAKEDHEALTH)"
HelpInfo(15)="%gFAKEDCOUNT %yX %w Set Faked Players for zed count calculation"
HelpInfo(16)="%gFAKEDHEALTH %yX %w Set Faked Players for zed health calculation"
HelpInfo(17)="%gDIFF %yX %w Changes map difficulty (2-8) for the next map"
bAlwaysTick=True
}