//----------------------------------------------------------- // //----------------------------------------------------------- class KFConsole extends ExtendedConsole; var enum EKFSpeechMenuState { KFSMS_Main, KFSMS_Support, KFSMS_Ack, KFSMS_Alerts, KFSMS_Directions, KFSMS_Insults, } KFSMState, PreviousStateName; var array PRIs; // List of squad leaders on the player's team, cleared when speech menu is closed var int savedSelectedObjective; state SpeechMenuVisible { function bool KeyType( EInputKey Key, optional string Unicode ) { if (bIgnoreKeys) return true; return false; } function class GetKFVoiceClass() { local KFPlayerReplicationInfo rop; if ( ViewportOwner == None || ViewportOwner.Actor == None || ViewportOwner.Actor.PlayerReplicationInfo == none ) { return none; } rop = KFPlayerReplicationInfo(ViewportOwner.Actor.PlayerReplicationInfo); return class(rop.VoiceType); } //-------------------------------------------------------------------------- // build voice command array. //-------------------------------------------------------------------------- // Rebuild the array of options based on the state we are now in. function RebuildSMArray() { switch(KFSMState) { case KFSMS_Main: buildSMMainArray(); break; case KFSMS_Support: buildSMSupportArray(); break; case KFSMS_Ack: buildSMAcknowledgmentArray(); break; case KFSMS_Alerts: buildSMAlertsArray(); break; case KFSMS_Directions: buildSMDirectionsArray(); break; case KFSMS_Insults: buildSMInsultsArray(); break; } } //-------------------------------------------------------------------------- // Build voice command array for Main(Just Categories) //-------------------------------------------------------------------------- function buildSMMainArray() { local int i; local KFPlayerReplicationInfo KFRepInfo; SMOffset = 0; SMArraySize = 0; KFRepInfo = KFPlayerReplicationInfo(ViewportOwner.Actor.PlayerReplicationInfo); for (i = 1; i < 6; i++) { SMNameArray[SMArraySize] = SMStateName[i]; SMIndexArray[SMArraySize] = i; SMArraySize++; } } //-------------------------------------------------------------------------- // Build voice command array for Support //-------------------------------------------------------------------------- function buildSMSupportArray() { local int i; local class KFVP; local KFGameReplicationInfo KFGameRep; local KFPlayerReplicationInfo KFPlayerRep; KFGameRep = KFGameReplicationInfo(ViewportOwner.Actor.GameReplicationInfo); KFPlayerRep = KFPlayerReplicationInfo(ViewportOwner.Actor.PlayerReplicationInfo); SMArraySize = 0; PreviousStateName = KFSMS_Main; KFVP = GetKFVoiceClass(); if(KFVP == None) { return; } for ( i = 0; i < KFVP.Default.NumSupports; i++ ) { if ( KFVP.Default.SupportAbbrev[i] != "" ) { SMNameArray[SMArraySize] = KFVP.Default.SupportAbbrev[i]; } else { SMNameArray[SMArraySize] = KFVP.Default.SupportString[i]; } SMIndexArray[SMArraySize] = i; SMArraySize++; } } //-------------------------------------------------------------------------- // Build voice command array for Acknowledgments //-------------------------------------------------------------------------- function buildSMAcknowledgmentArray() { local int i; local class KFVP; local KFGameReplicationInfo KFGameRep; local KFPlayerReplicationInfo KFPlayerRep; KFGameRep = KFGameReplicationInfo(ViewportOwner.Actor.GameReplicationInfo); KFPlayerRep = KFPlayerReplicationInfo(ViewportOwner.Actor.PlayerReplicationInfo); SMArraySize = 0; PreviousStateName = KFSMS_Main; KFVP = GetKFVoiceClass(); if(KFVP == None) { return; } for ( i = 0; i < KFVP.Default.NumAcknowledgments; i++ ) { if ( KFVP.Default.AcknowledgmentAbbrev[i] != "" ) { SMNameArray[SMArraySize] = KFVP.Default.AcknowledgmentAbbrev[i]; } else { SMNameArray[SMArraySize] = KFVP.Default.AcknowledgmentString[i]; } SMIndexArray[SMArraySize] = i; SMArraySize++; } } //-------------------------------------------------------------------------- // Build voice command array for Alerts //-------------------------------------------------------------------------- function buildSMAlertsArray() { local int i; local class KFVP; local KFGameReplicationInfo KFGameRep; local KFPlayerReplicationInfo KFPlayerRep; KFGameRep = KFGameReplicationInfo(ViewportOwner.Actor.GameReplicationInfo); KFPlayerRep = KFPlayerReplicationInfo(ViewportOwner.Actor.PlayerReplicationInfo); SMArraySize = 0; PreviousStateName = KFSMS_Main; KFVP = GetKFVoiceClass(); if(KFVP == None) { return; } for ( i = 0; i < KFVP.Default.NumAlerts; i++ ) { if ( KFVP.Default.AlertAbbrev[i] != "" ) { SMNameArray[SMArraySize] = KFVP.Default.AlertAbbrev[i]; } else { SMNameArray[SMArraySize] = KFVP.Default.AlertString[i]; } SMIndexArray[SMArraySize] = i; SMArraySize++; } } //-------------------------------------------------------------------------- // Build voice command array for Directions //-------------------------------------------------------------------------- function buildSMDirectionsArray() { local int i; local class KFVP; local KFGameReplicationInfo KFGameRep; local KFPlayerReplicationInfo KFPlayerRep; KFGameRep = KFGameReplicationInfo(ViewportOwner.Actor.GameReplicationInfo); KFPlayerRep = KFPlayerReplicationInfo(ViewportOwner.Actor.PlayerReplicationInfo); SMArraySize = 0; PreviousStateName = KFSMS_Main; KFVP = GetKFVoiceClass(); if(KFVP == None) { return; } for ( i = 0; i < KFVP.Default.NumDirections; i++ ) { if ( KFVP.Default.DirectionAbbrev[i] != "" ) { SMNameArray[SMArraySize] = KFVP.Default.DirectionAbbrev[i]; } else { SMNameArray[SMArraySize] = KFVP.Default.DirectionString[i]; } SMIndexArray[SMArraySize] = i; SMArraySize++; } } //-------------------------------------------------------------------------- // Build voice command array for Insults //-------------------------------------------------------------------------- function buildSMInsultsArray() { local int i; local class KFVP; local KFGameReplicationInfo KFGameRep; local KFPlayerReplicationInfo KFPlayerRep; KFGameRep = KFGameReplicationInfo(ViewportOwner.Actor.GameReplicationInfo); KFPlayerRep = KFPlayerReplicationInfo(ViewportOwner.Actor.PlayerReplicationInfo); SMArraySize = 0; PreviousStateName = KFSMS_Main; KFVP = GetKFVoiceClass(); if(KFVP == None) { return; } for ( i = 0; i < KFVP.Default.NumInsults; i++ ) { if ( KFVP.Default.InsultAbbrev[i] != "" ) { SMNameArray[SMArraySize] = KFVP.Default.InsultAbbrev[i]; } else { SMNameArray[SMArraySize] = KFVP.Default.InsultString[i]; } SMIndexArray[SMArraySize] = i; SMArraySize++; } } function EnterKFState(EKFSpeechMenuState newState, optional bool bNoSound) { KFSMState = newState; RebuildSMArray(); if ( !bNoSound ) { PlayConsoleSound(SMAcceptSound); } } function LeaveState() // Go up a level { PlayConsoleSound(SMDenySound); if ( KFSMState == KFSMS_Main ) { GotoState(''); } else { EnterKFState(PreviousStateName, true); } } function HandleInput(int keyIn) { local int SelectIndex; local KFPlayerReplicationInfo KFRepInfo; local bool inVehicle; //local UnrealPlayer up; // GO BACK - previous state (might back out of menu); if ( keyIn == -1 ) { LeaveState(); HighlightRow = 0; return; } // TOP LEVEL - we just enter a new state if ( KFSMState == KFSMS_Main ) { KFRepInfo = KFPlayerReplicationInfo(ViewportOwner.Actor.PlayerReplicationInfo); if( ViewportOwner.Actor.Pawn != none && ((ViewportOwner.Actor.Pawn.IsA('KFVehicle')) ||(ViewportOwner.Actor.Pawn.IsA('KFVehicleWeaponPawn'))) ) inVehicle = true; else inVehicle = false; switch(keyIn) { case 1: SMType = 'SUPPORT'; EnterKFState(KFSMS_Support); break; case 2: SMType = 'ACK'; EnterKFState(KFSMS_Ack); break; case 3: SMType = 'ALERT'; EnterKFState(KFSMS_Alerts); break; case 4: SMType = 'DIRECTION'; EnterKFState(KFSMS_Directions); break; case 5: SMType = 'INSULT'; EnterKFState(KFSMS_Insults); break; } return; } // Next page on the same level if ( keyIn == 0 ) { // Check there is a next page! if ( SMArraySize - SMOffset > 9 && SMArraySize != 10 ) { SMOffset += 9; return; } keyIn = 10; } // 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; } ViewportOwner.Actor.Speech(SMType, SMIndexArray[selectIndex], ""); PlayConsoleSound(SMAcceptSound); GotoState(''); } function string NumberToString(int num) { local EInputKey key; if ( num < 0 || num > 9 ) { return ""; } if(bSpeechMenuUseLetters) { key = LetterKeys[num]; } else { key = NumberKeys[num]; } return ViewportOwner.Actor.ConsoleCommand("LOCALIZEDKEYNAME" @ string(int(key))); } 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); } // Hackish if ( SMArraySize != 10 ) { 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); Canvas.SetDrawColor(255,255,255,255); if ( SMArraySize == 10 ) { stopAt = Min(SMOffset+10, SMArraySize); } else { stopAt = Min(SMOffset+9, SMArraySize); } for ( i = SMOffset; i < stopAt; i++ ) { Canvas.SetPos(XPos, YPos); if ( !sizing ) { 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 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 ( 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 && SMArraySize != 10 ) { 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; } HandleInput(input); HighlightRow = 0; 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[KFSMState], 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(139,28,28,255); Canvas.SetPos(Canvas.ClipX * SMOriginX, Canvas.ClipY * SMOriginY); Canvas.DrawTileStretched(Texture'KF_InterfaceArt_tex.Menu.thin_border_SlightTransparent', XMax + (SMMargin*Canvas.ClipX), YMax + (SMMargin*Canvas.ClipY)); // Draw highlight if ( bSpeechMenuUseMouseWheel ) { Canvas.SetDrawColor(255,202,180,128); Canvas.SetPos( Canvas.ClipX*SMOriginX, Canvas.ClipY*(SMOriginY+SMMargin) + ((HighlightRow - 0.1)*SMLineSpace) ); Canvas.DrawTileStretched(Texture'KF_InterfaceArt_tex.Menu.thin_border_SlightTransparent', XMax + (SMMargin*Canvas.ClipX), 1.1*SMLineSpace ); } // 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(139,28,28,255); Canvas.SetPos(Canvas.ClipX*SMOriginX, (Canvas.ClipY*SMOriginY) - (1.5*SMLineSpace)); Canvas.DrawTileStretched(Texture'KF_InterfaceArt_tex.Menu.thin_border_SlightTransparent', XMax + (SMMargin*Canvas.ClipX), (1.5*SMLineSpace)); Canvas.SetDrawColor(255,255,128,255); Canvas.SetPos(Canvas.ClipX*(SMOriginX+SMMargin), (Canvas.ClipY*SMOriginY) - (1.2*SMLineSpace)); Canvas.DrawText(SMStateName[KFSMState]); } function BeginState() { bVisible = true; bIgnoreKeys = true; bCtrl = false; HighlightRow = 0; EnterKFState(KFSMS_Main, true); SMCallsign = ""; PlayConsoleSound(SMOpenSound); } function EndState() { bVisible = false; bCtrl = false; PRIs.Length = 0; } // Close speech menu on level change event NotifyLevelChange() { Global.NotifyLevelChange(); GotoState(''); } } defaultproperties { SMOriginX=0.01 SMOriginY=0.3 SMMargin=0.015 SMStateName(0)="Speech Menu" SMStateName(1)="Support" SMStateName(2)="Acknowledge" SMStateName(3)="Alerts" SMStateName(4)="Directions" SMStateName(5)="Insults" 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 AddedCurrentHead="Added Server:" AddedCurrentTail="To Favorites!" ServerInfoMenu="KFInterface.KFGUIServerInfo" }