| Home Page | Recent Changes | Preferences

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

The Unreal Engine Documentation Site

Wiki Community

Topic Categories

Image Uploads

Random Page

Recent Changes

Offline Wiki

Unreal Engine

Console Commands

Terminology

FAQs

Help Desk

Mapping Topics

Mapping Lessons

UnrealEd Interface

UnrealScript Topics

UnrealScript Lessons

Making Mods

Class Tree

Modeling Topics

Chongqing Page

Log In