Announcement

Collapse

The Infinity Blade Forums Have Moved

We've launched brand new Infinity Blade forums with improved features and revamped layout. We've also included a complete archive of the previous posts. Come check out the new Infinity Blade forums.
See more
See less

Setting Up a Rudimentary Chat Box

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • Setting Up a Rudimentary Chat Box


    This tutorial is confirmed working up to September 2011 UDK.


    This intermediate to advanced level tutorial will cover the steps needed for a rudimentary multiplayer multi-line Chat window that works during gameplay, capturing all keyboard entry, and disallowing the game from capturing keyboard entry while it has focus. It will provide two ways to access the chat input - mouse click, and keyboard command.

    This tutorial assumes you are already very familiar with setting up and using Scaleform and CLIK widgets, and that you have a working mouse cursor in a Scaleform based HUD.

    The tutorial covers UDK networking/replication. I recommend you familiarize yourself with it: http://udn.epicgames.com/Three/ReplicationHome.html

    IMPORTANT: This tutorial also requires the toggle-able mouse tutorial. If you don't have that in your HUD, see this forum post for the tutorial: Adding a Mouse Cursor

    NOTE: You may download all these files pre-built from the Scaleform Sandbox Files thread --> HERE <--.




    Step 1 - Flash File Setup

    Text Input Box
    • Drop a CLIK TextInput widget onto your HUD. (C:\UDK\UDK-2011-09\Development\Flash\CLIK\components\TextInput.FLA )
    • Give it an instance name of chatInput.
    • Open the Component Inspector (CS4) or the Component Parameters rollout (CS5) and enable 'actAsButton'.


    Send Button
    • Next drop a CLIK Button widget next to the TextInput widget. (C:\UDK\UDK-2011-09\Development\Flash\CLIK\components\Button.FLA)
    • Give it an instance name of chatSendBtn.
    • Open the Component Inspector (CS4) or the Component Parameters rollout (CS5) and enter 'Send' in the label field of the button.


    Multi-line Scrollable Chat Log
    • Drop a CLIK Text Area widget above the TextInput widget. (C:\UDK\UDK-2011-09\Development\Flash\CLIK\components\TextArea.FLA)
    • Give it an instance name of chatLog.
    • Open the Component Inspector (CS4) or the Component Parameters rollout (CS5) and disable 'editable'.
    • Drop a CLIK Scroll Bar widget to the right of the TextInput widget. (C:\UDK\UDK-2011-09\Development\Flash\CLIK\components\Scrollbar.FLA )
    • Give it an instance name of chatScrollBar.
    • Select the Text Area, and open the Component Inspector (CS4) or the Component Parameters rollout (CS5) and set the scrollBar field of the Text Area to chatScrollBar.


    The Chat Form
    • Align the four widgets on stage so they are all near each other, forming a box. You can stretch (non-uniform scale) the widgets as needed.
    • Select all four widgets on the stage, right click, and choose Convert to Symbol.
    • Set the Name to chatForm
    • Set the Type to Movie Clip.
    • Enable Export for ActionScript & Export in frame 1.
    • Set the Identifier to chatForm
    • Set the Class to gfx.core.UIComponent
    • Press OK.
    • Delete the chatForm movie clip form the stage, leaving it in the library.


    The Chat Window
    • Copy the file \Development\Flash\CLIK\demos\com\Scaleform\Window .as to \Development\Flash\CLIK\gfx\controls\Window.as
    • Open this class file and change line 7 (the class declaration line) to this:

      Code:
      class gfx.controls.Window extends UIComponent {
    • Open the file \Development\Flash\CLIK\demos\WindowDemo.FLA.
    • Go to the Library panel of this file.
    • Select the WindowSkinned symbol.
    • Right click the WindowSkinned symbol and select Copy.
    • Return to your HUD FLA file.
    • Right click on the stage and select Paste to paste the Window symbol in place.
    • Align the window near the bottom left of the stage.
    • Give it an instance name of chatWindow.
    • With the chatWindow selected on stage, open the Component Inspector (CS4) or the Component Parameters rollout (CS5).
    • Set the formSource to chatForm.
    • Ensure formType is set to symbol.
    • Set maxHeight & maxWidget to 400.
    • Set minHeight and minWidget to 200.
    • Set offsetBottom to 24, offsetLeft to 20, offsetRight to 20, and offsetTop to 46, or whatever works for you after testing.
    • Set title to Chat.
    • Right click the WindowSkinned symbol in the Library Panel and select Properties.
    • Change the Class field to gfx.controls.Window and press OK.
    • Right click the symbol again and choose Component Definition.
    • Change the Class field to gfx.controls.Window and press OK.

    • Save, Publish, and Import your SWF into UDK as usual. You should now have a draggable chat window on the stage, which contains the chat input, chat area, send button, and scrollbar.




    Uploaded with ImageShack.us



    Step 2 HUD Class UnrealScript

    Your HUD Class should extend GFxMoviePlayer.

    Add these new variables to your UnrealScript HUD Class file:

    Code:
    var WorldInfo ThisWorld;
    var SFPlayerController PC;
    
    var array<string> chatMessages; // this will hold all the chat messages
    var bool bChatting;
    
    // These are our CLIK widgets for the chat system
    var GFxClikWidget MyChatInput, MyChatSendButton, MyChatLog;
    Modify your Start()/Init() function as follows (add the red lines):

    Code:
    function Init(optional LocalPlayer player)
    {
        super.Init(player);
        ThisWorld = GetPC().WorldInfo;
    
        Start();
        Advance(0);
    
        // ... other initialization code here ...
    
        
        // Register the HUD with the PlayerController
        PC = SFPlayerController(GetPC());
        PC.registerHUD(self);
    }
    Modify the ToggleCursor() function (from the Mouse tutorial) by adding the red lines of code below.

    Code:
    /** Toggles mouse cursor on/off */
    function ToggleCursor(bool showCursor, float mx, float my)
    {	
        if (showCursor)
        {
    	MouseContainer = CreateMouseCursor();
    	MouseCursor = MouseContainer.GetObject("my_cursor");
    	MouseCursor.SetPosition(mx,my);
    	MouseContainer.SetBool("topmostLevel", true);
        }
        else
        {
    	MouseContainer.Invoke("removeMovieClip", args);
    	MouseContainer = none;	
        }
    	
        if (!bChatting)
        {
    	self.bCaptureInput = showCursor;
    	self.bIgnoreMouseInput = !showCursor;		
        }
        else
        {
    	self.bCaptureInput = true;
    	self.bIgnoreMouseInput = false;
        }
    }
    Now modify the WidgetInitialized() function of your HUD and set up event listeners for mouse click events on the chat text input field and the chat send button:

    Code:
    event bool WidgetInitialized(name WidgetName, name WidgetPath, GFxObject Widget)
    {    
        switch(WidgetName)
        {             
            case ('chatInput'):
                MyChatInput = GFxClikWidget(Widget);
                MyChatInput.AddEventListener('CLIK_press', OnChat);		
                break;
    	case ('chatSendBtn'):
    	    MyChatSendButton = GFxClikWidget(Widget);
                MyChatSendButton.AddEventListener('CLIK_press', OnChatSend);
    	    break;
    	case ('chatLog'):
    	    MyChatLog = GFxClikWidget(Widget);
    	    break;
            default:
                break;
        }
        return true;
    }
    Add the OnChat() event handler.

    Code:
    // Event Handler - handles when the player clicks on the chat box text input field.
    function OnChat(GFxClikWidget.EventData ev)
    {
        bChatting = true;
    }
    Add the OnChatSend() function. This function broadcasts the message when the Send button is pressed, and returns control to the game.

    Code:
    function OnChatSend(GFxClikWidget.EventData ev)
    {
        local string Msg;
    
        Msg = MyChatInput.GetString("text");
    
        if (Msg != "")
        {
            PC.SendTextToServer(PC, Msg);
        }
       
        MyChatInput.SetString("text", "");
        self.bCaptureInput = false;
        bChatting = false;
    }
    Now, for the function that updates the chat area, displaying each message received thus far from Broadcast():

    Code:
    function UpdateChatLog(string message)
    {
        local string displayMsg;
        local int i;
    
        chatMessages.AddItem(message);
        
        displayMsg = "";
    
        for (i = 0; i < chatMessages.length; i++)
        {
    	displayMsg @= chatMessages[i];
    	displayMsg @= "\n";
        }
        
        MyChatLog.SetString("text", displayMsg);
        MyChatLog.SetFloat("position", MyChatLog.GetFloat("maxscroll"));
    }
    Add the widget bindings and other important variables in your default properties:

    Code:
    defaultproperties
    {
        WidgetBindings.Add((WidgetName="chatInput",WidgetClass=class'GFxClikWidget'))
        WidgetBindings.Add((WidgetName="chatSendBtn",WidgetClass=class'GFxClikWidget'))
        WidgetBindings.Add((WidgetName="chatLog",WidgetClass=class'GFxClikWidget'))
    
        bIgnoreMouseInput = true;
        bCaptureInput = false;
    }


    Step 3 - GameInfo Class Setup

    Open your GameInfo class.

    Only add these variables to your game info class, if it does not extend UTGame or a child of UTGame, such as UTDeathmatch. You will get a warning on compile, if these variables are already being declared. If so, remove them from your game info class.

    Code:
    var class<BroadcastHandler> BroadcastHandlerClass;
    var BroadcastHandler BroadcastHandler;	// handles message (text and localized) broadcasts
    Next, add this line (in red) to the InitGame() function in your GameInfo class:

    Code:
    event InitGame( string Options, out string ErrorMessage )
    {
        Super.InitGame(Options, ErrorMessage);
        BroadcastHandler = spawn(BroadcastHandlerClass);
    }
    Inside our GameInfo class, we'll override the Broadcast event class from \Development\Src\Engine\Classes\GameInfo.uc

    Code:
    event Broadcast( Actor Sender, coerce string Msg, optional name Type )
    {
        local SFPlayerController PC;
        local PlayerReplicationInfo PRI;
    	
        // This code gets the PlayerReplicationInfo of the sender. We'll use it to get the sender's name with PRI.PlayerName
        if ( Pawn(Sender) != None )
            PRI = Pawn(Sender).PlayerReplicationInfo;
        else if ( Controller(Sender) != None )
    	PRI = Controller(Sender).PlayerReplicationInfo;
    	
        // This line executes a "Say"
        BroadcastHandler.Broadcast(Sender,Msg,Type);
    	
        // This is where we broadcast the received message to all players (PlayerControllers)
        if (WorldInfo != None)
        {
    	foreach WorldInfo.AllControllers(class'SFPlayerController',PC)
    	{
    	    `Log(Self$":: Sending "$PC$" a broadcast message from "$PRI.PlayerName$" which is '"$Msg$"'.");
    	    PC.ReceiveBroadcast(PRI.PlayerName, Msg);
    	}
        }
    }
    Last of all, add these lines to your GameInfo class' default properties, being sure to modify them with your class names:

    Code:
    defaultproperties
    {
        PlayerControllerClass=class'SFPlayerController'
        BroadcastHandlerClass=class'Engine.BroadcastHandler'
        HUDType=class'SFTutorial.SFHudWrapper'
        bUseClassicHUD=true
    }


    Step 4 - PlayerController Class Setup

    Create/Open the PlayerController class (in this case: SFPlayerController):

    Code:
    class SFPlayerController extends UTPlayerController;
    First we'll create a function that registers the HUD inside the PlayerController so we can easily call functions in the HUD from the PlayerController:

    Code:
    var SFHud MySFHud;
    
    function registerHUD(SFHud hud)
    {
        MySFHud = hud;
    }
    The next function is used to send a message to the server:

    Code:
    exec function SendTextToServer(SFPlayerController PC, String TextToSend)
    {
    	`Log(Self$":: Client wants to send '"$TextToSend$"' to the server.");
    	ServerReceiveText(PC, TextToSend);
    }
    This function is used to receive a server message and then broadcast it:

    Code:
    reliable server function ServerReceiveText(SFPlayerController PC, String ReceivedText)
    {	
        WorldInfo.Game.Broadcast(PC, ReceivedText, 'Say');
    }
    Last of all, we need to create a client function that listens for broadcasts from the server, and routes them to the chat window:

    Code:
    reliable client function ReceiveBroadcast(String PlayerName, String ReceivedText)
    {
        `Log(Self$":: The Server sent me '"$ReceivedText$"' from "$PlayerName$".");
        MySFHud.UpdateChatLog(PlayerName @ ": " @ ReceivedText);
    }


    OPTIONAL - Enable Chatting Via Keyboard Command (Pressing Enter)

    For this step, we'll use the Enter key to begin chatting, as well as sending (completing) the chat message. You can however use whatever key you want. For a list of potential keys, see this post: http://forums.epicgames.com/showthread.php?t=756159

    Step 1 - Add Key Binding

    Open DefaultInput.ini, and add the following line:

    Code:
    .Bindings=(Name="Enter",Command="ChatHandler")
    NOTE: You will need to comment out or delete the following line for the pressed key to work for chatting:

    Code:
    .Bindings=(Name="Enter",Command="GBA_Use")
    Step 2 - HudWrapper Class Setup

    Open your HUDWrapper. This is the class that instantiates the HUD. Add the function that will be executed on key press.:

    Code:
    exec function ChatHandler()
    {
        HudMovie.ToggleChat(); // Replace HudMovie with the reference name of your HUD movie.
    }
    Step 3 - HUD Class Setup

    Open your HUD class.

    First, we need to ensure that our chosen key is never captured as input by our HUD movie. We do this by adding it to the focus ignore key list. Add this line to your Start()/Init() function:

    Code:
        AddFocusIgnoreKey('Enter');
    Next, add a function that will enable chatting via keyboard command. This function is called by the HudWrapper:

    Code:
    function ToggleChat()
    {
        if (!bChatting)
        {
    	self.bCaptureInput = true;
    	OnChat();
        }
        else
        {
    	self.bCaptureInput = false;
    	OnChatSend();
        }
    }
    Next, modify the OnChat() and OnChatSend() function parameters so that they are optional:

    Code:
    function OnChat(optional GFxClikWidget.EventData ev)
    function OnChatSend(optional GFxClikWidget.EventData ev)
    Now modify the OnChat() function by adding this line of code:

    Code:
    MyChatInput.SetBool("focused", true);
    And finally, modify the OnChatSend() function with this line of code:

    Code:
    MyChatLog.SetBool("focused", true);

    Recompile scripts, and test your HUD.

  • #2
    First of all, thanks for this great tutorial!

    I have followed each step and everything compiled without any problem. However in game, when I type something and press send button nothing shows up. I checked the log window and a warning message shows as:

    Function MyGame.SFHud:OnChatSend:003D
    ScriptWarning: Accessed None 'MyChatInput'

    What could be the problem? I tried changing instance names of widgets but it didn't help.
    Thanks.

    Comment


    • #3
      Sorry there were several typos in the tutorial & the sample SFHud file. I have corrected the typos. Just make sure your code matches the new sample files.

      Comment


      • #4
        Thanks, it's working perfectly.

        Comment


        • #5
          Simple amazing just what i was needing thanks matt!

          Comment


          • #6
            awesome, thanks

            Comment


            • #7
              I'm kind of trying to implement a textArea with a working scrollbar (I haven't really reached the implementeation yet), and it behaves somewhat iffy. the TextArea has the scrollbar defined as it's scrollbar, and I can definitely see the Scrollbar being updated as the text starts to overflow the textArea, however whenever I try to scroll to the end, either by pressing the arrows or dragging the scrollbutton the textArea becomes blank and the scrollbutton disappears until i append the text in the textarea again, then it scrolls to the top again (which makes it impossible to see the overflowed text). I don't know if it's my way of implementation that causes this problem, but here is what i have:
              AS Code for updating the chat:
              Code:
              function AppendChat(msg:String)
              {	
              	chatMsg.push(msg);
              	gameLobby_mc.chatForm.chatLog.textField.text = "";
              	for(var a=0; a < chatMsg.length; a++)
              		gameLobby_mc.chatForm.chatLog.textField.text = gameLobby_mc.chatForm.chatLog.textField.text + "\n" + chatMsg[a];
              //chatMSG holds ALL the strings that gets send to the AppendChat function
              		
              }
              Oh, and it should also be noted that i followed the tutorial BUT I didn't implement the movable window as i want the chat to be static

              Comment


              • #8
                Have you tried setting the position of your scrollbar after the text area is updated?

                gameLobby_mc.chatForm.chatLog.position = gameLobby_mc.chatForm.chatLog.maxscroll;

                Comment


                • #9
                  Your AppendChat function has some problems with it. Use this code instead:

                  Code:
                  function AppendChat(msg:String)
                  {	
                      var newMsg:String
                      chatMsg.push(msg);
                      newMsg = "";
                  	
                      for(var a=0; a < chatMsg.length; a++)
                      {
                  	newMsg += chatMsg[a];
                  	newMsg += "\n";
                      }
                  	
                      gameLobby_mc.chatForm.chatLog.text = newMsg;
                      gameLobby_mc.chatForm.chatLog.position = gameLobby_mc.chatForm.chatLog.maxscroll;
                  }

                  Comment


                  • #10
                    In need of assistance please ?

                    Hello again folks,

                    Just gone through this Tutorial... all went well no compile errors, however as the topic above suggests "Nothing Happens" once the send button is pressed.

                    The flash is working fine, I have a draggable window I can type in the appropriate boxes on screen (so mouse cursor is fine).

                    The only bit I'm a bit confused on is the main bit probably another blonde moment, as follows.

                    ***
                    // The important part is in red.
                    SFHudWrapper(PC.myHUD).HudMovie.UpdateChatLog(PRI. PlayerName@": "@Msg);
                    ***

                    Now all of my files are names as the ones attached here, I have 99.9% checked for typos as it compiles well but still not working.

                    Any input greatly appreciated.

                    Thx

                    Comment


                    • #11
                      This tutorial no longer works as of the June build of UDK. Something has changed, but I don't know what. I am seeing alot of Accessed None errors in the log, regarding the player profile. That is in a bare bones UDK install, so it's not Scaleform related.

                      Comment


                      • #12
                        Ah I see ... Thank you Matt for your response, do you know of any other methods what are used for example what I could look at, it was pretty much exactly what I wanted aswell.

                        Regards

                        Comment


                        • #13
                          ++ To anybody else reading this thread who have or are working on a simple chat panel like this, I would really appreciate any ionput here or advice how you folks are going about this.

                          Many Thx (2 days @ work 1 more to go) before some more free time.

                          Comment


                          • #14
                            After following your tutorial and also getting some help on a few other errors, i have ran into another problem. When the chat form loads the chat input doesnt accept input. I can click on it and it shows a cursor but i cant type anything into it. I can post some code or whatever is needed, thanks for any help

                            Comment


                            • #15
                              Does it work in the Scaleform player, when you launch it using the Scaleform Launcher in Flash?

                              Comment

                              Working...
                              X