Legacy:TABname Completion
TABname Completion mimics that uncommonly-known mIRC command that fills in a person's name, depending on what text they enter (when you press the TAB key).
This code is/will be in a version of Esc sometime soon – I have placed this in my UTConsole class, in the 'Typing' state, under the 'KeyEvent' function. When entering part of any Player's name (case-sensitive), it will complete the Player's name.
To Do
- Thanks to Mychaeel's code, it now cycles through similar names. And it works perfectly - no-one prove me wrong.
Implementation
The following implementation in UnrealScript has been created by DJPaul and Mychaeel for the Esc mod. Feel free to use and modify.
state Typing
{
//Process 'String' from right-to-left, looking for the first 'LookFor'.
function int FindRightMost(string String, string LookFor)
{
local int i;
for (i=len(String)-1; i>=0; i--)
{
if ( mid(String, i, 1) == LookFor )
{
return i+1;
}
}
//Rogue-value.
return 667;
}
event bool KeyEvent( EInputKey Key, EInputAction Action, FLOAT Delta )
{
local string TextNameCompletedFirst, TextNameCompletedSuccessor;
local string ThisPlayerName; //To cut down on long statements below.
local int RightSpace, i;
if (Action!=IST_Press)
return false;
if ((Key == IK_Tab) && (Viewport.Actor != none))
{
// String comparisons (equality, alphabetical order) shall be case-insensitive.
// Use ~= for equality and Caps() for alphabetical order in UnrealScript.
RightSpace = FindRightMost(TypedStr, " ");
if (RightSpace == 667)
return false;
if (TextNamePrefix == "")
{
TextNamePrefix = Right(TypedStr, len(TypedStr)-RightSpace);
TextNameCompletedPrev = "";
}
if (Viewport.Actor.GameReplicationInfo != none)
{
for (i=0; i<32; i++)
{
if (Viewport.Actor.GameReplicationInfo.PRIArray[i] != none)
{
ThisPlayerName = Viewport.Actor.GameReplicationInfo.PRIArray[i].PlayerName;
if (left(ThisPlayerName, len(TextNamePrefix)) == TextNamePrefix)
{
// Save the first matching player name in alphabetical order in case we don't
// find an alphabetical successor of TextNameCompletedPrev.
if ((TextNameCompletedFirst == "") || (ThisPlayerName < TextNameCompletedFirst))
TextNameCompletedFirst = ThisPlayerName;
if (TextNameCompletedPrev != "")
{
// Save the player name we're looking at if it is one of TextNameCompletedPrev's
// alphabetical successors (and a better match than the last one we found).
if (ThisPlayerName > TextNameCompletedPrev)
if ((TextNameCompletedSuccessor == "") || (ThisPlayerName < TextNameCompletedSuccessor))
TextNameCompletedSuccessor = ThisPlayerName;
}
}
}
}
if (TextNameCompletedSuccessor == "") // no alphabetical successor found?
TextNameCompletedSuccessor = TextNameCompletedFirst; // start over from first
TextNameCompletedPrev = TextNameCompletedSuccessor; // save for next iteration
// TextNameCompletedSuccessor now contains the next matching name. Replace the
// partially entered name by the content of TextNameCompletedSuccessor.
TypedStr = left(TypedStr, (RightSpace-1)) $ " " $ TextNameCompletedSuccessor;
return true;
}
else
{
return false;
}
}
else
{
TextNamePrefix = ""; //Make code reevaluate the entered prefix.
return Super.KeyEvent(Key, Action, Delta);
}
}
}
Mychaeel: Wouldn't you like case-insensitivity for that? (That's why I mentioned a ~= b
and Caps(a) < Caps(b)
in that comment – it would be handy.)
DJPaul: Good point - will make it so that it converts them both to uppercase first, just as easy as using a ~# b
. I'll upload the tested code this evening.
Mychaeel: ~=
strikes me as more elegant (and more concise), that's all. After all its express purpose is to compare strings without case sensitivity.
xX)(Xx: Clearer instructions for where to place the code would be nice ;) or if anyone has the time, a proper .u file, as this is something which a lot of the UT community will want
DJPaul: This went into Esc, a UT1998 mod. IIRC, I put it into our custom Console class. As to where you want it to go, if it's in a dialogue box, you're going to want to do put it in the equivalent of a onKeyEvent method. If you want it from the "T"alk line, you're going to have to replace the class that is done in; I don't know if this is still in Console, I never looked.
El Muerte: it's ExtendedConsole for UT200x. Btw, UT1998 mod? I hope you mean UT'99 ;) My UTelAdSE and UnGateway mods also have tab completion to complete commands, but it works more like the Bash shell (prints a list of available options).
xX)(Xx: Will this work server side? Or will the latest anti-cheats scream HACK! ? ;)
EricBlade: I had to change all occurences of "Viewport" to "ViewportOwner", and add "local string TextNamePrefix, TextNameCompletedPrev;" to the KeyEvent function
----
Category ... erm. Useful Function? Function? Snippet? something, anyway