shrubbot command to team chat


(NovaPrime) #1

How do I make a shrubbot command pipe to team chat?

example (not working)

[command]
command = ammo
exec = say_team [n]: ^7Need Ammo!! ^1Only [t] Ammo Left For My [w]! ; wait 100
desc = Announce you are low on Ammo
levels = 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23


(twt_thunder) #2

on what mod? this doesnt work on all mods


(stealth6) #3

I’m not sure it’s possible.

The custom commands allow you to execute server side cvars. That’s why say_team doesn’t work since it’s a client side cvar.
say is both client & server side.

I’m pretty sure you can do it with lua though, just scan incoming text for the command then use et.G_Say( clientNum, mode, text ) I think to send the text.


(NovaPrime) #4

@ thunder
I am using etpub

@Stealth
do you have any working scripts I can add that string into? or maybe a more detailed example of how to do this? I use lua but don’t know how to start a script from scratch.

by the way, what are all the message shortcuts (i.e., CP, chat…etc)?


(twt_thunder) #5

say_team wont work anyhow…

it has to be something like this:

[command]
command =ammo
exec = cp “I am low on ammo”
desc = Center Print the text “I am low on ammo” to all connected clients
levels = 0 1 2 3 4 5

and that will as it says say it to all


(Micha) #6

You could do this command with lua. You could create a / or ! command.


(NovaPrime) #7

Stealth said to use “et.G_Say( clientNum, mode, text )” in a lua, which part of this points to the team chat? the g_say or the mode? if the mode, what can I replace it with to pipe to team chat?


(NovaPrime) #8

ok, this don’t work but am I on the right track?



--      > Ammo and Location Team Chat Commands
--      > Initial Alpha version
--	> /ammo
--	> /location

--Refister the mod
function et_InitGame(levelTime,randomSeed,restart)
	et.RegisterModname("ammo")
end

-- Set to 0 if you want to disable these commands
USE_AMMO = 1
USE_LOCATION = 1

-- Set NUMINFO to the number of AMMO that will be printed in the client console
NUMINFO = 2

-- Add a new line for each rule.
-- Make sure you set NUMINFO value above to the correct number of info.
Ammo = {
	"",
	"[n]: ^7Need Ammo!! ^1Only [t] Ammo Left For My [w]!",
}

-- Used for /location (print a location URL in the client's console)
-- Define your location below
LOCATION = "[n]: ^7I am at location [L]"

function et_ClientCommand(clientNum, command)
	command = string.lower(command)
		--If a client types "/ammo" in his console
		if (command == "AMMO") and (USE_AMMO == 1) then
			for i=1,(NUMINFO),1 do
				et.G_Say( clientNum, "print \"" .. AMMO .."^7
\"" )
			end
		return 1
		--If a client types "/location in his console
		elseif (command == "location") and (USE_LOCATION == 1) then
				et.G_Say( clientNum, "print \"" .. LOCATION .."^7
\"" )
				return 1
		end
end


(acQu) #9

Mode 1 in et.G_Say should be teamchat in etpro.

Check if this prints it the correct way:

		if (command == "ammo") and (USE_AMMO == 1) then
			et.G_Say( clientNum, 1, "Need Ammo" )

Long time i did not touch lua :rolleyes:


(Micha) #10

So you want to see the location of the player which is asking for ammo?

Ammo = {
“”,
“[n]: ^7Need Ammo!! ^1Only [t] Ammo Left For My [w]!”,
}

This is a table. The [n] and so on isn’t needed in lua.
Also you don’t need for i=1,(NUMINFO),1 do stuff on this.

local ammo = et.gentity_get(clientNum, “ps.ammo”)
local name = et.Info_ValueForKey(et.trap_GetUserinfo(clientNum), “name”)
local weapon = et.gentity_get(clientNum, “sess.PlayerWeapon”)

et.trap_SendConsoleCommand( et.SAY_TEAM, “qsay “…name…”: ^7Need Ammo!! ^1Only “…ammo…” Ammo Left For My “…weapon…”!” )

Should be possible to check all players ps.ammo and make it like (just an example/not working)


function et_RunFrame(leveltime)
        local maxClients = tonumber(et.trap_Cvar_Get("sv_maxclients")) - 1;
        for client=0, maxClients do
          local ammo = et.gentity_get(client, "ps.ammo")
          if ammo < 30 and antispam == nil then
             if checkclass(client) == 3 then
                et.trap_SendServerCommand(client, "chat \""..PlayerX.." needs ammo!
\"" )
                antispam = 1
             end
         end
        end
end

--0=Soldier, 1=Medic, 2=Engineer, 3=FieldOps, 4=CovertOps
function checkclass(client)
   local cs = et.trap_GetConfigstring(et.CS_PLAYERS + client)
    return tonumber(et.Info_ValueForKey(cs, "c"))
end

Anyways I can have a look at it if you want. I got a lua for revive that works like this. Thanks to PerlO_oung?! :slight_smile:

EDIT

Ok I did some coding and could manage to make a lua. It’s not fully tested and I’m not sure if it fits what you want/need.


--[[

	Revive Ammo Addon
	===================
	by Micha!

	Further information:
	--------------------
	http://forums.warchest.com/showthread.php/38943-shrubbot-command-to-team-chat
	
	
	Contact:
	--------------------
	http://www.teammuppet.eu
	
	
	Info:
	--------------------
	Commands usage: 	/rpos		/ammo		!rpos		!ammo

--]]---------------------------------------------------------------------------------
---------------------------------CONFIG START----------------------------------------
--[[---------------------------------------------------------------------------------

true means on
false means off

--]]

commandprefix =			"!"							--command prefix

admin_min_level = 		0							--minimum admin level needed to use the shrubbot commands

rpos_cmd =				"rpos"						--revive position command
ammo_cmd =				"ammo"						--ammo command

ammosound = 			"sound/chat/axis/22a.wav"	--ammo sound file

countammoclip = 		true						--true: count ammo and ammoclip
													--false: only count ammo

-------------------------------------------------------------------------------------
-------------------------------CONFIG END--------------------------------------------
-------------------------------------------------------------------------------------

-------------------------------------------------------------------------------------
----------DO NOT CHANGE THE FOLLOWING IF YOU DO NOT KNOW WHAT YOU ARE DOING----------
-------------------------------------------------------------------------------------

Version = "0.1"
Modname = "revive_ammo_addon"

-------------global vars----------------
et.CS_PLAYERS = 689
woundedplayers = {}
local spaces = 2
local string_out = "" -- will hold up to 5 players
----------------------------------------

weapontable = { 
[3]=	"MP40",
[5]=	"Panzerfaust",
[6]=	"Flamethrower",
[8]=	"Thompson",
[10]=	"Sten", 
[23]=	"K43 Rifle",
[24]=	"M1 Rifle",
[25]=	"M1 Garand", 
[31]=	"MG42", 
[32]=	"K43",
[33]=	"FG42", 
[35]=	"Mortar", 
}

-------//---------------------Start of functions----------------------------

function et_InitGame(levelTime,randomSeed,restart)
	mclients = tonumber( et.trap_Cvar_Get( "sv_maxClients" ) )
	
    et.G_Print("["..Modname.."] Version: "..Version.." Loaded
")
    et.RegisterModname(Modname.." "..Version.." "..et.FindSelf())

	rpos = {}
	fops = {}
end

function et_ClientCommand(clientNum, command)
	local argv1 = string.lower(et.trap_Argv(1))

  -------//--------------------revive----------------------------
  if string.lower(command) == rpos_cmd or ( string.find(argv1, "^"..commandprefix.."" .. rpos_cmd .. "") and getlevel(clientNum) ) then
	for i=0, mclients-1, 1 do
		RevivePos(clientNum,i)
	end
	table.sort(rpos)
	if rpos[1] == nil then
	 et.trap_SendServerCommand(clientNum, "chat \"^3REVIVEME: ^7No person to revive near you!\"" )
	else
   	 et.trap_SendServerCommand(clientNum, "chat \"^3REVIVEME: ^7Next person to revive in ^1"..rpos[1].."m ^7near you!\"" )
	 
		local v
		local player_count = 0	
		for i=1, table.getn(woundedplayers), 1 do
			v = woundedplayers[i]
			player_count = player_count + 1
			string_out = string_out .. "^7" .. playerName(v)
			if ( player_count < 5) then				    
				string_out = string_out .. string.rep(" ", spaces - string.len(v))
			end
			if ( player_count >= 5 ) then
				player_count = 0
				v = string.format(string_out)
				et.trap_SendServerCommand(clientNum,"chat \"^3REVIVEME^7: ^7"..v.."\"")
				string_out = ""
				woundedplayers = {}
			end
		end
		if (string.len(string_out) > 0) then
			v = string.format(string_out)
			et.trap_SendServerCommand(clientNum,"chat \"^3REVIVEME^7: ^7"..v.."\"")
			string_out = ""
			woundedplayers = {}
		end
	end
	rpos = {}
	
	-------//--------------------return----------------------------
	if string.lower(command) == "rpos" then return 1 end
	if string.find(argv1, "^"..commandprefix.."" .. rpos_cmd .. "") then return end
  end
  
	-------//--------------------ammo----------------------------
	if string.lower(command) == ammo_cmd or ( string.find(argv1, "^"..commandprefix.."" .. ammo_cmd .. "") and getlevel(clientNum) ) then
		for i=0, mclients-1, 1 do
			if et.gentity_get(i, "sess.sessionTeam") == et.gentity_get(clientNum, "sess.sessionTeam") then
				weaponcode = et.gentity_get(clientNum, "sess.PlayerWeapon")
				local weaponname = weapontable[weaponcode]
				-------//--------------------check ammo----------------------------
				if weaponcode == 5 or weaponcode == 6 or weaponcode == 35 then --in case it's: Panzerfaust, Flamethrower or Mortar
					ammo = et.gentity_get(clientNum, "ps.ammoclip", weaponcode)
				else
					-------//--------------------check ammo----------------------------
					if countammoclip then
						ammo = et.gentity_get(clientNum, "ps.ammo", weaponcode) + et.gentity_get(clientNum, "ps.ammoclip", weaponcode)
					elseif countammoclip == false then
						ammo = et.gentity_get(clientNum, "ps.ammo", weaponcode)
					end
				end
					--[[ --only works on new etpub so I disabled it for now
					if weaponname then
						et.trap_SendServerCommand(-1, "tc clientNum \"^3Need Ammo!! ^7Only ^1"..ammo.." ^7ammo left for my ^1"..weaponname.."^7!\"")
					else
						et.trap_SendServerCommand(-1, "tc clientNum \"^3Need Ammo!! ^7Only ^1"..ammo.." ^7ammo left^7! "..weaponcode.."\"")
					end
					--]]
				if weaponname then --weapon is known ? (out of weapontable)
					et.trap_SendServerCommand(i, "chat \"^7"..playerName(clientNum).."^7: ^3I Need Ammo! ^7Only ^1"..ammo.." ^7ammo left for my ^1"..weaponname.."^7!\"")
				else
					et.trap_SendServerCommand(i, "chat \"^7"..playerName(clientNum).."^7: ^3I Need Ammo! ^7Only ^1"..ammo.." ^7ammo left^7!\"")
				end
				et.G_ClientSound( i, et.G_SoundIndex(ammosound) )
				-------//--------------------find fieldops----------------------------
				for cno=0, mclients-1, 1 do
					FindFops(clientNum,cno)
				end
				
				table.sort(fops)
				if fops[1] == nil then
					et.trap_SendServerCommand(clientNum, "chat \"^3AMMO: ^7No fieldops to supply near you!\"" )
				else
					et.trap_SendServerCommand(clientNum, "chat \"^3AMMO: ^7Next fieldops to supply you in ^1"..fops[1].."m ^7near you!\"" )
				end
				fops = {}
				
				-------//--------------------return----------------------------
				if string.lower(command) == "ammo" then return 1 end
				if string.find(argv1, "^"..commandprefix.."" .. ammo_cmd .. "") then return end
			end
		end
	end
    -------//--------------------end----------------------------
    return 0   -- allows the cmd
 end

-------//--------------------player name----------------------------
function playerName(id) -- return a player's name
  local name = et.Info_ValueForKey(et.trap_GetUserinfo(id), "name")
  if name == "" then
    return "*unknown*"
  end
  return name
end

-------//--------------------revive position----------------------------
function RevivePos(caller,id)
	if caller == id then return 1 end
	if et.gentity_get(id, "sess.sessionTeam") == 3 or et.gentity_get(caller, "sess.sessionTeam") == 3 then return 1 end
	if et.gentity_get(caller, "sess.sessionTeam") == et.gentity_get(id, "sess.sessionTeam") then
		if et.gentity_get(id, "health") <= 0 and et.gentity_get(id, "r.contents") ~= 0 then
			local callerpos = et.gentity_get(caller,"r.currentOrigin")
			local idpos = et.gentity_get(id,"r.currentOrigin")
			distance = dist(callerpos,idpos)
			table.insert(rpos,distance)
			table.insert(woundedplayers,id)
		end
	end
end

-------//--------------------fieldops position----------------------------
function FindFops(caller,id)
	if caller == id then return 1 end
	if et.gentity_get(id, "sess.sessionTeam") == 3 or et.gentity_get(caller, "sess.sessionTeam") == 3 then return 1 end
	if et.gentity_get(caller, "sess.sessionTeam") == et.gentity_get(id, "sess.sessionTeam") then
		if checkclass(id) == 3 then
			local callerpos = et.gentity_get(caller,"r.currentOrigin")
			local idpos = et.gentity_get(id,"r.currentOrigin")
			distance = dist(callerpos,idpos)
			table.insert(fops,distance)
		end
	end
end
	
-------//--------------------distance----------------------------
function dist(a ,b)
   local dx = math.abs(b[1] - a[1])
   local dy = math.abs(b[2] - a[2])
   local dz = math.abs(b[3] - a[3])
   local d = math.sqrt((dx ^ 2) + (dy ^ 2) + (dz ^ 2))
   return math.floor(d / 52.4934)
end

-------//--------------------player class----------------------------
--0=Soldier, 1=Medic, 2=Engineer, 3=FieldOps, 4=CovertOps
function checkclass(client)
   local cs = et.trap_GetConfigstring(et.CS_PLAYERS + client)
    return tonumber(et.Info_ValueForKey(cs, "c"))
end

-------//--------------------get player shrubbot level----------------------------
function getlevel(client)
    local lvl = et.G_shrubbot_level(client)
    if lvl >= admin_min_level then
        return true
    end
        return nil
end


(NovaPrime) #11

@acqu
I made that change and it did report in team chat, but the rest of my script was buggy, I will probably try to add your line to Micha’s below

@Micha

Very nice script! please add one more “end” at bottom, my server gave me an error, but then it worked once I added.

Not sure if this delivers only in team chat, but hey I love it anyway! I like how it reports if no fdops is near :slight_smile:

I will see if acqu’s mode fix will work on your script and then it will be 100% !!!


(stealth6) #12

I’ve never finished a lua script for ET before, but I just read about the et.G_say on the lua wiki for ET. (Looks like acQu & Micha know what they’re talking about though :))

et.G_Say( clientNum, mode, text )
Sends a chat command on behalf of client clientNum with the mode mode (see et.SAY_* constants) and chat text text.


predefined constants
et.SAY_ALL
et.SAY_TEAM
et.SAY_BUDDY
et.SAY_TEAMNL

source: http://wolfwiki.anime.net/index.php/ETPro:Lua_Mod_API

I checked Micha’s script, but I can’t see the missing end statement?
After reading through Micha’s script a bit it seems like it’s easy to retreive the ammo & weapon that the player is using, but it does use 20-30 lines :tongue:

I still wonder if you can use


et.G_Say( i, et.SAY_TEAM, "^7Need Ammo!! ^1Only [t] Ammo Left For My [w]!" )

instead of


et.trap_SendServerCommand(i, "chat \"^7"..playerName(clientNum).."^7: ^3I Need Ammo! ^7Only ^1"..ammo.." ^7ammo left for my ^1"..weaponname.."^7!\"")

Will [t] & [w] work this way? Obviously Micha’s way is better if you want it to work on all mods.


(acQu) #13

[QUOTE=stealth6;486655]I still wonder if you can use


et.G_Say( i, et.SAY_TEAM, "^7Need Ammo!! ^1Only [t] Ammo Left For My [w]!" )

instead of


et.trap_SendServerCommand(i, "chat \"^7"..playerName(clientNum).."^7: ^3I Need Ammo! ^7Only ^1"..ammo.." ^7ammo left for my ^1"..weaponname.."^7!\"")

Will [t] & [w] work this way? Obviously Micha’s way is better if you want it to work on all mods.[/QUOTE]

First line should work on all mods. Just rechecked the etpub Lua sources for that. Only thing i was worried about was the constants not defined, but they are here: https://www.assembla.com/code/etpub/subversion/nodes/565/trunk/src/game/g_lua.c#ln1649. As pretty much all other mods have based their Lua on etpub Lua (except of course etpro), it should work on all mods the same way. Second line is also a possibility.


(Micha) #14

I tested and noticed so I come up with the following lua. I tried to use what acQu said but I just get problems using et.G_Say.
I added a anti spam counter to ammo and it also sends the message just to fops if wished.

Anyways you are free to edit the lua. Just post it here :slight_smile:


--[[

	Revive Ammo Addon
	===================
	by Micha!

	Further information:
	--------------------
	http://forums.warchest.com/showthread.php/38943-shrubbot-command-to-team-chat
	
	
	Contact:
	--------------------
	http://www.teammuppet.eu
	
	
	Info:
	--------------------
	Commands usage: 	/rpos		/ammo		!rpos		!ammo

--]]---------------------------------------------------------------------------------
---------------------------------CONFIG START----------------------------------------
--[[---------------------------------------------------------------------------------

true means on
false means off

--]]

commandprefix =			"!"							--command prefix

admin_min_level = 		0							--minimum admin level needed to use the shrubbot commands

rpos_cmd =				"rpos"						--revive position command
ammo_cmd =				"ammo"						--ammo command

ammosound = 			"sound/chat/axis/22a.wav"	--ammo sound file

countammoclip = 		true						--true: count ammo and ammoclip
													--false: only count ammo
													
antispam = 				true						--just show "I Need Ammo" message and play sound to fieldops (less spam)
antispammax = 			2							--anti spam maximum -> x time allowed to use the command, counter will start after this value
blocktime = 			20							--wait time after anti spam maximum is hit (in seconds)

-------------------------------------------------------------------------------------
-------------------------------CONFIG END--------------------------------------------
-------------------------------------------------------------------------------------

-------------------------------------------------------------------------------------
----------DO NOT CHANGE THE FOLLOWING IF YOU DO NOT KNOW WHAT YOU ARE DOING----------
-------------------------------------------------------------------------------------

Version = "0.2"
Modname = "revive_ammo_addon"

-------------global vars----------------
samplerate = 1000
et.CS_PLAYERS = 689
woundedplayers = {}
local spaces = 2
local string_out = "" -- will hold up to 5 players
antispamcounter = {}
waittimer = {}
----------------------------------------

weapontable = {
[0]=	"SMG", --can be used from allies and axis
[3]=	"MP40",
[5]=	"Panzerfaust",
[6]=	"Flamethrower",
[8]=	"Thompson",
[10]=	"Sten", 
[23]=	"K43 Rifle",
[24]=	"M1 Rifle",
[25]=	"M1 Garand", 
[31]=	"MG42", 
[32]=	"K43",
[33]=	"FG42", 
[35]=	"Mortar", 
}

-------//---------------------Start of functions----------------------------

function et_InitGame(levelTime,randomSeed,restart)
	mclients = tonumber( et.trap_Cvar_Get( "sv_maxClients" ) )
	
    et.G_Print("["..Modname.."] Version: "..Version.." Loaded
")
    et.RegisterModname(Modname.." "..Version.." "..et.FindSelf())

	rpos = {}
	fops = {}
	
	for clientNum=0, mclients-1, 1 do
		antispamcounter[clientNum] = 0
		waittimer[clientNum] = 0
	end
	
end

function et_ClientCommand(clientNum, command)
	local argv1 = string.lower(et.trap_Argv(1))

	-------//--------------------revive----------------------------
	if string.lower(command) == rpos_cmd or ( string.find(argv1, "^"..commandprefix.."" .. rpos_cmd .. "") and getlevel(clientNum) ) then
		if et.gentity_get(clientNum, "sess.sessionTeam") == 3 then
			et.trap_SendServerCommand(clientNum, "chat \"^3REVIVEME: ^7Can't execute this command while beeing in spectator mode\"")
			return 1
		end
		for i=0, mclients-1, 1 do
			RevivePos(clientNum,i)
		end
		table.sort(rpos)
		if rpos[1] == nil then
			et.trap_SendServerCommand(clientNum, "chat \"^3REVIVEME: ^7No person to revive near you!\"" )
		else
			et.trap_SendServerCommand(clientNum, "chat \"^3REVIVEME: ^7Next person to revive in ^1"..rpos[1].."m ^7near you!\"" )
	 
			local v
			local player_count = 0	
			for i=1, table.getn(woundedplayers), 1 do
				v = woundedplayers[i]
				player_count = player_count + 1
				string_out = string_out .. "^7" .. playerName(v)
				if ( player_count < 5) then				    
					string_out = string_out .. string.rep(" ", spaces - string.len(v))
				end
				if ( player_count >= 5 ) then
					player_count = 0
					v = string.format(string_out)
					et.trap_SendServerCommand(clientNum,"chat \"^3REVIVEME^7: ^7"..v.."\"")
					string_out = ""
					woundedplayers = {}
				end
			end
			if (string.len(string_out) > 0) then
				v = string.format(string_out)
				et.trap_SendServerCommand(clientNum,"chat \"^3REVIVEME^7: ^7"..v.."\"")
				string_out = ""
				woundedplayers = {}
			end
		end
		rpos = {}
	
		-------//--------------------return----------------------------
		if string.lower(command) == "rpos" then return 1 end
		if string.find(argv1, "^"..commandprefix.."" .. rpos_cmd .. "") then return end
	end
  
	-------//--------------------ammo----------------------------
	if string.lower(command) == ammo_cmd or ( string.find(argv1, "^"..commandprefix.."" .. ammo_cmd .. "") and getlevel(clientNum) ) then
		if et.gentity_get(clientNum, "sess.sessionTeam") == 3 then
			et.trap_SendServerCommand(clientNum, "chat \"^3AMMO: ^7Can't execute this command while beeing in spectator mode\"")
			if string.lower(command) == "ammo" then return 1 end
			if string.find(argv1, "^"..commandprefix.."" .. ammo_cmd .. "") then return end
		end
		
		-------//--------------------anti spam----------------------------
		antispamcounter[clientNum] = antispamcounter[clientNum] + 1
		if antispamcounter[clientNum] > antispammax then
			local seconds = (blocktime - waittimer[clientNum])
			et.trap_SendServerCommand(clientNum, "chat \"^3AMMO: ^7You need to wait ^1"..seconds.." sec ^7till you can do the cmd again\"")
			if string.lower(command) == "ammo" then return 1 end
			if string.find(argv1, "^"..commandprefix.."" .. ammo_cmd .. "") then return end
		end
		
		for i=0, mclients-1, 1 do
			if et.gentity_get(i, "sess.sessionTeam") == et.gentity_get(clientNum, "sess.sessionTeam") then
				
				AmmoCheck(clientNum)
				
				for cno=0, mclients-1, 1 do --only use the clients on same team
					if antispam then --hm maybe just play the ammo sound/message to just fieldops for less annoying spam
						if checkclass(cno) == 3 then
							if weaponname then --weapon is known ? (out of weapontable)
								et.trap_SendServerCommand(cno, "chat \"^7"..playerName(clientNum).."^7: ^3I Need Ammo! ^7Only ^1"..ammo.." ^7ammo left for my ^1"..weaponname.."^7!\"")
							else
								et.trap_SendServerCommand(cno, "chat \"^7"..playerName(clientNum).."^7: ^3I Need Ammo! ^7Only ^1"..ammo.." ^7ammo left^7!\"")
							end

							et.G_ClientSound( cno, et.G_SoundIndex(ammosound) )
						end
						
					elseif antispam == false then
						if weaponname then --weapon is known ? (out of weapontable)
							et.trap_SendServerCommand(cno, "chat \"^7"..playerName(clientNum).."^7: ^3I Need Ammo! ^7Only ^1"..ammo.." ^7ammo left for my ^1"..weaponname.."^7!\"")
						else
							et.trap_SendServerCommand(cno, "chat \"^7"..playerName(clientNum).."^7: ^3I Need Ammo! ^7Only ^1"..ammo.." ^7ammo left^7!\"")
						end

						et.G_ClientSound( cno, et.G_SoundIndex(ammosound) )
					end
					-------//--------------------find fieldops----------------------------
					FindFops(clientNum,cno)
				end
				
				table.sort(fops)
				if fops[1] == nil then
					et.trap_SendServerCommand(clientNum, "chat \"^3AMMO: ^7No fieldops to supply you near you!\"" )
				else
					et.trap_SendServerCommand(clientNum, "chat \"^3AMMO: ^7Next fieldops to supply you in ^1"..fops[1].."m ^7near you!\"" )
				end
				fops = {}
				
				-------//--------------------return----------------------------
				if string.lower(command) == "ammo" then return 1 end
				if string.find(argv1, "^"..commandprefix.."" .. ammo_cmd .. "") then return end
			end
		end
	end
    -------//--------------------end----------------------------
    return 0   -- allows the cmd
 end
 
 -------//--------------------anti spam ticker----------------------------
 function et_RunFrame( levelTime )
	if math.mod(levelTime, samplerate) ~= 0 then return end
	for cno=0, mclients-1, 1 do
		if antispamcounter[cno] >= 3 then
			waittimer[cno] = waittimer[cno] + 1
		end
		if waittimer[cno] == blocktime then
			antispamcounter[cno] = 0
			waittimer[cno] = 0
		end
	end
 end

-------//--------------------player name----------------------------
function playerName(id) -- return a player's name
  local name = et.Info_ValueForKey(et.trap_GetUserinfo(id), "name")
  if name == "" then
    return "*unknown*"
  end
  return name
end

-------//--------------------revive position----------------------------
function RevivePos(caller,id)
	if caller == id then return 1 end
	if et.gentity_get(id, "sess.sessionTeam") == 3 or et.gentity_get(caller, "sess.sessionTeam") == 3 then return 1 end
	if et.gentity_get(caller, "sess.sessionTeam") == et.gentity_get(id, "sess.sessionTeam") then
		if et.gentity_get(id, "health") <= 0 and et.gentity_get(id, "r.contents") ~= 0 then
			local callerpos = et.gentity_get(caller,"r.currentOrigin")
			local idpos = et.gentity_get(id,"r.currentOrigin")
			distance = dist(callerpos,idpos)
			table.insert(rpos,distance)
			table.insert(woundedplayers,id)
		end
	end
end

-------//--------------------fieldops position----------------------------
function FindFops(caller,id)
	if caller == id then return 1 end
	if et.gentity_get(id, "sess.sessionTeam") == 3 or et.gentity_get(caller, "sess.sessionTeam") == 3 then return 1 end
	if et.gentity_get(caller, "sess.sessionTeam") == et.gentity_get(id, "sess.sessionTeam") then
		if checkclass(id) == 3 then
			local callerpos = et.gentity_get(caller,"r.currentOrigin")
			local idpos = et.gentity_get(id,"r.currentOrigin")
			distance = dist(callerpos,idpos)
			table.insert(fops,distance)
		end
	end
end
	
-------//--------------------distance----------------------------
function dist(a ,b)
   local dx = math.abs(b[1] - a[1])
   local dy = math.abs(b[2] - a[2])
   local dz = math.abs(b[3] - a[3])
   local d = math.sqrt((dx ^ 2) + (dy ^ 2) + (dz ^ 2))
   return math.floor(d / 52.4934)
end

-------//--------------------Ammo check----------------------------
function AmmoCheck(clientNum)
	weaponcode = et.gentity_get(clientNum, "sess.PlayerWeapon")
	weaponname = weapontable[weaponcode]
	-------//--------------------check ammo----------------------------
	if weaponcode == 5 or weaponcode == 6 or weaponcode == 35 then --in case it's: Panzerfaust, Flamethrower or Mortar
		ammo = et.gentity_get(clientNum, "ps.ammoclip", weaponcode)
	else
		-------//--------------------check ammo----------------------------
		if countammoclip then
			ammo = et.gentity_get(clientNum, "ps.ammo", weaponcode) + et.gentity_get(clientNum, "ps.ammoclip", weaponcode)
		elseif countammoclip == false then
			ammo = et.gentity_get(clientNum, "ps.ammo", weaponcode)
		end
	end
end

-------//--------------------player class----------------------------
--0=Soldier, 1=Medic, 2=Engineer, 3=FieldOps, 4=CovertOps
function checkclass(client)
   local cs = et.trap_GetConfigstring(et.CS_PLAYERS + client)
    return tonumber(et.Info_ValueForKey(cs, "c"))
end

-------//--------------------get player shrubbot level----------------------------
function getlevel(client)
    local lvl = et.G_shrubbot_level(client)
    if lvl >= admin_min_level then
        return true
    end
        return nil
end

btw to answer this threads main question:


function et_ClientCommand(clientNum, command)
   mclients = tonumber( et.trap_Cvar_Get( "sv_maxClients" ) )  
   for i=0, mclients-1, 1 do
       if et.gentity_get(i, "sess.sessionTeam") == et.gentity_get(clientNum, "sess.sessionTeam") then
          for cno=0, mclients-1, 1 do
            if command == "blub" then
              et.trap_SendServerCommand(cno, "chat \"^7Hi team mates\"")
           end
         end
       end
   end
end

Also see this (out of etpub lua doc):

SERVER COMMANDS

et.trap_SendServerCommand() is used to send a command from the server to one or more clients. The first argument is the slot number of the client the command will be sent to. If it’s equal to -1, the command will be broadcast to all clients.

The following commands can be issued with this function:
Chatting

“c clientNum “message””

c prints message as a global chat message on behalf of the client specified by clientNum.

“tc clientNum “message” X-location Y-location Z-location”

tc prints message as a team chat message on behalf of the client specified by clientNum.
The X, Y and Z-location's are optional parameters that represent the client's location.
If the X, Y and Z-location's are left out then the message will be printed without a location.

“bc clientNum “message” X-location Y-location Z-location”

bc prints message as a fireteam chat message on behalf of the client specified by clientNum.
The X, Y and Z-location's are optional parameters that represent the client's location.
If the X, Y and Z-location's are left out then the message will be printed without a location.