// ==================================================================== // (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 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 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 Favorites; var config array SavedPasswords; var config string PasswordPromptMenu; var string LastConnectedServer, LastURL; struct ChatStruct { var string Message; var int team; }; var array 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) 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 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 GetVoiceClass() { if(ViewportOwner == None || ViewportOwner.Actor == None || ViewportOwner.Actor.PlayerReplicationInfo == None) return None; return class(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 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 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 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 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 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 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 CRecs; local array WRecs; local array MRecs; local array MutRecs; local array GRecs; local array ARecs; local array 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) Recs; local int i, j; local bool bShowAll; local class GameClass; local array Hints; class'CacheManager'.static.GetGameTypeList(Recs); bShowAll = param == ""; for ( i = 0; i < Recs.Length; i++ ) { GameClass = class(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" }