| 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.


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

Mapping Topics

Mapping Lessons

UnrealEd Interface

Questions&Answers

Scripting Topics

Scripting Lessons

Making Mods

Class Tree

Questions&Answers

Modeling Topics

Questions&Answers

Log In