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

791 lines
18 KiB
Ucode

//-----------------------------------------------------------
//
//-----------------------------------------------------------
class KFConsole extends ExtendedConsole;
var enum EKFSpeechMenuState
{
KFSMS_Main,
KFSMS_Support,
KFSMS_Ack,
KFSMS_Alerts,
KFSMS_Directions,
KFSMS_Insults,
} KFSMState, PreviousStateName;
var array<PlayerReplicationInfo> 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<KFVoicePack> GetKFVoiceClass()
{
local KFPlayerReplicationInfo rop;
if ( ViewportOwner == None || ViewportOwner.Actor == None || ViewportOwner.Actor.PlayerReplicationInfo == none )
{
return none;
}
rop = KFPlayerReplicationInfo(ViewportOwner.Actor.PlayerReplicationInfo);
return class<KFVoicePack>(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<KFVoicePack> 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<KFVoicePack> 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<KFVoicePack> 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<KFVoicePack> 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<KFVoicePack> 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"
}