To be honest benchmark will not help you much unless you have your own dedicated server. If you have your own server I would suggest using munin or any other lower level monitoring tools to monitor your HD, CPU and RAM usage. Munin has good plugins too.
If that fixed the issue then it seems like HD I/O issue on your server. Try this command on u Linux shell and
dd if=/dev/zero of=test bs=64k count=16k conv=fdatasyncAnd post the output here. It might give an idea if something is wrong with hard drives.
There is currently panzerwar, sniperwar and riflewar . . . so I was wondering if a !pistolwar could be also added to the next edition of the silentmod ?
OR You can run cron on your server to get new geoip.dat every month That would be much easier ... I try to set up my basic things as cron so I don't have to worry to update it and it always get updated.
I thought always that this 'inside' feature is the best side of this anticheat, it makes it more secure and more difficult to understand by crackers. Additionally making something from outside is a way harder than inside, there is several reasons that explain that: compatibility, security, complexity.
I know that typing [g] shows your silEnT GUID and typing it into fireteam chat whilst not in a fireteam will work to do it privately, but for absolute security, I wanted to make a custom command of !myguid so I made this LUA script.. Problem is I have never ever touched anything LUA or ET related, so I have no idea if this will even work and I have no means of testing it.. So I wonder if someone can tell me if I've done anything wrong, and/or if it will actually work?
----------------------------------------------------------------------
-- Filename: myguid.lua
----------------------------------------------------------------------
-- MyGUID - Prints your silEnT GUID just like /cl_guid would for etkey based GUIDs.
----------------------------------------------------------------------
-- Created by =F|A=Chuckun
-- If you use it, please donate to our clan to help fund the servers
-- Any amount will help!!
-- Fearless-Assassins.com
----------------------------------------------------------------------
-- For use with shrubbot, exec 'getmyguid'
----------------------------------------------------------------------
description = "silEnT GUID Command"
version = "1.0"
function et_InitGame(levelTime,randomSeed,restart)
local modname = string.format("%s", description)
et.G_Print(string.format("%s loaded\n", modname))
et.RegisterModname(modname)
end
function et_ConsoleCommand(command)
if et.trap_Argv(0) == "getmyguid" then
local userinfo = et.trap_GetUserinfo( playerID )
local guid = et.Info_ValueForKey( userinfo, "sil_guid" )
et.trap_SendServerCommand(clientNum, "print \"^osilEnT GUID: ^7"..guid.."\n")
end
return 1
end
Or perhaps there's an easier way to simply print the GUID within the command's exec line, with no need for any LUA mod?
I would like to request an enhancement to the HUD. It would be nice to have a visual indicator (maybe the green circle thingie with the exclamation point in it) on the screen while an objective has been captured by another player. Right now, as far as I know you have to look in the player list to see if someone has something. Its an extra tap and it sometimes goes unnoticed with all the other noise and chatter that someone actually has the objective. Think about a map like Frostbite, I know there are times when I didn't realize allies had the docs and I'm totally out of position and they win the map.
I like how right now there is the popup when a dynamite is planted. It shows the location of the dynamite and it is clear and obvious that an engineer is needed quickly. I think the same kind of notification would be nice - just a little green popup when someone has an objective.
Now - I'm not sure how this would be handled on maps like Baserace, where both teams can have objective. Maybe some kind of alternate colors (blue and red) for the icon to show which team has an objective.
Like solar and Dragonji already pointed out, ETPro sourcecode is not available. But I will add as a representative of the silEnT mod team, that even if ETPro source code would be available, there would be no motivation for the silEnT mod team to add features to it. If we would do anything with it, we would just look for things we could use to improve our mod.
I think I now know why it didn't work. You had this in your campaigncycle.cfg
set d_initial "set g_gametype 4 ; oasis ; set nextcampaign vstr d2"
While it indeed needs to have the map command to start the game.
set d_initial "set g_gametype 4 ; map oasis ; set nextcampaign vstr d2"
Like in the original campaigncycle.cfg.
We didn't change anything that could cause lags. Most probably it's related to the network, not the mod itself. We've been playing on our server on 0.8.1 for a long time now and we haven't noticed any change in that regard.
Will check what's wrong over the weekend.. or tonight cos it's not 5 mins work. At least not for me cos it been ages i made sound pack even for my clan. So I will get u going over the weekend. (No Promises cos real life comes first)
PS: Dedicated server for Perl is over kill. SSD KVM VPS works instead of that Just a suggestion.
This is a scripting error and I need to check where it's failing. First and foremost merge your 2 pk3's to one. With 2 different ones it's hard to debug what's wrong.
You are using DRi sound pack.. or that's what i noticed from your files...I will need to fire up my test server to see what's wrong with your pk3..
You don't need to send me any $$. We are here to help anyone as far as we can. Sure you can donate to MyGamingTalk.com. Donation option is right on corner of the forums.
That way you can check if sound is working or not. You will need to give path of the sound which you would like to test.
If you can play the sound through rcon then .wav file is fine and it's scripting error. I will help you out in the evening once i reach home. Drop me a PM with RCON password and server IP and I will see what I can do.
heh, you just assume Petty arguments aside, I can share it here for you or anyone else who wants to do custom sounds this way. The advantage of this is that you can restrict certain sounds by shrubbot level. We use this as a small benefit for regulars, vip regulars and members.
In full disclosure, another member of IoW wrote these scripts, so I can't really help you if things aren't working or this is poorly written or wrong or causes your server to crash. Use at your own risk! All I know is, it works...
First you need formatting.lua. I think it was supposed to be a general purpose utility script that is shared by other scripts.
function makeDisplayString(text, color, length, alignment)
-- Initialize display string
local displayString
-- Get the display length of the text
local textDisplayLength = displayLength(text)
-- If the text display length fits in the desired display length
if textDisplayLength <= length then
-- Create enough padding to make the text the correct length for display
local padding = ""
for i = 1, length - textDisplayLength do
padding = padding .. ' '
end
-- If alignment is set to centered
if alignment == "center" and string.len(padding) >= 2 then
-- Find the middle of the padding and put each half on one side of the string
local paddingSplitPoint = math.floor(string.len(padding) / 2)
displayString = string.sub(padding, 1, paddingSplitPoint) .. text .. string.sub(padding, paddingSplitPoint + 1)
-- Otherwise, if alignment was set to right
elseif alignment == "right" then
-- Put the padding at the beginning of the string
displayString = padding .. text
else
-- Otherwise add the padding to the end of the string (left aligned)
displayString = text .. padding
end
-- If the text is too big to fit in the desired display length
else
-- If the display length was specified as a very low number (so can't display the text properly)
if length <= 3 then
-- Fill the display length with dots
displayString = ""
for i = 1, length do
displayString = displayString .. '.'
end
-- Otherwise, the display length has enough space to show part of the text
else
-- Create a table to hold parts of the text (chunks beginning with a color code [if possible])
local textTable = {}
-- Split up the text into color coded pieces until there is no more text
local moreText = true
while moreText do
-- Try to find the first occurence of a color code
local firstColorCodeLocation = string.find(text, "%^[^%^]")
-- Initialize text part
local textPart
-- If there are no color codes in the text
if not firstColorCodeLocation then
-- Set the text part to the entire text and specify that there is no more text to add
textPart = text
moreText = false
-- Otherwise, a color code was found
else
-- If the first color code is not at the beginning of the text
if firstColorCodeLocation > 1 then
-- Set the text part to the text leading up to the first color code
textPart = string.sub(text, 1, firstColorCodeLocation - 1)
-- Otherwise, the first color code is at the beginning of the text
else
-- Attempt to find the second color code
local secondColorCodeLocation = string.find(text, "%^[^%^]", firstColorCodeLocation + 2)
-- If the second color code is found
if secondColorCodeLocation then
-- Set the text part to be the text leading up to the second color code (including the first one)
textPart = string.sub(text, 1, secondColorCodeLocation - 1)
else
-- Otherwise, set the text part to the entire remaining text and specify that there is no more text to add
textPart = text
moreText = false
end
end
-- After determining a text part for the table remove that part from the text
text = string.sub(text, string.len(textPart) + 1)
end
-- Add the text part to the table
table.insert(textTable, textPart)
end
-- Set the amount of text needed to fill the desired display length (not including the ellipses)
local displayTextNeeded = length - 3
-- Initialize the display string that will hold the display text
displayString = ""
-- While more text is needed
while displayTextNeeded > 0 do
-- Get the next text part from the table and remove the table entry for it
local nextTextPart = textTable[1]
table.remove(textTable, 1)
-- If the text part begins with a color code
if string.find(nextTextPart, "%^[^%^]") then
-- Get the amount of text needed from the text part (or as much as possible) and update the text needed
nextTextPart = string.sub(nextTextPart, 1, displayTextNeeded + 2)
displayTextNeeded = displayTextNeeded - (string.len(nextTextPart) - 2)
-- Otherwise, there is no color code in the text part
else
-- Get the amount of text needed from the text part (or as much as possible) and update the text needed
nextTextPart = string.sub(nextTextPart, 1, displayTextNeeded)
displayTextNeeded = displayTextNeeded - string.len(nextTextPart)
end
-- Add the text part to the display string
displayString = displayString .. nextTextPart
end
-- Now that no more text is needed, add ellipses to show that it didn't fit
displayString = displayString .. colorString("...", color)
end
end
displayString = colorString(displayString, color)
-- return the formatted string
return displayString
end
function colorString(text, color)
if color then
-- If text does not begin with a color code
if string.find(text, "%^[^%^]") ~= 1 then
-- Add the color code to the beginning of the text
text = '^' .. color .. text
end
end
-- Return text with color code
return text
end
function displayLength(text)
-- Initialize the display length to the full length of the text
local textDisplayLength = string.len(text)
-- Loop through each color code
for colorCode in string.gmatch(text, "%^[^%^]") do
-- Subtract the color code characters from the display length
textDisplayLength = textDisplayLength - string.len(colorCode)
end
return textDisplayLength
end
function makeLine(character, length)
-- Initialize the line string
local line = ""
-- Add characters until the string is as long as specified
for i = 1, length do
line = line .. character
end
-- Return the print line
return line
end
function trim(s, side)
-- Initialize the number of spaces removed to 0
local i = 0
-- If the right side was not specified
if side ~= 'r' then
-- While there are spaces at the beginning of the string
while string.find(s, "^%s") do
-- Remove the first space and increment counter
s = string.gsub(s, "^%s", "")
i = i + 1
end
end
-- If the left side was not specified
if side ~= 'l' then
-- While there are spaces at the end of the string
while string.find(s, "%s$") do
-- Remove the last space and increment counter
s = string.gsub(s, "%s$", "")
i = i + 1
end
end
-- Return the trimmed string and the amount of spaces removed
return s, i
end
function printETLine(clientNum, text)
-- Print the specified text into the specified client's console
if clientNum ~= "[i]" then
et.trap_SendServerCommand(clientNum, 'print "' .. text .. '\n"')
else
et.G_Print( text )
end
end
function printMessage(clientNum, text, messageType)
-- Print the specified text into the specified client's console
if clientNum ~= "[i]" then
et.trap_SendServerCommand(clientNum, messageType .. ' "' .. text .. '"')
else
et.G_Print( text )
end
end
Then playsound.lua contains the command implementation
require("formatting")
-- Initialize a table to hold all possible sounds
soundTable = {}
-- Initialize a table to hold all players playsound cvar values
playsoundCvarTable = {}
function et_InitGame(levelTime, randomSeed, restart)
-- Read sounds into soundTable
local configFile, length = et.trap_FS_FOpenFile("playsound.cfg", et.FS_READ)
-- If there were no errors opening the file
if length ~= -1 then
-- Read data from config file and close it
local soundData = et.trap_FS_Read(configFile, length)
et.trap_FS_FCloseFile(configFile)
-- For each sound block in config file
for soundBlock in string.gmatch(soundData, "[%w%-_]+[%s\n\r]+%b{}") do
-- Get the sound command name
local sound = string.match(soundBlock, "[%w%-_]+")
-- Initialize parameter table for the sound command
local soundParameterTable = {}
-- Get level required from the sound block
soundParameterTable["level"] = tonumber(string.sub(string.match(soundBlock, "level:[%d_]+"), 7))
-- Get a list of sound filenames from the sound block
local soundFilenameList = {}
for soundFilenameLine in string.gmatch(soundBlock, "sound:[%w%-_]+.wav") do
local soundFilename = string.sub(soundFilenameLine, 7)
table.insert(soundFilenameList, soundFilename)
end
soundParameterTable["sounds"] = soundFilenameList
-- Add the sound parameters to the sound table
soundTable[string.lower(sound)] = soundParameterTable
end
end
end
function et_CvarValue(clientNum, cvar, value)
-- Add the cvar value to the script cvar table
playsoundCvarTable[clientNum][cvar] = value
end
function et_ClientConnect(clientNum, firstTime, isBot)
-- Querry server to get cvar value
et.G_QueryClientCvar(clientNum, "playsound_method")
-- Initialize the playsound_method cvar to nil since we do not know the value yet
local clientCvarValueTable = {}
-- Add client to the cvar table
playsoundCvarTable[clientNum] = clientCvarValueTable
-- Return nil to indicate that the player was not rejected by this function
return nil
end
function et_ClientDisconnect(clientNum)
-- Remove the player from the playsound cvar table
playsoundCvarTable[clientNum] = nil
end
function et_ConsoleCommand(command)
-- If client executed play command from console
if string.lower(et.trap_Argv(0)) == "play" then
-- If there were at least 3 parameters (including command name)
if et.trap_Argc() >= 3 then
-- Get client's admin level
local clientNum=0
local clientLevel=0
if et.trap_Argv(1) == "[i]" then
-- When CONSOLE executes this command, there is no clientNum. So we force the value to 50
-- Avoids a server crash, which is always good
clientLevel = 50
else
clientNum = et.trap_Argv(1)
clientLevel = et.G_shrubbot_level(clientNum)
end
-- Get sound client passed as a parameter
local sound = et.trap_Argv(2)
-- Get the parameter table for the requested sound
local soundParameterTable = soundTable[string.lower(sound)]
-- If the sound exists
if soundParameterTable then
-- Get the level required to play the sound
local level = soundParameterTable["level"]
-- If the client has high enough level
if clientLevel >= level then
-- Choose a random sound from the parameters
local soundFilename = soundParameterTable["sounds"][math.random(# soundParameterTable["sounds"])]
-- -- Play the sound
-- local soundPath = "sound/playsound/" .. soundFilename
-- -- et.trap_SendConsoleCommand(et.EXEC_NOW, soundCommand)
-- et.G_globalSound(soundPath)
-- Loop through the clients and play sound based on their cvar playsound_method
for slot, clientCvarValueTable in pairs(playsoundCvarTable) do
local playsoundMethod = clientCvarValueTable["playsound_method"] or "sound"
if playsoundMethod == "sound" then
-- Play the sound for the client
local soundPath = "sound/playsound/" .. soundFilename
local soundIndex = et.G_SoundIndex(soundPath)
et.G_ClientSound(slot, soundIndex)
end
if playsoundMethod == "text" then
local soundText = soundParameterTable["text"]
-- Send message to the client showing the text version of the sound command
printETLine(slot, soundText)
printETLine(slot, "test")
end
end
else
-- Otherwise warn client that they do not have high enough level
printETLine(clientNum, "^oplay: ^7Permission denied")
end
else
-- Otherwise inform client that the sound doesn't exist
printETLine(clientNum, "^oplay: ^7The sound you specified does not exist")
end
else
-- Otherwise inform client that they need to specify a sound name
printETLine(clientNum, "^oplay: ^7You must specify a sound name")
end
-- Return 1 to indicate that the command was handled by this function
return 1
end
if string.lower(et.trap_Argv(0)) == "listsounds" then
-- Initialize display variables
local columnSeparator = " "
local lineCharacter = '-'
local borderColor = '9'
local textColor = 'f'
local columnWidth = 12
local numberColumns = 6
-- Get client's admin level
local clientNum=0
local clientLevel=0
if et.trap_Argv(1) == "[i]" then
-- When CONSOLE executes this command, there is no clientNum. So we force the value to 50
-- Avoids a server crash, which is always good
clientLevel = 50
else
clientNum = et.trap_Argv(1)
clientLevel = et.G_shrubbot_level(clientNum)
end
-- Create a table to hold sounds available to the client
local playerSoundTable = {}
-- For each sound in the sound table
for sound, parameterTable in pairs(soundTable) do
-- If the client has high enough level
if clientLevel >= parameterTable['level'] then
-- Add sound to player sound table
table.insert(playerSoundTable, sound)
end
end
-- Sort player sound table in alphebetical order
table.sort(playerSoundTable)
-- Get number of characters that would be removed from the trimmed separator
local trimmedSeparator, charactersRemoved = trim(columnSeparator)
-- Determine line length based on number of columns, column width, and the separator display length
local lineLength = (columnWidth * numberColumns) + (displayLength(columnSeparator) * (numberColumns + 1)) - charactersRemoved
-- Print a line to act as the top border of the chart
-- printETLine(clientNum, colorString(makeLine(lineCharacter, lineLength), borderColor))
-- While there are sounds in the player sound table
while # playerSoundTable > 0 do
-- Initialize line holding sound names
local soundsLine = colorString(trim(columnSeparator, 'l'), borderColor)
-- For each column
for i = 1, numberColumns do
-- Add the sound from the beginning of the list
soundsLine = soundsLine .. makeDisplayString(playerSoundTable[1] or '', textColor, columnWidth, "left")
-- If this is not the last column
if i < numberColumns then
-- Add a separator (column border)
soundsLine = soundsLine .. colorString(columnSeparator, borderColor)
else
-- Otherwise add a separator with the right side trimmed
soundsLine = soundsLine .. colorString(trim(columnSeparator, 'r'), borderColor)
end
-- Remove first sound from the beginning of the table
table.remove(playerSoundTable, 1)
end
-- Print the sound line followed by a border line
printETLine(clientNum, soundsLine)
-- printETLine(clientNum, colorString(makeLine(lineCharacter, lineLength), borderColor))
end
-- Return 1 to indicate that the command was handled by this function
return 1
end
-- Return 0 to pass any command for standard et processing
return 0
end
There is some stuff in here about having clients opt out of the sounds, but I don't think it was ever finished nor does it work AFAIK. But take them as-is if you like.
Next, the format of the playsound.cfg file is this:
wewin
{
level:1
sound:the_game.wav
}
...
So you've got the command (as in !play wewin), the minimum shrubbot level required to use the sound (note all higher levels can use it), then the sound file name itself. The sound file must be in 'sound/playsound/' in your pk3 file, or else you can change the path coded in the playsound.lua file. But this way, you can just edit playsound.cfg to add your sounds, the command string and level required to run it. No end to the amount of sounds you can have.
Next, define the commands in your shrubbot.cfg file:
[command]
command = ^bplay
exec = play [i] [1]
desc = Play a sound
syntax =
levels = 0 1 2 3 4 5
[command]
command = ^blistsounds
exec = listsounds [i]
desc = List all sounds
syntax =
levels = 0 1 2 3 4 5
Finally, be sure to include the LUA scripts in your et config files:
set lua_modules "playsound.lua"
@beck if you download our pk3 file either from our silent server (abcsilent.abcclan.org) or from here and have a look inside it you will see how it is done. Else pm me.
@Larrywall Yes it is possible have a look inside our pk3 file to see.
Briefly you need to edit wm_quickmessageAlt.menu
If you look through this above you should see where the edits are.
Then you need to edit the wm_allies_chat.voice and the wm_axis_chat.voice
This above was added in at the end of the existing file.
More info. If you look at this line
QM_MENU_ITEM( "1. ^7Monty Python", exec "VoiceChat Monty"; close wm_ABC_Sounds, "1", 1 ) [name shown in menu], exec"VoiceChat [name of voicechat]
So when this is selected off quick chat it will play from wm_allies_chat.voice
So different people will hear a different message.
What he means is we have stuff like: !play goodgame or !play welose or !play fu or other stuff like that. So one custom command that accepts a parameter that determines the sound that is played.
Our !play command is like this:
[command]
command = ^bplay
exec = play [i] [1]
desc = Play a sound
syntax =
levels = 0 1 2 3 4 5
But it does use a custom LUA script that configures what sounds are available and at what shrubbot level. We did it because there is (was?) a limit of 63 custom commands and we wanted WAY more. I suppose you could do what fanboi has with one change:
[command]
command = ^bplay
exec = playsound sound/misc/[1].wav
desc = Play a sound
syntax =
levels = 0 1 2 3 4 5
that might work - but then people would have to know what sounds you have in your custom pak.
EDIT: Oh, and because we manage this through LUA and config files, we also have a !listsounds command that displays the sounds available for each shrubbot level.