Legacy:TABname Completion - Unreal Wiki

# Legacy:TABname Completion

### From Unreal Wiki, The Unreal Engine Documentation Site

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

##### Views

- Legacy
- Discussion
- Current revision

##### Search