Creating Custom Tags (chat appearing twice)

Hey guys, so I am making a chat tags addon for my TTT server, but I’m having this error when I type in the chat.

http://puu.sh/wNJ7e/c0abf14d28.jpg

I’m assuming this has to do with the sandbox gamemode but I don’t know how to override the default chat. Any help would be appreciated.

Code:



-- [[ Custom Tags ]] ----------------------------
-- [[ Created by: Dogger ]] ---------------------
-- [[ Designed for Boujee Gamers TTT Server ]] --

-- Clientside File

local tag = {}
local ply = LocalPlayer()

local color = {} 
color.pl = Color(0, 255, 0, 255)
color.tag = Color(255, 0, 0, 255)

function OpenMenu() 

	local frame = vgui.Create("DFrame")

	frame.width = 390
	frame.height = 390

	frame:SetSize(frame.width, frame.height)
	frame:SetPos(400, 500)
	frame:MakePopup()
	frame:SetTitle("Boujee TTT Custom Tags")
	frame:AlignLeft(20)
	
	-- Set Tag button
	local button1 = vgui.Create("DButton", frame)
	
	button1.width = 110
	button1.height = 25
	button1.x = 25
	button1.y = 50
	
	button1:SetSize(button1.width, button1.height)
	button1:SetPos(button1.x, button1.y)
	button1:SetText("Set Tag")
	
	--Change Tag Color button
	local button2 = vgui.Create("DButton", frame)
	
	button2.width = 110
	button2.height = 25
	button2.x = 25
	button2.y = 130
	
	button2:SetSize(button2.width, button2.height)
	button2:SetPos(button2.x, button2.y)
	button2:SetText("Set Tag Color")
	
	--Change Name Color button
	local button3 = vgui.Create("DButton", frame)
	
	button3.width = 110
	button3.height = 25
	button3.x = 25
	button3.y = 250
	
	button3:SetSize(button3.width, button3.height)
	button3:SetPos(button3.x, button3.y)
	button3:SetText("Set Name Color")
	
	--Tag text entry
	local tagEntry = vgui.Create("DTextEntry", frame)
	
	tagEntry.x = button1.x + 134
	tagEntry.y = button1.y + 2
	
	tagEntry:SetPos(tagEntry.x, tagEntry.y)
	tagEntry:SetSize(180, 20)
	tagEntry:SetUpdateOnType(true)
	tagEntry:SetText("Enter Custom Tag")
	
	tagEntry.OnValueChange = function(self)
		tagEntry.value = self:GetValue()
	end
	
	-- Tag Color Mixer
	local colorPicker1 = vgui.Create("DColorMixer", frame)
	
	colorPicker1.x = button2.x + 135
	colorPicker1.y = button2.y - 30
	
	colorPicker1:SetPos(colorPicker1.x, colorPicker1.y)
	colorPicker1:SetPalette(false)
	colorPicker1:SetAlphaBar(false)
	colorPicker1:SetColor(Color(30, 100, 160) )
	colorPicker1:SetSize(180, 100)
	
	-- Name Color Mixer
	local colorPicker2 = vgui.Create("DColorMixer", frame)
	
	colorPicker2.x = button3.x + 135
	colorPicker2.y = button3.y - 30
	
	colorPicker2:SetPos(colorPicker2.x, colorPicker2.y)
	colorPicker2:SetPalette(false)
	colorPicker2:SetAlphaBar(false)
	colorPicker2:SetColor(Color(30, 100, 160) )
	colorPicker2:SetSize(180, 100)
	
	-- Set tag button is pressed
	button1.DoClick = function()
		tag.CustomTag = tagEntry.value
		tag.Enabled = true
		
		chat.AddText(Color(255,0,0,255), "[Tags] ", color_white, "You have set your tag to ", color.tag, tag.CustomTag )
	end
	
	-- Tag Color button pressed
	button2.DoClick = function()
		if tag.Enabled == true then
			tag.CustomColor = colorPicker1:GetColor()
			chat.AddText(Color(255,0,0,255), "[Tags] ", color_white, "Tag color changed: ", tag.CustomColor, tag.CustomTag, color_white, "." )
		else
			chat.AddText(Color(255,0,0,255), "[Tags] Error: ", color_white, "You must have a tag enabled to set it's color!")
		end
	end

	-- Name Color button pressed
	button3.DoClick = function()
		tag.CustomNameColor = colorPicker2:GetColor()
		chat.AddText(Color(255,0,0,255), "[Tags] ", color_white, "Name color changed: ", tag.CustomNameColor, ply:Nick(), color_white, "." )
	end
	
end

// - Open the menu when player types command - //

hook.Add("OnPlayerChat", "PlayerChat", function( ply, text ) 
	
	if text == "!tags" then OpenMenu() end
	
	if tag.Enabled == true then
		chat.AddText(tag.CustomColor, "[", tag.CustomTag, "]", " ", tag.CustomNameColor, ply:Nick(), ": ", color_white, text)
	end
	
end )

This is one of the first things I have created in lua, so I would also appreciate any tips on how I could improve my code!

If you put


return true

at the end of your OnPlayerChat hook, it’ll suppress the original message.

GM:OnPlayerChat

Add “return true” to the end of your OnPlayerChat hook and it should work as intended.

Edit: a-cookie beat me

Thanks both of you. I should have read the ENTIRE wiki page.

[editline]19th July 2017[/editline]

Okay new problem, on my server when I open the derma, it opens on every player screen. How would I open this only to the local player who types !tags?

I tried changing OpenMenu() to ply:OpenMenu() and I got errors.


 

[ERROR] lua/autorun/client/cl_tags.lua:137: attempt to call method 'OpenMenu' (a nil value)
  1. fn - lua/autorun/client/cl_tags.lua:137
   2. unknown - addons/ulib/lua/ulib/shared/hook.lua:109


If you want the method to work like that, you’ll have to grab the Player metatable with

FindMetaTable and add the function to that.

If you want to create a function that will be called on a player.
Replace
[LUA]function someFunctionName() end[/LUA]
With
[LUA]pMeta = FindMetaTable(“Player”)
function pMeta:someFunctionName() end [/LUA]

I changed the hook to this:



hook.Add("OnPlayerChat", "PlayerChat", function( ply, text ) 
	
	if text == "!tags" then pMeta:MenuOpen() end
	
	if tag.Enabled == true then
		chat.AddText(tag.CustomColor, "[", tag.CustomTag, "]", " ", tag.CustomNameColor, ply:Nick(), ": ", color_white, text)
		return true
	else
		chat.AddText(color_white, ply:Nick(), ": ", text)
		return true
	end
end )


and the function opens like this:



local pMeta = FindMetaTable("Player")
function pMeta:MenuOpen() 


But it still opens on every player’s screen when called.

check if ply == localplayer

At the top of the code I put ply = LocalPlayer()

[editline]19th July 2017[/editline]

no i said, check if the player that is provided in the onplayerchat hook is equal to you, the localplayer, if it is then you call the function

you’ll want to put your check on this line along with your current check


if text == "!tags" then pMeta:MenuOpen() end

Okay thank you.

Currently, when I set my tag, that tag appears next to everyone’s name when they type. Basically the tag is only showing up for the local player. What would I do to make the tag unique to the player and for everyone to see?

Network it using the net libary
Library: http://wiki.garrysmod.com/page/Category:net
Use examples: http://wiki.garrysmod.com/page/Net_Library_Usage

Okay, so I have got the server to receive the tag info when the player clicks the set tag button.



AddCSLuaFile("cl_tags.lua")

util.AddNetworkString("button1Pressed")
util.AddNetworkString("button2Pressed")

net.Receive("button1Pressed", function(ply) 
	tag = net.ReadString()
	print("Server received set tag: " .. tag)
end )

net.Receive("button2Pressed", function(ply) 
	tagColor = net.ReadColor()
	print("Server got tag color: " .. tagColor)
end )

hook.Add("PlayerSay", "CheckAndSendTag", function() 
	if tag then
		util.AddNetworkString("SendServerTagInfo")
		
		net.Start("SendServerTagInfo")
			net.WriteString(tag)
		net.Broadcast()
	end
	
	if tagColor then
		util.AddNetworkString("SendServerColorInfo")
		
		net.Start("SendServerColorInfo")
			net.WriteColor(tagColor)
		net.Broadcast()
	end
end )


(Ignore tag color code, I am only worried about the actual tag for now)
Now I am not sure what to have the client do when it receives the message from the server. Could I have to check for the server tag info in the OnPlayerChat hook?

Here is the updated code:




-- [[ Custom Tags ]] ----------------------------
-- [[ Created by: Dogger ]] ---------------------
-- [[ Designed for Boujee Gamers TTT Server ]] --

-- Clientside File

local tag = {}

local defaultTags = 
{
--Group    --Tag     --Color
{"superadmin", "Manager", Color(200, 30, 30, 255) },
{"dev", "Developer", Color(200, 30, 30, 255) },
{"admin", "Admin", Color(230, 200, 10, 255) },
{"t_admin", "Trial-Admin", Color(230, 200, 10, 255) },
{"donator", "Donator", Color(0, 210, 110, 255) },
{"vip", "VIP", Color(130, 30, 200, 255) },
{"member", "Member", Color(102, 178, 255, 255) }
}

local ply = LocalPlayer()

local color = {} 
color.defaultTag = Color(255, 0, 0, 255)
color.tagError = Color(255, 0, 0, 255)

local pMeta = FindMetaTable("Player")
function pMeta:MenuOpen() 

	local frame = vgui.Create("DFrame")

	frame.width = 390
	frame.height = 390

	frame:SetSize(frame.width, frame.height)
	frame:SetPos(400, 500)
	frame:MakePopup()
	frame:SetTitle("Boujee TTT Custom Tags")
	
	-- Set Tag button
	local button1 = vgui.Create("DButton", frame)
	
	button1.width = 110
	button1.height = 25
	button1.x = 25
	button1.y = 50
	
	button1:SetSize(button1.width, button1.height)
	button1:SetPos(button1.x, button1.y)
	button1:SetText("Set Tag")
	
	--Change Tag Color button
	local button2 = vgui.Create("DButton", frame)
	
	button2.width = 110
	button2.height = 25
	button2.x = 25
	button2.y = 130
	
	button2:SetSize(button2.width, button2.height)
	button2:SetPos(button2.x, button2.y)
	button2:SetText("Set Tag Color")
	
	--Change Name Color button
	local button3 = vgui.Create("DButton", frame)
	
	button3.width = 110
	button3.height = 25
	button3.x = 25
	button3.y = 250
	
	button3:SetSize(button3.width, button3.height)
	button3:SetPos(button3.x, button3.y)
	button3:SetText("Set Name Color")
	
	--Tag text entry
	local tagEntry = vgui.Create("DTextEntry", frame)
	
	tagEntry.x = button1.x + 134
	tagEntry.y = button1.y + 2
	
	tagEntry:SetPos(tagEntry.x, tagEntry.y)
	tagEntry:SetSize(180, 20)
	tagEntry:SetUpdateOnType(true)
	tagEntry:SetText("Enter Custom Tag")
	
	tagEntry.OnValueChange = function(self)
		tagEntry.value = self:GetValue()
	end
	
	-- Tag Color Mixer
	local colorPicker1 = vgui.Create("DColorMixer", frame)
	
	colorPicker1.x = button2.x + 135
	colorPicker1.y = button2.y - 30
	
	colorPicker1:SetPos(colorPicker1.x, colorPicker1.y)
	colorPicker1:SetPalette(false)
	colorPicker1:SetAlphaBar(false)
	colorPicker1:SetColor(Color(30, 100, 160) )
	colorPicker1:SetSize(180, 100)
	
	-- Name Color Mixer
	local colorPicker2 = vgui.Create("DColorMixer", frame)
	
	colorPicker2.x = button3.x + 135
	colorPicker2.y = button3.y - 30
	
	colorPicker2:SetPos(colorPicker2.x, colorPicker2.y)
	colorPicker2:SetPalette(false)
	colorPicker2:SetAlphaBar(false)
	colorPicker2:SetColor(Color(30, 100, 160) )
	colorPicker2:SetSize(180, 100)
	
	-- Set tag button is pressed
	button1.DoClick = function()
		if tagEntry.value then
			tag.CustomTag = tagEntry.value
			tag.Enabled = true
			
			--send tag info to server
			net.Start("button1Pressed")
				net.WriteString(tag.CustomTag)
			net.SendToServer()
			
			if tag.CustomColor then
				chat.AddText(Color(255,0,0,255), "[Tags] ", color_white, "You have set your tag to ", tag.CustomColor, tag.CustomTag, color_white, "."  )
			else
				chat.AddText(Color(255,0,0,255), "[Tags] ", color_white, "You have set your tag to ", color.defaultTag, tag.CustomTag, color_white, "."  )
			end
		else
			chat.AddText(color.tagError, "[Tags] Error: ", color_white, "Please enter a valid tag.")
		end
	end
	
	-- Tag Color button pressed
	button2.DoClick = function()
		if tag.Enabled == true then
			tag.CustomColor = colorPicker1:GetColor()
			
			--send tag color info to server
			net.Start("button2Pressed")
				net.WriteColor(tag.CustomColor)
			net.SendToServer()
		
			chat.AddText(Color(255,0,0,255), "[Tags] ", color_white, "Tag color changed: ", tag.CustomColor, tag.CustomTag, color_white, "." )
		else
			chat.AddText(color.tagError, "[Tags] Error: ", color_white, "You must have a tag enabled to set it's color!")
		end
	end

	-- Name Color button pressed
	button3.DoClick = function(ply)
		if ply == LocalPlayer() then
			tag.CustomNameColor = colorPicker2:GetColor()
			chat.AddText(Color(255,0,0,255), "[Tags] ", color_white, "Name color changed: ", tag.CustomNameColor, ply:Nick(), color_white, "." )
		end
	end
	
end

// - Playerchat Hook - //

hook.Add("OnPlayerChat", "PlayerChat", function( ply, text, Team, PlayerIsDead ) 
	
	if text == "!tags" then 
		if ply == LocalPlayer() then -- check if the player who typed !text is local player
			pMeta:MenuOpen() -- if yes then open the menu
		end
	end
	
	if tag.Enabled == true then
		chat.AddText(tag.CustomColor, "[", tag.CustomTag, "]", " ", tag.CustomNameColor, ply:Nick(), ": ", color_white, text)
		return true
	else
		for k, v in pairs(defaultTags) do
			if ply:IsUserGroup(v[1]) then
				if Team then
					if ply:Alive() then
						chat.AddText(Color(0, 204, 0, 255), "{TEAM} ", v[3], "[", v[2], "] ", ply:Nick(), color_white, ": ", Color(255, 255, 255, 255), text)
					elseif not ply:Alive() then
						chat.AddText(Color(255, 0, 0, 255), "*DEAD*", Color(0, 204, 0, 255), "{TEAM} ", v[3], "[", v[2], "] ", ply:Nick(), color_white, ": ", Color(255, 255, 255, 255), text)
					end
					return true
				end
				
				if ply:IsPlayer() then
					if ply:Alive() then
						chat.AddText(Color(255, 0, 0, 255), "", v[3], "[", v[2], "] ", ply:Nick(), color_white, ": ", Color(255, 255, 255, 255), text)
					elseif not ply:Alive() then
						chat.AddText(Color(255, 0, 0, 255), "*Dead* ", v[3], "[", v[2], "] ", ply:Nick(), color_white, ": ", Color(255, 255, 255, 255), text)
					end
					return true
				end
			end
		end
	end
end )

net.Receive("SendServerTagInfo", function() 
	print("Client got the server tag info!")
end )

net.Receive("SendServerColorInfo", function() 
end )


[editline]19th July 2017[/editline]

I am trying to make the tags unique and seen by all players.

Create a table with all the players tags in and then use the player as the key and the data as value.
You should also do this on the server, so when a new player joins they can be sent the tags data so they are always correct.
One last thing is don’t forget to remove the old players tags when they leave to stop memory being eaten.