Chat - TDMP-Team/TDMP-Lua-Modding-API GitHub Wiki

Getting started

In TDMP 0.4.0 with new chat by Danyadd you can bring some of additional features and also replace built-in chat with your own.
To get ready to work with TDMP's built-in chat, be sure to include this file:

#include "tdmp/chat.lua"

Chat functions

TDMP_AddChatMessage

TDMP_AddChatMessage(...)

Locally adds message to a chatbox. Takes infinite amount of arguments which can be:

  • table Color - Sets a color for all following strings. Must be rgb array: [1,1,1] where first element is red channel, second is green and third is blue.
  • Player player - You can pass player's table or metatable to a message to make chat automatically convert it to player's name. Some modded chats may also use it for their purposes. NOTE: Player table/metatable being converted into small table which contains only steamId and playerId of a player:
-- code snipper from tdmp/chat.lua
function TDMP_AddChatMessage(...)
	local args = {...}
	for i, v in ipairs(args) do
		local t = type(v)
		if t == "table" then
			if v.steamid then -- making player table smaller
				v = {steamid = v.steamid, id = v.id}
			-- ...
  • string anytext - just a regular text which would be passed to chatbox.
    Example of usage:
-- prints in chat our current health
#include "tdmp/chat.lua"

local white, red, green = {1, 1, 1}, {1, 0, 0}, {0, 1, 0}
function tick()
	if InputPressed("i") then
		local lPly = Player(TDMP_LocalSteamID)
		local hp = math.ceil(lPly:Health()*100)
		TDMP_AddChatMessage(lPly:GetColor(true), lPly:Nick() .. ", ", white, "your health is ", hp < 25 and red or green, hp)
	end
end

TDMP_SendChatMessage

TDMP_SendChatMessage(string message)

Sends a message into text chat from local player. In other words, makes local player say something in text chat

  1. string message - Message to be sent

TDMP_BroadcastChatMessage

TDMP_BroadcastChatMessage(...)

Server only. Same as TDMP_AddChatMessage but broadcasts message to all players. It is recommended to keep it as short as possible.


TDMP_SendChatMessageToPlayer

TDMP_SendChatMessageToPlayer(string steamid | table receivers, ...)

Server only. Same as TDMP_AddChatMessage but sends message to specified player or players, if first argument is a table of steamIds. It is recommended to keep it as short as possible. You can find example of usage in chat hooks section

Chat hooks

TDMP's chat (no matter are you using modded or built-in one) provides three hooks for modding chat

TDMP_ChatAddMessage

Calls when message adds to a chatbox. Pushes json table of arguments which were passed to TDMP_AddChatMessage or TDMP_BroadcastChatMessage or TDMP_SendChatMessageToPlayer. Can be used for replacing default chatbox with your own (see "Replacing built-in chat" section)

TDMP_ChatSuppressMessage (Server only)

Calls when server has received chat message from a player and allows to suppress that message or replace it with our own. Mostly can be used for chat commands.

  • [1] string = message which player has sent
  • [2] string = steamid of a player who sent the message By returning empty string ("") in this hook you'll completely suppress message. Otherwise, if you'll return a string, previous message would be replaced by returned one.
    Example:
-- adds "!me" and "test" chat commands.
#include "tdmp/hooks.lua"
#include "tmdp/chat.lua"
#include "tmdp/player.lua"

Hook_AddListener("TDMP_ChatSuppressMessage", "TDMP_ChatCommandExample", function(msgData)
    msgData = json.decode(msgData)

    local msg = msgData[1]
    if msg:sub(1, 3) == "!me" then
        local ply = Player(msgData[2])
        TDMP_BroadcastChatMessage(ply:GetColor(true), ply.nick .. " " .. msg:sub(4, #msg))

        return ""
    elseif msg == "test" then
        local ply = Player(msgData[2])
        TDMP_BroadcastChatMessage(ply:GetColor(true), ply.nick .. " ", white, "just called an ", {.5,0,1}, "event ", white, "for ", {0.2,1,.2}, "each ", white, "player!")
    end
end)

TDMP_CanSeeChatMessage (Server only)

Calls after TDMP_ChatSuppressMessage hook if it did not return an empty string. Allows to make certain player not see a message from speaker.

  • [1] string = steamid of a player who sent the message (speaker)
  • [2] string = steamid of a listener. Can be speaker too.
  • [3] string = original message that speaker has sent, i.e. message which was not edited by TDMP_ChatSuppressMessage hook (if it ever was).
    Example:
-- adds proximity text chat and global chat command
#include "tdmp/hooks.lua"
#include "tmdp/chat.lua"
#include "tmdp/player.lua"

Hook_AddListener("TDMP_ChatSuppressMessage", "GlobalChatCommand", function(msgData)
    msgData = json.decode(msgData)

    local msg = msgData[1]
    if msg:sub(1,2) == "!!" then
        local ply = Player(msgData[2])
        TDMP_BroadcastChatMessage({.5, .5, .5}, "(Global) ", ply:GetColor(true), ply:Nick(), white, ": " ..  msg:sub(3, #msg))

        return ""
    end
end)

Hook_AddListener("TDMP_CanSeeChatMessage", "ProximityTextChat", function(msgData)
    msgData = json.decode(msgData)
    
    local speaker = Player(msgData[1])
    local listener = Player(msgData[2])
    local msg = msgData[3]

    if msg:sub(1,2) == "!w" then
        if Distance(speaker:GetPos(), listener:GetPos()) > 4 then return "0" end

        TDMP_SendChatMessageToPlayer(listener:SteamID(), {.5, .5, .5}, "(whispers) ", speaker:GetColor(true), speaker:Nick() .. " ", white, msg:sub(3, #msg))

        return "0"

    else
        if Distance(speaker:GetPos(), listener:GetPos()) > 10^2 then
            return "0"
        end
    end
end)

Replacing built-in chat

To replace built-in chat you must call SetBool("tdmp.disablechat", true) in init() function or outside it.
After that you'll have to handle incoming chat messages (from players and regular messages) by replacing TDMP_ChatAddMessage hook with your own.

Hook_AddListener("TDMP_ChatAddMessage", "TDMP_DefaultChatAddMessage", function(msg)
    msg = json.decode(msg)

end)

As example of chatbox you can use built-in chatbox source code, which can be accessed in Teardown/data/tdmp/TDMP/chat.lua, or at GitHub page
Note that TDMP_ChatAddMessage pushes table of colors, strings and players tables which you'll have to handle. Quick example from built-in chat:

Hook_AddListener("TDMP_ChatAddMessage", "TDMP_DefaultChatAddMessage", function(msg)
    msg = json.decode(msg)

    -- final message which would be added to messages table.
    local message = {
        body = {}, -- here we'll store our message

        -- and here's just custom data
        lifeTime = chat.msgLifeTime,
        alpha = 1
    }

    for i, v in ipairs(msg) do
        local t = type(v)
        if t == "table" and v[1] then -- if is a color
            message.body[#message.body + 1] = { -- then convert it to a bit more readable table and push it to body of a message
                r = v[1],
                g = v[2],
                b = v[3]
            }
        else
            if t == "table" and v.id then -- otherwise if table and contains "id" field, what indicates that it's a player table
                message.body[#message.body + 1] = TDMP_GetPlayer(v.id).nick -- then push player's nickname to body of a message
            else
                message.body[#message.body + 1] = tostring(v) -- otherwise convert value to a string and push
            end
        end
    end

    messageList[#messageList + 1] = message -- finally simply add message to messages list

    if #messageList > 8 then
        scrollYMax = scrollYMax + 1
    end

    scrollY = scrollYMax
end)

And one more snippet from built-in chat to show how to handle colors:

for i, msgData in ipairs(messageList) do
    if IsShowed then
        msgData.lifeTime = chat.msgLifeTime
        msgData.alpha = 1.0
    end

    UiTextShadow(0, 0, 0, .3*msgData.alpha, 2)

    UiTranslate(8,hLetter) -- moves message down by text height
    local totalW, totalH = 0, 0 -- totalH is unused for now
    for i, msg in ipairs(msgData.body) do
        if type(msg) == "table" then -- if element is a table, then it's a color which we need to apply down below
            UiColor(msg.r, msg.g, msg.b, msgData.alpha)
        else -- otherwise we need to render the text
            local w = UiGetTextSize(msg)
            if msg:sub(#msg,#msg) ~= " " then
                w = w - 7 -- dumb workaround of extra space which game adds by itself in UiGetTextSize function.
            end

            UiText(msg)
            UiTranslate(w,0) -- Render text and offset by rendered size

            totalW = totalW + w -- and add rendered size to total width of message
        end
    end

    -- reset everything
    UiTranslate(-totalW - 8,0)
    UiColor(1,1,1,1)
end