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

2182 lines
53 KiB
Ucode

// ====================================================================
// (C) 2002, Epic Games
// ====================================================================
class ExtendedConsole extends Console;
#exec OBJ LOAD FILE=ROMenuSounds.uax
#exec OBJ LOAD FILE=KF_InterfaceArt_tex.utx
// if _RO_
// else
//#exec OBJ LOAD FILE=InterfaceContent.utx
// end if _RO_
// Visible Console stuff
var globalconfig int MaxScrollbackSize;
var array<string> Scrollback;
var int SBHead, SBPos; // Where in the scrollback buffer are we
var bool bCtrl, bAlt, bShift;
var bool bConsoleHotKey;
var float ConsoleSoundVol;
var localized string AddedCurrentHead;
var localized string AddedCurrentTail;
var localized string ServerFullMsg;
////// Speech Menu
var float SMLineSpace;
var enum ESpeechMenuState
{
SMS_Main,
SMS_VoiceChat, // List of voice chat groups on the server
SMS_Ack,
SMS_FriendFire,
SMS_Order,
SMS_Other,
SMS_Taunt,
SMS_TauntAnim,
SMS_PlayerSelect,
SMS_VoiceChatChannel // List of options for this channel (public & private)
} SMState;
// These are put together using the menu and sent to the 'Speech' exec command.
var name SMType;
var int SMIndex;
var string SMCallsign;
var int SMOffset;
var string SMNameArray[48];
var int SMIndexArray[48];
var int SMArraySize;
var config float SMOriginX;
var config float SMOriginY;
var float SMMargin, SMTab;
// if _RO_
var localized string SMStateName[20];
// else
// var localized string SMStateName[10];
// end if _RO_
var localized string SMChannelOptions[3];
var array<VoiceChatRoom> VoiceChannels;
var localized string SMAllString;
var localized string SMMoreString;
var sound SMOpenSound;
var sound SMAcceptSound;
var sound SMDenySound;
var config EInputKey LetterKeys[10];
var EInputKey NumberKeys[10];
var config bool bSpeechMenuUseLetters;
var config bool bSpeechMenuUseMouseWheel;
var bool bSpeechMenuLocked;
var int HighlightRow;
////// End Speech Menu
struct StoredPassword
{
var config string Server,
Password;
};
struct ServerFavorite
{
var() config int ServerID;
var() config string IP;
var() config int Port;
var() config int QueryPort;
var() config string ServerName;
};
var() protected config array<ServerFavorite> Favorites;
var config array<StoredPassword> SavedPasswords;
var config string PasswordPromptMenu;
var string LastConnectedServer,
LastURL;
struct ChatStruct
{
var string Message;
var int team;
};
var array<ChatStruct> ChatMessages;
var config string ChatMenuClass;
var transient GUIPage ChatMenu;
var bool bTeamChatOnly;
// RO
//var transient UT2MusicManager MusicManager; // Obsolete
var config string StatsPromptMenuClass; // Menu that appears when connecting to a stats enabled server
var config string MusicManagerClassName;
var config string WaitingGameClassName;
var config string NeedPasswordMenuClass; // Menu that appears when connecting to a passworded server
var config string ServerInfoMenu; // Menu that appears when press F2
// _RO_
var config string SteamLoginMenuClass; // Menu that appears when you need to relogin to Steam
var int SteamLoginRetryCount; // Number of times the client has tried to autoreconnect when they get a SteamAuthStalled error
// end _RO_
delegate OnChat(string Msg, int TeamIndex);
function OnStatsClosed(optional bool bCancelled)
{
if ( bCancelled )
return;
OnStatsConfigured();
}
function OnStatsConfigured()
{
// DelayedConsoleCommand("reconnect");
ViewportOwner.GUIController.CloseAll(false);
ViewportOwner.Actor.ClientTravel(LastURL,TRAVEL_Absolute,false);
}
event ConnectFailure(string FailCode,string URL)
{
local string Error, Server;
local int i,Index;
LastURL = URL;
Server = Left(URL,InStr(URL,"/"));
i = instr(FailCode," ");
if (i>0)
{
Error = Right(FailCode,len(FailCode)-i-1);
FailCode = Left(FailCode,i);
}
log("Connect Failure: "@FailCode$"["$Error$"] ("$URL$")");
if(FailCode == "NEEDPW")
{
for(Index = 0;Index < SavedPasswords.Length;Index++)
{
if(SavedPasswords[Index].Server == Server)
{
ViewportOwner.Actor.ClearProgressMessages();
ViewportOwner.Actor.ClientTravel(URL$"?password="$SavedPasswords[Index].Password,TRAVEL_Absolute,false);
return;
}
}
LastConnectedServer = Server;
if ( ViewportOwner.GUIController.OpenMenu(NeedPasswordMenuClass, URL, FailCode) )
return;
}
else if(FailCode == "WRONGPW")
{
ViewportOwner.Actor.ClearProgressMessages();
for(Index = 0;Index < SavedPasswords.Length;Index++)
{
if(SavedPasswords[Index].Server == Server)
{
SavedPasswords.Remove(Index,1);
SaveConfig();
}
}
LastConnectedServer = Server;
if ( ViewportOwner.GUIController.OpenMenu(NeedPasswordMenuClass, URL, FailCode) )
return;
}
else if(FailCode == "NEEDSTATS")
{
ViewportOwner.Actor.ClearProgressMessages();
if ( ViewportOwner.GUIController.OpenMenu(StatsPromptMenuClass, "", FailCode) )
{
GUIController(ViewportOwner.GUIController).ActivePage.OnReopen = OnStatsConfigured;
return;
}
}
else if ( FailCode == "LOCALBAN" )
{
ViewportOwner.Actor.ClearProgressMessages();
ViewportOwner.GUIController.OpenMenu(class'GameEngine'.default.DisconnectMenuClass,Localize("Errors","ConnectionFailed","Engine"),class'AccessControl'.default.IPBanned);
return;
}
else if ( FailCode == "SESSIONBAN" )
{
ViewportOwner.Actor.ClearProgressMessages();
ViewportOwner.GUIController.OpenMenu(class'GameEngine'.default.DisconnectMenuClass,Localize("Errors","ConnectionFailed","Engine"),class'AccessControl'.default.SessionBanned);
return;
}
else if ( FailCode == "SERVERFULL" )
{
ViewportOwner.Actor.ClearProgressMessages();
ViewportOwner.GUIController.OpenMenu(class'GameEngine'.default.DisconnectMenuClass,ServerFullMsg);
return;
}
else if ( FailCode == "CHALLENGE" )
{
ViewportOwner.Actor.ClearProgressMessages();
ViewportOwner.Actor.ClientNetworkMessage("FC_Challege","");
return;
}
// _RO_
else if ( FailCode == "STEAMLOGGEDINELSEWHERE" )
{
ViewportOwner.Actor.ClearProgressMessages();
LastConnectedServer = Server;
if ( ViewportOwner.GUIController.OpenMenu(SteamLoginMenuClass, URL, FailCode) )
return;
}
else if ( FailCode == "STEAMVACBANNED" )
{
ViewportOwner.Actor.ClearProgressMessages();
ViewportOwner.Actor.ClientNetworkMessage("ST_VACBan","");
return;
}
else if ( FailCode == "STEAMVALIDATIONSTALLED")
{
// Lame hack for a Steam problem. Take this out when Valve fixes the SteamValidationStalled bug
if( SteamLoginRetryCount < 5 )
{
SteamLoginRetryCount++;
ViewportOwner.Actor.ClientTravel( URL,TRAVEL_Absolute,false);
ViewportOwner.GUIController.CloseAll(false,True);
return;
}
else
{
ViewportOwner.Actor.ClearProgressMessages();
ViewportOwner.Actor.ClientNetworkMessage("ST_Unknown","");
return;
}
}
else if ( FailCode == "STEAMAUTH" /*|| FailCode == "STEAMVALIDATIONSTALLED"*/)
{
ViewportOwner.Actor.ClearProgressMessages();
ViewportOwner.Actor.ClientNetworkMessage("ST_Unknown","");
return;
}
// end _RO_
log("Unhandled connection failure! FailCode '"$FailCode@"' URL '"$URL$"'");
ViewportOwner.Actor.ProgressCommand("menu:"$class'GameEngine'.default.DisconnectMenuClass,FailCode,Error);
}
event NotifyLevelChange()
{
Super.NotifyLevelChange();
if ( VoiceChannels.Length > 0 )
VoiceChannels.Remove(0, VoiceChannels.Length);
}
////// End Speech Menu
exec function CLS()
{
SBHead = 0;
ScrollBack.Remove(0,ScrollBack.Length);
}
function PostRender( canvas Canvas ); // Subclassed in state
function Chat(coerce string Msg, float MsgLife, PlayerReplicationInfo PRI)
{
local int index;
Message(Msg,MsgLife); // For compatibility
Index = ChatMessages.Length;
ChatMessages.Length = Index+1;
ChatMessages[Index].Message = Msg;
if ( (PRI != None) && (PRI.Team!=None) )
ChatMessages[Index].Team = PRI.Team.TeamIndex;
else
ChatMessages[Index].Team = 2;
if ( (!bTeamChatOnly) || (PRI == None) || (PRI.Team==None) || (PRI.Team == ViewportOwner.Actor.PlayerReplicationInfo.Team) )
{
OnChat(Msg, ChatMessages[Index].team);
OnChatMessage(Msg);
}
if (ChatMessages.Length>100)
ChatMessages.Remove(0,1);
}
delegate OnChatMessage(string Msg);
event Message( coerce string Msg, float MsgLife)
{
if (ScrollBack.Length==MaxScrollBackSize) // if full, Remove Entry 0
{
ScrollBack.Remove(0,1);
SBHead = MaxScrollBackSize-1;
}
else
SBHead++;
ScrollBack.Length = ScrollBack.Length + 1;
Scrollback[SBHead] = Msg;
Super.Message(Msg,MsgLife);
}
event bool KeyEvent( EInputKey Key, EInputAction Action, FLOAT Delta )
{
if (Key==ConsoleHotKey)
{
if(Action==IST_Release)
ConsoleOpen();
return true;
}
return Super.KeyEvent(Key,Action,Delta);
}
function PlayConsoleSound(Sound S)
{
if(ViewportOwner == None || ViewportOwner.Actor == None || ViewportOwner.Actor.Pawn == None)
return;
ViewportOwner.Actor.ClientPlaySound(S);//,true,ConsoleSoundVol);
}
//-----------------------------------------------------------------------------
// State used while typing a command on the console.
event NativeConsoleOpen()
{
ConsoleOpen();
}
exec function ConsoleOpen()
{
UnPressButtons();
TypedStr = "";
TypedStrPos = 0;
bCtrl = False;
bAlt = False;
bShift = False;
GotoState('ConsoleVisible');
PlayConsoleSound(SMOpenSound);
}
exec function ConsoleClose()
{
TypedStr="";
TypedStrPos = 0;
bCtrl = False;
bAlt = False;
bShift = False;
if( GetStateName() == 'ConsoleVisible' )
{
PlayConsoleSound(SMDenySound);
GotoState( '' );
}
}
exec function ConsoleToggle()
{
log("console toggle");
UnPressButtons();
if( GetStateName() == 'ConsoleVisible' )
ConsoleClose();
else
ConsoleOpen();
}
state ConsoleVisible
{
function bool KeyType( EInputKey Key, optional string Unicode )
{
local PlayerController PC;
if (bIgnoreKeys || bConsoleHotKey)
return true;
if (ViewportOwner != none)
PC = ViewportOwner.Actor;
if (bCtrl && PC != none)
{
if (Key == 3) //copy
{
PC.CopyToClipboard(TypedStr);
return true;
}
else if (Key == 22) //paste
{
TypedStr $= PC.PasteFromClipboard();
TypedStrPos += Len(PC.PasteFromClipboard());
return true;
}
else if (Key == 24) // cut
{
PC.CopyToClipboard(TypedStr);
TypedStr="";
TypedStrPos = 0;
return true;
}
}
if( Key>=0x20 )
{
if( Unicode != "" )
TypedStr = Left(TypedStr, TypedStrPos) $ Unicode $ Right(TypedStr, Len(TypedStr) - TypedStrPos);
else
TypedStr = Left(TypedStr, TypedStrPos) $ Chr(Key) $ Right(TypedStr, Len(TypedStr) - TypedStrPos);
TypedStrPos++;
return( true );
}
return( true );
}
function bool KeyEvent( EInputKey Key, EInputAction Action, FLOAT Delta )
{
local string Temp;
local int i;
if ( Action == IST_Release )
{
if ( Key == ConsoleHotKey )
{
if ( bConsoleHotKey ) ConsoleClose();
return True;
}
switch ( Key )
{
case IK_Ctrl:
bCtrl = False;
break;
case IK_Alt:
bAlt = False;
break;
case IK_Shift:
bShift = False;
break;
case IK_Escape:
if ( TypedStr != "" )
{
TypedStr = "";
TypedStrPos = 0;
HistoryCur = HistoryTop;
}
else ConsoleClose();
return True;
default:
return True;
}
}
else if ( Action == IST_Press )
{
bIgnoreKeys = False;
if ( Key == ConsoleHotKey )
{
bConsoleHotKey = True;
return True;
}
switch ( Key )
{
case IK_Ctrl:
bCtrl = True;
break;
case IK_Alt:
bAlt = True;
break;
case IK_Shift:
bShift = True;
break;
case IK_Escape:
return True;
case IK_Enter:
if( TypedStr!="" )
{
// Print to console.
History[HistoryTop] = TypedStr;
HistoryTop = (HistoryTop+1) % ArrayCount(History);
if ( ( HistoryBot == -1) || ( HistoryBot == HistoryTop ) )
HistoryBot = (HistoryBot+1) % ArrayCount(History);
HistoryCur = HistoryTop;
// Make a local copy of the string.
Temp=TypedStr;
TypedStr="";
TypedStrPos=0;
if( !ConsoleCommand( Temp ) )
Message( Localize("Errors","Exec","Core"), 6.0 );
Message( "", 6.0 );
}
return true;
case IK_Up:
if ( HistoryBot >= 0 )
{
if (HistoryCur == HistoryBot)
HistoryCur = HistoryTop;
else
{
HistoryCur--;
if (HistoryCur<0)
HistoryCur = ArrayCount(History)-1;
}
TypedStr = History[HistoryCur];
TypedStrPos = Len(TypedStr);
}
return true;
case IK_Down:
if ( HistoryBot >= 0 )
{
if (HistoryCur == HistoryTop)
HistoryCur = HistoryBot;
else
HistoryCur = (HistoryCur+1) % ArrayCount(History);
TypedStr = History[HistoryCur];
TypedStrPos = Len(TypedStr);
}
return True;
case IK_Backspace:
if( TypedStrPos > 0 )
{
TypedStr = Left(TypedStr,TypedStrPos-1)$Right(TypedStr, Len(TypedStr) - TypedStrPos);
TypedStrPos--;
}
return true;
case IK_Delete:
if ( TypedStrPos < Len(TypedStr) )
TypedStr = Left(TypedStr,TypedStrPos)$Right(TypedStr, Len(TypedStr) - TypedStrPos - 1);
return true;
case IK_Left:
i = TypedStrPos - 1;
if ( bCtrl )
while ( i > 0 && Mid(TypedStrPos,i,1) != " " )
i--;
TypedStrPos = Max(0, i);
return true;
case IK_Right:
i = TypedStrPos + 1;
if ( bCtrl )
while ( i <= Len(TypedStr) && Mid(TypedStr,i,1) != " " )
i++;
TypedStrPos = Min(Len(TypedStr), i);
return true;
case IK_Home:
TypedStrPos = 0;
return true;
case IK_End:
TypedStrPos = Len(TypedStr);
return true;
case IK_PageUp:
case IK_MouseWheelUp:
if (SBPos<ScrollBack.Length-1)
{
if (bCtrl)
SBPos+=5;
else
SBPos++;
if (SBPos>=ScrollBack.Length)
SBPos = ScrollBack.Length-1;
}
return true;
case IK_PageDown:
case IK_MouseWheelDown:
if (SBPos>0)
{
if (bCtrl)
SBPos-=5;
else
SBPos--;
if (SBPos<0)
SBPos = 0;
}
}
}
return True;
}
function BeginState()
{
SBPos = 0;
bVisible= true;
bIgnoreKeys = true;
bConsoleHotKey = false;
HistoryCur = HistoryTop;
bCtrl = false;
}
function EndState()
{
bVisible = false;
bCtrl = false;
bConsoleHotKey = false;
}
function PostRender( canvas Canvas )
{
local float fw,fh;
local float yclip,y;
local int idx;
Canvas.Font = class'HudBase'.static.GetConsoleFont(Canvas);
yclip = canvas.ClipY*0.5;
Canvas.StrLen("X",fw,fh);
Canvas.SetPos(-5,-5);
Canvas.SetDrawColor(255,255,255,255);
Canvas.Style=1;
// if _RO_
Canvas.DrawTileStretched(Texture'KF_InterfaceArt_tex.Menu.thin_border_SlightTransparent',Canvas.ClipX + 10,yClip + 7);
// else
// Canvas.DrawTileStretched(material'ConsoleBack',Canvas.ClipX,yClip);
// end if _RO_
Canvas.Style=1;
Canvas.SetPos(0,yclip-1);
Canvas.SetDrawColor(255,255,255,255);
// if _RO_
//Canvas.DrawTile(Texture'InterfaceArt_tex.Menu.RODisplay',Canvas.ClipX,2,0,0,64,2);
// else
// Canvas.DrawTile(texture 'InterfaceContent.Menu.BorderBoxA',Canvas.ClipX,2,0,0,64,2);
// end if _RO_
Canvas.SetDrawColor(255,255,255,255);
Canvas.SetPos(0,yclip-5-fh);
Canvas.DrawTextClipped("(>"@Left(TypedStr, TypedStrPos)$chr(4)$Eval( TypedStrPos < Len(TypedStr), Mid(TypedStr, TypedStrPos), "_"), true);
idx = SBHead - SBPos;
y = yClip-y-5-(fh*2);
if (ScrollBack.Length==0)
return;
Canvas.SetDrawColor(255,255,255,255);
while (y>fh && idx>=0)
{
Canvas.SetPos(0,y);
Canvas.DrawText(Scrollback[idx],false);
idx--;
y-=fh;
}
}
}
//---------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------//
delegate OnExecAddFavorite( ServerFavorite Fav );
exec function AddCurrentToFavorites()
{
local string address, ipString, portString;
local int colonPos, portNum;
local ServerFavorite NewFav;
if( ViewportOwner == None || ViewportOwner.Actor == None )
return;
// Get current network address
address = ViewportOwner.Actor.GetServerNetworkAddress();
if(address == "")
return;
// Parse text to find IP and possibly port number
colonPos = InStr(address, ":");
if(colonPos < 0)
{
// No colon - assume port 7777
ipString = address;
portNum = 7777;
}
else
{ // Parse out port number
ipString = Left(address, colonPos);
portString = Mid(address, colonPos+1);
portNum = int(portString);
}
NewFav.IP = ipString;
NewFav.Port = portNum;
NewFav.QueryPort = portNum + 1;
if ( AddFavorite( NewFav ) )
ViewportOwner.Actor.ClientMessage(AddedCurrentHead@address@AddedCurrentTail);
OnExecAddFavorite( NewFav );
}
static function bool InFavorites( ServerFavorite Fav )
{
local int i;
if ( Fav.IP == "" )
return false;
if ( Fav.Port == 0 )
Fav.Port = 7777;
if ( Fav.QueryPort == 0 )
Fav.QueryPort = Fav.Port + 1;
for ( i = 0; i < default.Favorites.Length; i++ )
{
if ( Fav.IP == default.Favorites[i].IP &&
Fav.Port == default.Favorites[i].Port &&
Fav.QueryPort == default.Favorites[i].QueryPort )
return true;
}
return false;
}
// Returns true only if this was a new server
static function bool AddFavorite( ServerFavorite NewFav )
{
local int i;
local bool bNew;
if ( NewFav.IP == "" )
return false;
if ( NewFav.Port == 0 )
NewFav.Port = 7777;
if ( NewFav.QueryPort == 0 )
NewFav.QueryPort = NewFav.Port + 1;
bNew = True;
for ( i = 0; i < default.Favorites.Length; i++ )
{
if ( NewFav.IP == default.Favorites[i].IP &&
NewFav.Port == default.Favorites[i].Port &&
NewFav.QueryPort == default.Favorites[i].QueryPort )
{
if ( NewFav.ServerName ~= default.Favorites[i].ServerName )
return false;
bNew = False;
break;
}
}
default.Favorites[i] = NewFav;
StaticSaveConfig();
return bNew;
}
static function bool RemoveFavorite( string IP, int Port, int QueryPort )
{
local int i;
for ( i = 0; i < default.Favorites.Length; i++ )
{
if ( default.Favorites[i].IP == IP && default.Favorites[i].Port == Port && default.Favorites[i].QueryPort == QueryPort )
{
default.Favorites.Remove(i,1);
StaticSaveConfig();
return true;
}
}
return false;
}
static function GetFavorites( out array<ServerFavorite> List )
{
List = default.Favorites;
}
static function SaveFavorites()
{
// TODO: Add bDirty tracking, to only save if favorites have actually been modified
StaticSaveConfig();
}
//---------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------//
exec function SpeechMenuToggle()
{
// Don't show speech menu if no voice pack type
if( ViewportOwner.Actor.PlayerReplicationInfo.bOnlySpectator || (ViewportOwner.Actor.PlayerReplicationInfo.VoiceType == None) )
return;
GotoState('SpeechMenuVisible');
}
state SpeechMenuVisible
{
exec function SpeechMenuToggle()
{
GotoState('');
}
function bool KeyType( EInputKey Key, optional string Unicode )
{
if (bIgnoreKeys)
return true;
return false;
}
function class<TeamVoicePack> GetVoiceClass()
{
if(ViewportOwner == None || ViewportOwner.Actor == None || ViewportOwner.Actor.PlayerReplicationInfo == None)
return None;
return class<TeamVoicePack>(ViewportOwner.Actor.PlayerReplicationInfo.VoiceType);
}
// JTODO: Bubble sort. Sorry. But I already wrote the GUIList sort today and its late.
function SortSMArray()
{
local int i,j, tmpInt;
local string tmpString;
for(i=0; i<SMArraySize-1; i++)
{
for(j=i+1; j<SMArraySize; j++)
{
if(SMNameArray[i] > SMNameArray[j])
{
tmpString = SMNameArray[i];
SMNameArray[i] = SMNameArray[j];
SMNameArray[j] = tmpString;
tmpInt = SMIndexArray[i];
SMIndexArray[i] = SMIndexArray[j];
SMIndexArray[j] = tmpInt;
}
}
}
}
// Rebuild the array of options based on the state we are now in.
function RebuildSMArray()
{
local int i, index;
local class<TeamVoicePack> tvp;
local GameReplicationInfo GRI;
local PlayerReplicationInfo MyPRI;
local VoiceChatReplicationInfo VRI;
local UnrealPlayer up;
local name GameMesgGroup;
local Pawn TauntPawn;
local bool bShowJoin, bShowLeave, bShowTalk;
SMArraySize = 0;
SMOffset=0;
tvp = GetVoiceClass();
if(tvp == None)
return;
//Log("TVP:"$tvp$" NumTaunts:"$tvp.Default.numTaunts);
switch (SMState)
{
case SMS_Main:
if ( VoiceChatAllowed() )
{
SMNameArray[SMArraySize] = SMStateName[1];
SMIndexArray[SMArraySize] = 1;
SMArraySize++;
}
if ( ViewportOwner.Actor.PlayerReplicationInfo != None && !ViewportOwner.Actor.PlayerReplicationInfo.bOnlySpectator )
{
for(i=2; i<7; i++)
{
SMNameArray[SMArraySize] = SMStateName[i];
SMIndexArray[SMArraySize] = i;
SMArraySize++;
}
if ( (ViewportOwner.Actor.Pawn != None) && !ViewportOwner.Actor.Pawn.IsA('RedeemerWarhead') )
{
SMNameArray[SMArraySize] = SMStateName[7];
SMIndexArray[SMArraySize] = 7;
SMArraySize++;
}
}
if ( SMArraySize == 0 )
GotoState('');
break;
case SMS_Taunt:
for(i=0; i<tvp.Default.numTaunts; i++)
{
if(tvp.Default.MatureTaunt[i] == 1 && ViewportOwner.Actor.bNoMatureLanguage)
continue;
if(tvp.Default.TauntAbbrev[i] != "")
SMNameArray[SMArraySize] = tvp.Default.TauntAbbrev[i];
else
SMNameArray[SMArraySize] = tvp.Default.TauntString[i];
SMIndexArray[SMArraySize] = i;
SMArraySize++;
}
SortSMArray();
break;
case SMS_Ack:
for(i=0; i<tvp.Default.numAcks; i++)
{
if (tvp.Default.AckAbbrev[i] != "")
SMNameArray[SMArraySize] = tvp.Default.AckAbbrev[i];
else
SMNameArray[SMArraySize] = tvp.Default.AckString[i];
SMIndexArray[SMArraySize] = i;
SMArraySize++;
}
SortSMArray();
break;
case SMS_FriendFire:
for(i=0; i<tvp.Default.numFFires; i++)
{
if(tvp.Default.FFireAbbrev[i] != "")
SMNameArray[SMArraySize] = tvp.Default.FFireAbbrev[i];
else
SMNameArray[SMArraySize] = tvp.Default.FFireString[i];
SMIndexArray[SMArraySize] = i;
SMArraySize++;
}
SortSMArray();
break;
case SMS_Order:
for(i=0; i<9; i++)
{
if(tvp.Default.OrderSound[i] == None)
continue;
index = tvp.static.OrderToIndex(i, ViewportOwner.Actor.Level.GetGameClass());
if(tvp.Default.OrderAbbrev[index] != "")
SMNameArray[SMArraySize] = tvp.Default.OrderAbbrev[index];
else
SMNameArray[SMArraySize] = tvp.Default.OrderString[index];
SMIndexArray[SMArraySize] = index;
SMArraySize++;
}
break;
case SMS_Other:
GameMesgGroup = ViewportOwner.Actor.Level.GetGameClass().Default.OtherMesgGroup;
for(i=0; i<ArrayCount(tvp.Default.OtherString); i++)
{
if(tvp.Default.OtherSound[i] == None)
continue;
// If we have defined a group for this message, only put it in the menu if it matches the current game group.
if(tvp.Default.OtherMesgGroup[i] != '' && tvp.Default.OtherMesgGroup[i] != GameMesgGroup)
continue;
if(tvp.Default.OtherAbbrev[i] != "")
SMNameArray[SMArraySize] = tvp.Default.OtherAbbrev[i];
else
SMNameArray[SMArraySize] = tvp.Default.OtherString[i];
SMIndexArray[SMArraySize] = i;
SMArraySize++;
}
break;
case SMS_PlayerSelect:
if(ViewportOwner == None || ViewportOwner.Actor == None || ViewportOwner.Actor.PlayerReplicationInfo == None)
return;
GRI = ViewportOwner.Actor.GameReplicationInfo;
MyPRI = ViewportOwner.Actor.PlayerReplicationInfo;
// First entry is to send to 'all'
// HACK: Don't let you send 'Hold This Position' to all all bots
if( SMIndex != 1)
{
SMNameArray[SMArraySize] = SMAllString;
SMArraySize++;
}
for(i=0; i<GRI.PRIArray.Length; i++)
{
if ( GRI.bTeamGame )
{
// Dont put player on list if myself, not on a team, on the same team, or a spectator.
if( GRI.PRIArray[i].Team == None || MyPRI.Team == None )
continue;
if( GRI.PRIArray[i].Team.TeamIndex != MyPRI.Team.TeamIndex )
continue;
}
if( GRI.PRIArray[i].TeamId == MyPRI.TeamId )
continue;
if( GRI.PRIArray[i].bOnlySpectator )
continue;
SMNameArray[SMArraySize] = GRI.PRIArray[i].PlayerName;
SMArraySize++;
// Dont need a number- we use the name direct
}
break;
case SMS_TauntAnim:
if(ViewportOwner == None || ViewportOwner.Actor == None)
return;
up = UnrealPlayer(ViewportOwner.Actor);
if(up == None || up.Pawn == None)
return;
if ( Vehicle(up.Pawn) != None )
TauntPawn = Vehicle(up.Pawn).Driver;
else
TauntPawn = up.Pawn;
for(i=0; i<TauntPawn.TauntAnims.Length; i++)
{
SMNameArray[SMArraySize] = TauntPawn.TauntAnimNames[Clamp(i,0,15)]; // clamped because taunt array is max 8, see Pawn.uc
SMIndexArray[SMArraySize] = i;
SMArraySize++;
}
SortSMArray();
break;
case SMS_VoiceChat:
if( ViewportOwner == None || ViewportOwner.Actor == None ||
ViewportOwner.Actor.PlayerReplicationInfo == None || ViewportOwner.Actor.VoiceReplicationInfo == None)
{
log("VoiceChatChannel not displaying. ViewportOwner:"$ViewportOwner@"Actor:"$ViewportOwner.Actor@"MyPRI:"$ViewportOwner.Actor.PlayerReplicationInfo@"VRI:"$ViewportOwner.Actor.VoiceReplicationInfo,'VoiceChat');
return;
}
VRI = ViewportOwner.Actor.VoiceReplicationInfo;
MyPRI = ViewportOwner.Actor.PlayerReplicationInfo;
VoiceChannels = VRI.GetChannels();
for ( i = 0; i < VoiceChannels.Length; i++ )
{
if ( VoiceChannels[i].CanJoinChannel(MyPRI) )
{
bShowTalk = True;
if ( VoiceChannels[i].IsMember(MyPRI, True) )
bShowLeave = True;
else bShowJoin = True;
}
}
// Only display talk option if there are any channels that we can talk in.
if ( bShowTalk )
{
// Store the currently selected channel name
SMNameArray[SMArraySize] = SMChannelOptions[2]; // Talk
SMIndexArray[SMArraySize] = 2;
SMArraySize++;
}
// Only display join option if there are any channels that we can join
if ( bShowJoin )
{
SMNameArray[SMArraySize] = SMChannelOptions[0]; // Join
SMIndexArray[SMArraySize] = 0;
SMArraySize++;
}
// Only display leave option if we are a member of any channels
if ( bShowLeave )
{
SMNameArray[SMArraySize] = SMChannelOptions[1]; // Leave
SMIndexArray[SMArraySize] = 1;
SMArraySize++;
}
break;
case SMS_VoiceChatChannel:
if( ViewportOwner == None || ViewportOwner.Actor == None ||
ViewportOwner.Actor.VoiceReplicationInfo == None)
{
log(Name@"No VoiceReplicationInfo so not generating VoiceChat menu",'VoiceChat');
return;
}
VRI = ViewportOwner.Actor.VoiceReplicationInfo;
MyPRI = ViewportOwner.Actor.PlayerReplicationInfo;
SMStateName[ESpeechMenuState.EnumCount - 1] = SMChannelOptions[SMIndex];
switch ( SMIndex )
{
case 0: // Join
VoiceChannels = VRI.GetChannels();
for ( i = 0; i < VoiceChannels.Length; i++ )
{
if ( VoiceChannels[i].CanJoinChannel(MyPRI) && !VoiceChannels[i].IsMember(MyPRI, True) )
{
SMNameArray[SMArraySize] = VoiceChannels[i].GetTitle();
SMIndexArray[SMArraySize] = VoiceChannels[i].ChannelIndex;
SMArraySize++;
}
}
break;
case 1: // Leave
VoiceChannels = VRI.GetChannels();
for ( i = 0; i < VoiceChannels.Length; i++ )
{
if ( VoiceChannels[i].CanJoinChannel(MyPRI) && VoiceChannels[i].IsMember(MyPRI, True) )
{
SMNameArray[SMArraySize] = VoiceChannels[i].GetTitle();
SMIndexArray[SMArraySize] = VoiceChannels[i].ChannelIndex;
SMArraySize++;
}
}
break;
case 2: // Talk
VoiceChannels = VRI.GetChannels();
for ( i = 0; i < VoiceChannels.Length; i++ )
{
if ( VoiceChannels[i].CanJoinChannel(MyPRI) )
{
SMNameArray[SMArraySize] = VoiceChannels[i].GetTitle();
SMIndexArray[SMArraySize] = VoiceChannels[i].ChannelIndex;
SMArraySize++;
}
}
break;
}
break;
}
}
//////////////////////////////////////////////
function EnterState(ESpeechMenuState newState, optional bool bNoSound)
{
SMState = newState;
HighlightRow = 0;
RebuildSMArray();
if(!bNoSound)
PlayConsoleSound(SMAcceptSound);
}
function LeaveState() // Go up a level
{
PlayConsoleSound(SMDenySound);
switch ( SMState )
{
case SMS_Main:
CloseSpeechMenu();
break;
case SMS_PlayerSelect:
EnterState(SMS_Order, true);
break;
case SMS_VoiceChatChannel:
EnterState(SMS_VoiceChat,True);
break;
default:
EnterState(SMS_Main, True);
}
}
// // // // // //
function HandleInput(int keyIn)
{
local int selectIndex;
local UnrealPlayer up;
local Pawn TauntPawn;
local VoiceChatReplicationInfo VRI;
// GO BACK - previous state (might back out of menu);
if(keyIn == -1)
{
HighlightRow = 0;
LeaveState();
return;
}
// TOP LEVEL - we just enter a new state
if(SMState == SMS_Main)
{
switch( SMNameArray[keyIn-1] )
{
case SMStateName[1]: SMType = ''; if ( VoiceChatAllowed() ) EnterState( SMS_VoiceChat ); break;
case SMStateName[2]: SMType = 'ACK'; EnterState(SMS_Ack); break;
case SMStateName[3]: SMType = 'FRIENDLYFIRE'; EnterState(SMS_FriendFire); break;
case SMStateName[4]: SMType = 'ORDER'; EnterState(SMS_Order); break;
case SMStateName[5]: SMType = 'OTHER'; EnterState(SMS_Other); break;
case SMStateName[6]: SMType = 'TAUNT'; EnterState(SMS_Taunt); break;
case SMStateName[7]: SMType = ''; EnterState(SMS_TauntAnim); break;
}
return;
}
// Next page on the same level
if(keyIn == 0 )
{
// Check there is a next page!
if(SMArraySize - SMOffset > 9)
SMOffset += 9;
return;
}
// Previous page on the same level
if(keyIn == -2)
{
SMOffset = Max(SMOffset - 9, 0);
return;
}
// Otherwise - we have selected something!
selectIndex = SMOffset + keyIn - 1;
if(selectIndex < 0 || selectIndex >= SMArraySize) // discard - out of range selections.
return;
switch ( SMState )
{
case SMS_Order:
SMIndex = SMIndexArray[selectIndex];
EnterState(SMS_PlayerSelect);
break;
case SMS_VoiceChat:
SMIndex = SMIndexArray[selectIndex];
EnterState(SMS_VoiceChatChannel);
break;
case SMS_VoiceChatChannel:
VRI = ViewportOwner.Actor.VoiceReplicationInfo;
if (VRI == None)
return;
// Perform the action selected
switch ( SMIndex )
{
case 0: // Join Channel
ViewportOwner.Actor.Join(SMNameArray[selectIndex],"");
break;
case 1: // Leave Channel
ViewportOwner.Actor.Leave(SMNameArray[selectIndex]);
break;
case 2:
ViewportOwner.Actor.Speak(SMNameArray[selectIndex]);
break;
}
// Add confirmation
PlayConsoleSound(SMAcceptSound);
CloseSpeechMenu();
break;
case SMS_PlayerSelect:
if(SMNameArray[selectIndex] == SMAllString)
ViewportOwner.Actor.Speech(SMType, SMIndex, "");
else
ViewportOwner.Actor.Speech(SMType, SMIndex, SMNameArray[selectIndex]);
PlayConsoleSound(SMAcceptSound);
CloseSpeechMenu(); // Close menu after message
break;
case SMS_TauntAnim:
up = UnrealPlayer(ViewportOwner.Actor);
if ( Vehicle(up.Pawn) != None )
TauntPawn = Vehicle(up.Pawn).Driver;
else
TauntPawn = up.Pawn;
up.Taunt( TauntPawn.TauntAnims[ SMIndexArray[selectIndex] ] );
PlayConsoleSound(SMAcceptSound);
CloseSpeechMenu();
break;
default:
ViewportOwner.Actor.Speech(SMType, SMIndexArray[selectIndex], "");
PlayConsoleSound(SMAcceptSound);
CloseSpeechMenu();
}
}
//////////////////////////////////////////////
function string NumberToString(int num)
{
local EInputKey key;
local string s;
if(num < 0 || num > 9)
return "";
if(bSpeechMenuUseLetters)
key = LetterKeys[num];
else
key = NumberKeys[num];
s = ViewportOwner.Actor.ConsoleCommand( "LOCALIZEDKEYNAME"@string(int(key)) );
return s;
}
function DrawNumbers( canvas Canvas, int NumNums, bool IncZero, bool sizing, out float XMax, out float YMax )
{
local int i;
local float XPos, YPos;
local float XL, YL;
XPos = Canvas.ClipX * (SMOriginX+SMMargin);
YPos = Canvas.ClipY * (SMOriginY+SMMargin);
Canvas.SetDrawColor(128,255,128,255);
for(i=0; i<NumNums; i++)
{
Canvas.SetPos(XPos, YPos);
if(!sizing)
Canvas.DrawText(NumberToString(i+1)$"-", false);
else
{
Canvas.TextSize(NumberToString(i+1)$"-", XL, YL);
XMax = Max(XMax, XPos + XL);
YMax = Max(YMax, YPos + YL);
}
YPos += SMLineSpace;
}
if(IncZero)
{
Canvas.SetPos(XPos, YPos);
if(!sizing)
Canvas.DrawText(NumberToString(0)$"-", false);
XPos += SMTab;
Canvas.SetPos(XPos, YPos);
if(!sizing)
Canvas.DrawText(SMMoreString, false);
else
{
Canvas.TextSize(SMMoreString, XL, YL);
XMax = Max(XMax, XPos + XL);
YMax = Max(YMax, YPos + YL);
}
}
}
function DrawCurrentArray( canvas Canvas, bool sizing, out float XMax, out float YMax )
{
local int i, stopAt;
local float XPos, YPos;
local float XL, YL;
XPos = (Canvas.ClipX * (SMOriginX+SMMargin)) + SMTab;
YPos = Canvas.ClipY * (SMOriginY+SMMargin);
stopAt = Min(SMOffset+9, SMArraySize);
for(i=SMOffset; i<stopAt; i++)
{
Canvas.SetPos(XPos, YPos);
if(!sizing)
{
if ( SMState == SMS_VoiceChatChannel )
{
if ( IsActiveChannel(SMOffset + i) )
Canvas.SetDrawColor(0,255,0,255);
else if ( SMIndex == 2 && !IsMember(SMOffset + i) )
Canvas.SetDrawColor(160,160,160,255);
else Canvas.SetDrawColor(255,255,255,255);
}
else Canvas.SetDrawColor(255,255,255,255);
Canvas.DrawText(SMNameArray[i], false);
}
else
{
Canvas.TextSize(SMNameArray[i], XL, YL);
XMax = Max(XMax, XPos + XL);
YMax = Max(YMax, YPos + YL);
}
YPos += SMLineSpace;
}
}
function bool IsActiveChannel(int i)
{
if ( SMState != SMS_VoiceChatChannel )
return false;
if ( ViewportOwner.Actor == None || ViewportOwner.Actor.ActiveRoom == None )
return false;
if ( i < 0 || i > SMArraySize )
return false;
if ( SMIndexArray[i] != ViewportOwner.Actor.ActiveRoom.ChannelIndex )
return false;
return true;
}
function bool IsMember(int i)
{
if ( SMState != SMS_VoiceChatChannel )
return false;
if ( ViewportOwner.Actor == None || ViewportOwner.Actor.VoiceReplicationInfo == None || ViewportOwner.Actor.PlayerReplicationInfo == None )
return false;
return ViewportOwner.Actor.VoiceReplicationInfo.IsMember(ViewportOwner.Actor.PlayerReplicationInfo, SMIndexArray[i]);
}
//////////////////////////////////////////////
function int KeyToNumber(EInputKey InKey)
{
local int i;
for(i=0; i<10; i++)
{
if(bSpeechMenuUseLetters)
{
if(InKey == LetterKeys[i])
return i;
}
else
{
if(InKey == NumberKeys[i])
return i;
}
}
return -1;
}
function bool KeyEvent( EInputKey Key, EInputAction Action, FLOAT Delta )
{
local int input, NumNums;
NumNums = Min(SMArraySize - SMOffset, 10);
// While speech menu is up, dont let user use console. Debateable.
//if( KeyIsBoundTo( Key, "ConsoleToggle" ) )
// return true;
//if( KeyIsBoundTo( Key, "Type" ) )
// return true;
if (Action == IST_Press)
{
bIgnoreKeys=false;
if ( Key == IK_Ctrl )
bCtrl = True;
else if ( Key == IK_Alt )
bAlt = True;
else if ( key == IK_Shift )
bShift = True;
}
if ( Action == IST_Release )
{
if ( bAlt )
{
if ( Key == IK_Left ) // extra mouse buttons - only tested this on logitech mx500 :\
{
HandleInput(-1);
return True;
}
else if ( Key == IK_Right )
{
input = HighlightRow + 1;
if(input == 10)
input = 0;
HighlightRow=0;
HandleInput(input);
return True;
}
}
}
if( Action != IST_Press )
return false;
if( Key==IK_Escape)
{
HandleInput(-1);
return true ;
}
// If 'letters' mode is on, convert input
input = KeyToNumber(Key);
if(input != -1)
{
HandleInput(input);
return true;
}
// Keys below are only used if bSpeechMenuUseMouseWheel is true
if(!bSpeechMenuUseMouseWheel)
return false;
if( Key==IK_MouseWheelUp )
{
// If moving up on the top row, and there is a previous page
if(HighlightRow == 0 && SMOffset > 0)
{
HandleInput(-2);
HighlightRow=9;
}
else
{
HighlightRow = Max(HighlightRow - 1, 0);
}
return true;
}
else if( Key==IK_MouseWheelDown )
{
// If moving down on the bottom row (the 'MORE' row), act as if we hit it, and move highlight to top.
if(HighlightRow == 9)
{
HandleInput(0);
HighlightRow=0;
}
else
{
HighlightRow = Min(HighlightRow + 1, NumNums - 1);
}
return true;
}
else if( Key==IK_MiddleMouse )
{
input = HighlightRow + 1;
if(input == 10)
input = 0;
HighlightRow=0;
HandleInput(input);
return true;
}
return false;
}
function Font MyGetSmallFontFor(canvas Canvas)
{
local int i;
for(i=1; i<8; i++)
{
if ( class'HudBase'.default.FontScreenWidthSmall[i] <= Canvas.ClipX )
return class'HudBase'.static.LoadFontStatic(i-1);
}
return class'HudBase'.static.LoadFontStatic(7);
}
function PostRender( canvas Canvas )
{
local float XL, YL;
local int SelLeft, i;
local float XMax, YMax;
Canvas.Font = class'UT2MidGameFont'.static.GetMidGameFont(Canvas.ClipX); // Update which font to use.
// Figure out max key name size
XMax = 0;
YMax = 0;
for(i=0; i<10; i++)
{
Canvas.TextSize(NumberToString(i)$"- ", XL, YL);
XMax = Max(XMax, XL);
YMax = Max(YMax, YL);
}
SMLineSpace = YMax * 1.1;
SMTab = XMax;
SelLeft = SMArraySize - SMOffset;
// First we figure out how big the bounding box needs to be
XMax = 0;
YMax = 0;
DrawNumbers( canvas, Min(SelLeft, 9), SelLeft > 9, true, XMax, YMax);
DrawCurrentArray( canvas, true, XMax, YMax);
Canvas.TextSize(SMStateName[SMState], XL, YL);
XMax = Max(XMax, Canvas.ClipX*(SMOriginX+SMMargin) + XL);
YMax = Max(YMax, (Canvas.ClipY*SMOriginY) - (1.2*SMLineSpace) + YL);
// XMax, YMax now contain to maximum bottom-right corner we drew to.
// Then draw the box
XMax -= Canvas.ClipX * SMOriginX;
YMax -= Canvas.ClipY * SMOriginY;
Canvas.SetDrawColor(255,255,255,255);
Canvas.SetPos(Canvas.ClipX * SMOriginX, Canvas.ClipY * SMOriginY);
// if _RO_
// else
// Canvas.DrawTileStretched(texture 'InterfaceContent.Menu.BorderBoxD', XMax + (SMMargin*Canvas.ClipX), YMax + (SMMargin*Canvas.ClipY));
// end if _RO_
// Draw highlight
if(bSpeechMenuUseMouseWheel)
{
Canvas.SetDrawColor(255,255,255,128);
Canvas.SetPos( Canvas.ClipX*SMOriginX, Canvas.ClipY*(SMOriginY+SMMargin) + ((HighlightRow - 0.1)*SMLineSpace) );
// if _RO_
// else
// Canvas.DrawTileStretched(texture 'InterfaceContent.Menu.BorderBoxD', XMax + (SMMargin*Canvas.ClipX), 1.1*SMLineSpace );
// end if _RO_
}
// Then actually draw the stuff
DrawNumbers( canvas, Min(SelLeft, 9), SelLeft > 9, false, XMax, YMax);
DrawCurrentArray( canvas, false, XMax, YMax);
// Finally, draw a nice title bar.
Canvas.SetDrawColor(255,255,255,255);
Canvas.SetPos(Canvas.ClipX*SMOriginX, (Canvas.ClipY*SMOriginY) - (1.5*SMLineSpace));
// if _RO_
// else
// Canvas.DrawTileStretched(texture 'InterfaceContent.Menu.BorderBoxD', XMax + (SMMargin*Canvas.ClipX), (1.5*SMLineSpace));
// end if _RO_
Canvas.SetDrawColor(255,255,128,255);
Canvas.SetPos(Canvas.ClipX*(SMOriginX+SMMargin), (Canvas.ClipY*SMOriginY) - (1.2*SMLineSpace));
Canvas.DrawText(SMStateName[SMState]);
if (SMState == SMS_VoiceChatChannel)
DrawMembers(Canvas, XMax, YMax);
}
function DrawMembers(Canvas Canvas, float XMax, float YMax)
{
local array<int> Members;
local int i;
local float XPos, YPos, XL, YL;
local GameReplicationInfo GRI;
local string CurrentPlayer;
GRI = ViewportOwner.Actor.GameReplicationInfo;
if ( GRI == None )
return;
if (HighlightRow >= 0 && HighlightRow < SMArraySize)
{
Members = ViewportOwner.Actor.VoiceReplicationInfo.GetChannelMembersAt( SMIndexArray[SMOffset + HighlightRow] );
Canvas.SetDrawColor(255,255,175,220);
// XPos = (Canvas.ClipX * (SMOriginX+SMMargin)) + SMTab;
// YPos = Canvas.ClipY * (SMOriginY+SMMargin);
XPos = XMax + (SMMargin * Canvas.ClipX * 2.25)/* + SMTab*/;
YPos = Canvas.ClipY*(SMOriginY+SMMargin) + ((HighlightRow + 0.1)*SMLineSpace);
for(i=0; i<Members.Length; i++)
{
CurrentPlayer = GRI.FindPlayerByID(Members[i]).PlayerName;
Canvas.SetPos(XPos, YPos);
Canvas.TextSize(CurrentPlayer, XL, YL);
XMax = Max(XMax, XPos + XL);
YMax = Max(YMax, YPos + YL);
YPos += SMLineSpace;
Canvas.DrawText( CurrentPlayer );
}
}
}
function BeginState()
{
bVisible = true;
bIgnoreKeys = true;
bCtrl = false;
HighlightRow=0;
EnterState(SMS_Main, true);
SMCallsign="";
PlayConsoleSound(SMOpenSound);
}
function CloseSpeechMenu()
{
if (!bSpeechMenuLocked)
GoToState('');
}
function EndState()
{
bVisible = false;
bCtrl = false;
}
// Close speech menu on level change
event NotifyLevelChange()
{
Global.NotifyLevelChange();
GotoState('');
}
}
exec function InGameChat()
{
local GUIController GC;
GC = GUIController(ViewportOwner.GUIController);
if ( GC.OpenMenu(ChatMenuClass) )
ChatMenu = GC.ActivePage;
}
exec function ServerInfo()
{
local GUIController GC;
GC = GUIController(ViewportOwner.GUIController);
if (GC==None)
return;
GC.OpenMenu(ServerInfoMenu);
}
exec function TeamChatOnly()
{
bTeamChatOnly = !bTeamChatOnly;
}
exec function PlayWaitingGame()
{
local GUIController GC;
if (WaitingGameClassName == "")
return;
GC = GUIController(ViewportOwner.GUIController);
if (GC != None)
GC.OpenMenu(WaitingGameClassName);
}
exec function MusicMenu()
{
local GUIController C;
local int i;
if ( MusicManagerClassName == "" )
{
log("No music player menu configured. Please check the MusicManagerClassName line of the [XInterface.ExtendedConsole] section of the UT2004.ini.");
return;
}
C = GUIController(ViewportOwner.GUIController);
if ( C != None )
{
i = C.FindMenuIndexByName(MusicManagerClassName);
if ( i == -1 )
C.OpenMenu(MusicManagerClassName);
else C.RemoveMenuAt(i,true);
}
}
// For debugging PlayInfo
exec function DumpPlayInfo( string group )
{
local PlayInfo PInfo;
foreach AllObjects( class'PlayInfo', PInfo )
{
if ( PInfo.InfoClasses.Length > 0 && PInfo.Settings.Length > 0 )
{
PInfo.Dump(group);
break;
}
}
}
// For debugging CacheRecords
exec function DumpRecords(string Type)
{
DumpCacheRecords(Type);
}
final private function AddMessage(string Mesg)
{
log(Mesg);
Message(Mesg,0);
}
final function DumpCacheRecords(optional string CacheType)
{
local int i;
local string Margin;
local array<CacheManager.CrosshairRecord> CRecs;
local array<CacheManager.WeaponRecord> WRecs;
local array<CacheManager.MapRecord> MRecs;
local array<CacheManager.MutatorRecord> MutRecs;
local array<CacheManager.GameRecord> GRecs;
local array<CacheManager.AnnouncerRecord> ARecs;
local array<CacheManager.VehicleRecord> VRecs;
if ( CacheType == "" || CacheType ~= "Crosshair" )
{
class'CacheManager'.static.GetCrosshairList(CRecs);
AddMessage(" ================ Cached crosshair records ================ ");
for (i = 0; i < CRecs.Length; i++)
{
AddMessage(CRecs[i].RecordIndex$")"@CRecs[i].FriendlyName@CRecs[i].CrosshairTexture);
}
AddMessage("");
}
if ( CacheType == "" || CacheType ~= "GameType" )
{
class'CacheManager'.static.GetGameTypeList(GRecs);
AddMessage(" ================ Cached gametype records ================ ");
for (i = 0; i < GRecs.Length; i++)
{
for (Margin="";Len(Margin)<Len(i);Margin$=" ");
AddMessage(GRecs[i].RecordIndex$")"@GRecs[i].ClassName);
AddMessage(Margin$" Name :"$GRecs[i].GameName);
AddMessage(Margin$" Description :"$GRecs[i].Description);
AddMessage(Margin$" TextName :"$GRecs[i].TextName);
AddMessage(Margin$" GameAcronym :"$GRecs[i].GameAcronym);
AddMessage(Margin$" MapListType :"$GRecs[i].MapListClassName);
AddMessage(Margin$" MapPrefix :"$GRecs[i].MapPrefix);
AddMessage(Margin$" bTeamGame :"$GRecs[i].bTeamGame);
AddMessage(Margin$" Group :"$GRecs[i].GameTypeGroup);
}
AddMessage("");
}
if ( CacheType == "" || CacheType ~= "Weapon" )
{
class'CacheManager'.static.GetWeaponList(WRecs);
AddMessage(" ================ Cached weapon records ================ ");
for (i = 0; i < WRecs.Length; i++)
{
for (Margin="";Len(Margin)<Len(i);Margin$=" ");
AddMessage(WRecs[i].RecordIndex$")"@WRecs[i].ClassName);
AddMessage(Margin$" FriendlyName:"$WRecs[i].FriendlyName);
AddMessage(Margin$" Description :"$WRecs[i].Description);
AddMessage(Margin$" TextName :"$WRecs[i].TextName);
AddMessage(Margin$" PickupClass :"$WRecs[i].PickupClassName);
AddMessage(Margin$" Attachment :"$WRecs[i].AttachmentClassName);
}
AddMessage("");
}
if ( CacheType == "" || CacheType ~= "Map" )
{
class'CacheManager'.static.GetMapList(MRecs);
AddMessage(" ================ Cached map records ================ ");
for (i = 0; i < MRecs.Length; i++)
{
for (Margin="";Len(Margin)<Len(i);Margin$=" ");
AddMessage(MRecs[i].RecordIndex$")"@MRecs[i].MapName);
AddMessage(Margin$" Acronym :"$MRecs[i].Acronym);
AddMessage(Margin$" TextName :"$MRecs[i].TextName);
AddMessage(Margin$" FriendlyName :"$MRecs[i].FriendlyName);
AddMessage(Margin$" Author :"$MRecs[i].Author);
AddMessage(Margin$" PlayerCountMin:"$MRecs[i].PlayerCountMin);
AddMessage(Margin$" PlayerCountMax:"$MRecs[i].PlayerCountMax);
AddMessage(Margin$" Description :"$MRecs[i].Description);
AddMessage(Margin$" Screenshot :"$MRecs[i].ScreenshotRef);
AddMessage(Margin$" ExtraInfo :"$MRecs[i].ExtraInfo);
}
AddMessage("");
}
if ( CacheType == "" || CacheType ~= "Mutator" )
{
class'CacheManager'.static.GetMutatorList(MutRecs);
AddMessage(" ================ Cached mutator records ================ ");
for (i = 0; i < MutRecs.Length; i++)
{
for (Margin="";Len(Margin)<Len(i);Margin$=" ");
AddMessage(MutRecs[i].RecordIndex$")"@MutRecs[i].ClassName);
AddMessage(Margin$" FriendlyName :"$MutRecs[i].FriendlyName);
AddMessage(Margin$" Description :"$MutRecs[i].Description);
AddMessage(Margin$" GroupName :"$MutRecs[i].GroupName);
AddMessage(Margin$" ConfigMenu :"$MutRecs[i].ConfigMenuClassName);
AddMessage(Margin$" IconMaterialName :"$MutRecs[i].IconMaterialName);
}
AddMessage("");
}
if ( CacheType == "" || CacheType ~= "Announcer" )
{
class'CacheManager'.static.GetAnnouncerList(ARecs);
AddMessage(" ================ Cached announcer records ================ ");
for (i = 0; i < ARecs.Length; i++)
{
for (Margin="";Len(Margin)<Len(i);Margin$=" ");
AddMessage(ARecs[i].RecordIndex$")"@ARecs[i].ClassName);
AddMessage(Margin$" FriendlyName :"$ARecs[i].FriendlyName);
AddMessage(Margin$" PackageName :"$ARecs[i].PackageName);
AddMessage(Margin$" FallbackPackage :"$ARecs[i].FallbackPackage);
}
AddMessage("");
}
if ( CacheType == "" || CacheType ~= "Vehicle" )
{
class'CacheManager'.static.GetVehicleList(VRecs);
AddMessage(" ================ Cached vehicle records ================ ");
for (i = 0; i < VRecs.Length; i++)
{
for (Margin="";Len(Margin)<Len(i);Margin$=" ");
AddMessage(VRecs[i].RecordIndex$")"@VRecs[i].ClassName);
AddMessage(Margin$" FriendlyName :"$VRecs[i].FriendlyName);
AddMessage(Margin$" Description :"$VRecs[i].Description);
}
AddMessage("");
}
}
function bool VoiceChatAllowed()
{
if ( ViewportOwner == None )
return false;
if ( ViewportOwner.Actor == None )
return false;
if ( ViewportOwner.Actor.Level == None )
return false;
if ( ViewportOwner.Actor.Level.NetMode == NM_DedicatedServer )
return false;
if ( ViewportOwner.Actor.Level.NetMode == NM_StandAlone )
return false;
return true;
}
exec function DLO( string ClassName, string ClassType )
{
local class c;
local object o;
if ( ClassName == "" )
{
log("No class name specified.");
return;
}
if ( ClassType != "" )
c = class(DynamicLoadObject(ClassType,Class'Class'));
else c = class'class';
o = DynamicLoadObject(ClassName, c);
log("Result of DLO was "$o);
}
exec function DumpLoadingHints(string param)
{
local array<CacheManager.GameRecord> Recs;
local int i, j;
local bool bShowAll;
local class<GameInfo> GameClass;
local array<string> Hints;
class'CacheManager'.static.GetGameTypeList(Recs);
bShowAll = param == "";
for ( i = 0; i < Recs.Length; i++ )
{
GameClass = class<GameInfo>(DynamicLoadObject( Recs[i].ClassName, class'Class' ));
if ( GameClass != None )
{
Hints = GameClass.static.GetAllLoadHints(!bShowAll);
if ( Hints.Length > 0 )
{
log( Recs[i].GameName @ "Loading Hints -" );
for ( j = 0; j < Hints.Length; j++ )
log(" "$j$") "$Hints[j] );
log("");
}
}
}
}
exec function DebugTabOrder()
{
if ( GUIController(ViewportOwner.GUIController) != None && GUIController(ViewportOwner.GUIController).ActivePage != None )
{
log("Searching for components with invalid tab order...");
GUIController(ViewportOwner.GUIController).ActivePage.DebugTabOrder();
}
}
defaultproperties
{
SMOriginX=0.01
SMOriginY=0.3
SMMargin=0.015
SMStateName(0)="Speech Menu"
SMStateName(1)="Voice Chat"
SMStateName(2)="Acknowledge"
SMStateName(3)="Friendly Fire"
SMStateName(4)="Order"
SMStateName(5)="Other"
SMStateName(6)="Taunt"
SMStateName(7)="Taunt Anim"
SMStateName(8)="Player Select"
SMAllString="[ALL]"
SMMoreString="[MORE]"
// Replaceme
SMOpenSound=sound'KF_MenuSnd.msfxEdit'
SMAcceptSound=sound'KF_MenuSnd.msfxMouseClick'
SMDenySound=sound'KF_MenuSnd.CharFade'
ConsoleSoundVol=0.3
MaxScrollbackSize=128
bSpeechMenuUseMouseWheel=True
bSpeechMenuUseLetters=False
LetterKeys(0)=IK_Q
LetterKeys(1)=IK_W
LetterKeys(2)=IK_E
LetterKeys(3)=IK_R
LetterKeys(4)=IK_A
LetterKeys(5)=IK_S
LetterKeys(6)=IK_D
LetterKeys(7)=IK_F
LetterKeys(8)=IK_Z
LetterKeys(9)=IK_X
NumberKeys(0)=IK_0
NumberKeys(1)=IK_1
NumberKeys(2)=IK_2
NumberKeys(3)=IK_3
NumberKeys(4)=IK_4
NumberKeys(5)=IK_5
NumberKeys(6)=IK_6
NumberKeys(7)=IK_7
NumberKeys(8)=IK_8
NumberKeys(9)=IK_9
SMChannelOptions(0)="Join"
SMChannelOptions(1)="Leave"
SMChannelOptions(2)="Talk"
AddedCurrentHead="Added Server:"
AddedCurrentTail="To Favorites!"
StatsPromptMenuClass="GUI2K4.UT2K4StatsPrompt"
NeedPasswordMenuClass="GUI2K4.UT2K4GetPassword"
SteamLoginMenuClass="ROInterface.ROSteamLoginPage"
ServerInfoMenu="GUI2K4.UT2K4ServerInfo"
ChatMenuClass="GUI2K4.UT2K4InGameChat"
ServerFullMsg="Server is now full"
}