It is highly recommended that you use the workshop.codes editor to integrate this into your gamemode!

  • Automatic variables prevent variable conflicts
  • Mixins will simplify subtitle calls in your code

Join my Discord for help and discussions.

This is a tool that adds dynamic subtitles to the viewer's screen, with an optional hero speech sound effect. The import code in this post contains a simple demo. To add it to your code, create a new empty file and paste the code below into it. It currently uses 4 global variables, 9 player variables and 1 subroutine, though I will optimize this as the tool gets updated.

rule("[DS] Initialize")
        Ongoing - Global;

        Global.dsCharSpeed = Workshop Setting Integer(Custom String("Dynamic Subtitles"), Custom String("Subtitle speed (chars/second)"), 35, 5, 63, 0);
        Global.dsUseBot = Workshop Setting Toggle(Custom String("Dynamic Subtitles"), Custom String("Hero sound effects (uses a dummy bot)"), True, 1);

        Create HUD Text(All Players(All Teams), Null, Null, Custom String(" \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n "), 
        Top, 1, Null, Null, Null, Visible To, Default Visibility);

        Wait(Random Real(1, 2), Ignore Condition);

        Create Dummy Bot(Hero(Tracer), Current Game Mode == Game Mode(Deathmatch) ? Team(All) : Team(Team 2), -1, Up * 1000, Up);
        Global.dsBot = Last Created Entity;

        Start Forcing Dummy Bot Name(Global.dsBot, Custom String("DS BOT"));
        Set Status(Global.dsBot, Null, Phased Out, 999999);
        Disable Movement Collision With Players(Global.dsBot);
        Set Gravity(Global.dsBot, False);
        Set Invisible(Global.dsBot, All);
        Start Forcing Player Position(Global.dsBot, Global.dsBotPos, True);

rule("[DS] Start Dialogue")

        Abort If(Event Player.linesArray == Empty Array);
        Event Player.isSpeaking = True;
        Start Forcing Player To Be Hero(Global.dsBot, Hero Of(Event Player));
        Global.dsBotPos = Event Player;

        Event Player.wordCount = 0;
        Event Player.pauseOnNextSpace = False;
        Destroy HUD Text(Event Player.dsTextID);
        Wait(0.1, Ignore Condition);

        // Main text
        Create HUD Text(Players Within Radius(Event Player, 30, Team(All), Off), Null, Custom String("{0}  {1}  ({2}M)                                                                                                                      ", 
        Hero Icon String(Hero Of(Event Player)), Event Player, Round To Integer(Distance Between(Local Player, Event Player), To Nearest)), 
        Event Player.textString, Top, 2, Color(white), Event Player.textColor, Color(white), Visible To String and Color, Default Visibility);
        Event Player.dsTextID = Last Text ID;

        While(Event Player.linesArray != Empty Array);

            Event Player.pauseOnNextSpace = False;
            Event Player.textString = Custom String("");
            Event Player.wordCount = 0;

            For Player Variable(Event Player, dsCtrl, 0, String Length(Event Player.linesArray[0]), 1);

                Event Player.nextChar = Char In String(Event Player.linesArray[0], Event Player.dsCtrl);

                // Triggers

                    // Pause at punctuation
                    If(Event Player.pauseOnNextSpace && String Contains(Event Player.nextChar, Custom String(" ")));
                        Event Player.pauseOnNextSpace = False;
                        Wait(20 / Global.dsCharSpeed, Ignore Condition);
                    If(String Contains(Custom String("!?.-"), Event Player.nextChar));
                        Event Player.pauseOnNextSpace = True;

                    // Line break
                    If(String Contains(Event Player.nextChar, Custom String(" ")));
                        Event Player.wordCount += 1;
                        Set Status(Global.dsBot, Null, Hacked, 0.1);

                Event Player.textString = Custom String("{0}{1}", Event Player.textString, Event Player.nextChar);
                //Skip If(Has Status(Global.dsBot, Hacked), 1);
                //Set Status(Global.dsBot, Null, Hacked, 0.1);

                If(Event Player.wordCount >= 10);
                    Event Player.wordCount = 0;
                    Event Player.textString = Custom String("{0}{1}", Event Player.textString, Custom String("\n"));

                Wait(1 / Global.dsCharSpeed, Ignore Condition);

            Wait(4, Ignore Condition);
            Modify Player Variable(Event Player, linesArray, Remove From Array By Index, 0);
        Event Player.isSpeaking = False;

        Destroy HUD Text(Event Player.dsTextID);

@mixin parseDialogue(lines = Array(
    Custom String("You will suffer as I, Ramattra, have suffered! Your torment will outlast the stars!"), 
    Custom String("When the universe dwindles into dust, there you will be, still suffering as I have... suffered.")), color = Team Of(Event Player)) {

    Event Player.linesArray = Mixin.lines;
    Event Player.textColor = Mixin.color;
    Start Rule(StartDialogue, Restart Rule);

If you're not using the website editor, delete the @mixin part and paste its contents every time you want to call for a subtitle. Otherwise, to call a subtitle for dialogue inside a rule:

  1. Add @include parseDialogue(arrayOfLines, speakerColor) as an action in your desired rule. Currently, the subtitles are created from the Event Player context and are visible in the HUD of anyone within a certain distance from the speaker.
  2. Replace those paramaters with whatever you want. The first one must be an Array(line1, line1 etc.), the second one must be a color or custom color. If you just want the character to say one line, just add one custom string to the array.
  3. Magic happens!

Some important things you should know:

  • You can make many heroes speak at the same time, as the tool will stack the subtitles one under the other, but only the latest speaker will have the hero sound effects if they're turned on.
  • You'll need to adjust you gamemode HUD or change the HUD text created by this tool to put the subtitles in an appropriate position.
  • You'll also notice a config screen intended for you or any host to tune the subtitles. More options may be added in the future.

Workshop settings

You can change anything you want in the code to match your needs! Just don't forget to credit me somewhere :)

Players | 1 - 12
Categories: Tools, Miscellaneous
Heroes: All
Maps: All
Created at:
Last updated:
Current version: 1.0


Play subtitles on player
Play subtitles on player
Play subtitles on player
Play subtitles on player
Play subtitles on player



Users Also Like

Similar Codes

Join the Workshop.codes Discord