mirror of
https://github.com/fortressforever/fortressforever-scripts.git
synced 2024-11-22 20:51:28 +00:00
457 lines
17 KiB
Lua
457 lines
17 KiB
Lua
--[[
|
|
================================================================================================================
|
|
== base_chatcommands.lua
|
|
== -- Allows maps to use player chat as commands to perform
|
|
== -- various functions
|
|
================================================================================================================
|
|
== Instructions
|
|
== -- To add commands:
|
|
=~~ Code: ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~=
|
|
chatbase_addcommand( "commandname", "Command description", "command example" )
|
|
function chat_commandname( player, parameter1, parameter2, ... )
|
|
-- perform some task
|
|
end
|
|
=~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~=
|
|
== -- The description and example parameters are both optional
|
|
== -- Do NOT put the command prefix in either the example or the commandname parameters
|
|
== -- The player parameter will always get sent to chat_commandname functions, but the others are optional
|
|
== -- Parameters are sent by players in this format !commandname param1 param2 ...
|
|
== --
|
|
== -- To add player settings:
|
|
=~~ Code: ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~=
|
|
chatbase_addplayersetting( "settingname", default_value, "Setting description" )
|
|
=~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~=
|
|
== -- The description is optional
|
|
== --
|
|
== -- To get a setting value for a player:
|
|
=~~ Code: ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~=
|
|
chatbase_getplayersetting( player, "settingname" )
|
|
=~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~=
|
|
== --
|
|
== -- To set a setting value for a player:
|
|
=~~ Code: ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~=
|
|
chatbase_setplayersetting( player, "settingname", value )
|
|
=~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~=
|
|
== --
|
|
== -- Settings:
|
|
== -- -- The settings below should be copied, pasted, and altered into your maps .lua if you want to
|
|
== -- -- change any of them
|
|
================================================================================================================
|
|
]]--
|
|
|
|
-- chat command settings
|
|
CHAT_COMMAND_PREFIX = "!" -- Command prefix, all commands must start with this string
|
|
CHAT_COMMAND_HIDECHATSTRING = true -- Determines if the chat string is shown if it executes a command
|
|
CHAT_COMMAND_DISABLE_PERIODIC_NOTIFY = false -- If false, the server will notify players that chat commands
|
|
-- are enabled for the map ONLY IF non-default chat commands exist
|
|
CHAT_COMMAND_PERIODIC_NOTIFY_REPEAT = 0 -- Number of times to repeat the notification (set to -1 for infinite)
|
|
CHAT_COMMAND_PERIODIC_NOTIFY_PERIOD = 60 -- Time between notifications (in seconds)
|
|
|
|
-- theme settings
|
|
-- 0 = orange 1 = blue 2 = red 3 = yellow 4 = green
|
|
-- 5 = white 6 = black 7 = gray 8 = purple 9 = teal
|
|
CHAT_COMMAND_COLOR_MAIN = 0 -- used most often
|
|
CHAT_COMMAND_COLOR_HIGHLIGHT1 = 5 -- used to emphasize something
|
|
CHAT_COMMAND_COLOR_HIGHLIGHT2 = 5 -- used to emphasize something
|
|
CHAT_COMMAND_COLOR_HIGHLIGHT3 = 5 -- used to emphasize something
|
|
CHAT_COMMAND_COLOR_ERROR = 2 -- used for error messages
|
|
|
|
-- chat command debug settings
|
|
CHAT_COMMAND_DEBUG = false
|
|
CHAT_COMMAND_DEBUG_PREFIX = "[lua-chatcommands] "
|
|
|
|
--[[
|
|
=====================================
|
|
== GLOBAL VARS
|
|
=====================================
|
|
== Do NOT edit these unless you know
|
|
== exactly what you're doing
|
|
=====================================
|
|
]]--
|
|
|
|
-- chat commands global table
|
|
chatbase_commands = {}
|
|
chatbase_players = {}
|
|
chatbase_settings = {}
|
|
|
|
chatbase_defaultcommands = {"help","disablenotify"}
|
|
|
|
--[[
|
|
=====================================
|
|
== CHAT COMMAND FUNCTIONS
|
|
=====================================
|
|
==
|
|
=====================================
|
|
]]--
|
|
|
|
-------------------------------------
|
|
-- Setup
|
|
-------------------------------------
|
|
|
|
function chatbase_addcommand( command, description, example )
|
|
chatbase_debug( "Adding command "..tostring(command).." with desc "..tostring(description).." and example "..tostring(example) )
|
|
chatbase_commands[command] = {}
|
|
chatbase_commands[command].description = description
|
|
chatbase_commands[command].example = example
|
|
end
|
|
|
|
function chatbase_addplayersetting( setting, default, description )
|
|
chatbase_debug( "Adding setting "..tostring(setting).." with default "..tostring(default).." and desc "..tostring(description) )
|
|
chatbase_settings[setting] = {}
|
|
chatbase_settings[setting].default = default
|
|
chatbase_settings[setting].description = description
|
|
end
|
|
|
|
-------------------------------------
|
|
-- Utilities
|
|
-------------------------------------
|
|
|
|
function chatbase_customcommandsexist()
|
|
-- check that non-default commands exist
|
|
chatbase_debug("Checking if custom commands exist")
|
|
local nondefexist = false
|
|
for command,values in pairs(chatbase_commands) do
|
|
local found = false
|
|
chatbase_debug("Checking command "..tostring(command))
|
|
for i,defcommand in pairs(chatbase_defaultcommands) do
|
|
chatbase_debug(" -> Against default command "..tostring(defcommand))
|
|
if defcommand == command then
|
|
chatbase_debug("Command "..tostring(command).." is default")
|
|
found = true
|
|
end
|
|
end
|
|
if not found then
|
|
chatbase_debug("Command "..tostring(command).." is not default")
|
|
nondefexist = true
|
|
break;
|
|
end
|
|
end
|
|
|
|
chatbase_debug("Custom commands exist: "..tostring(nondefexist))
|
|
return nondefexist;
|
|
end
|
|
|
|
-------------------------------------
|
|
-- Notifications
|
|
-------------------------------------
|
|
|
|
function chatbase_setupnotify()
|
|
chatbase_debug("setupnotify called")
|
|
-- if notifications are completely disabled, return early
|
|
if CHAT_COMMAND_DISABLE_PERIODIC_NOTIFY then return end
|
|
chatbase_debug("setupnotify got past disabled check")
|
|
|
|
-- if only default commands exist, then theres no reason to notify
|
|
if not chatbase_customcommandsexist() then return end
|
|
chatbase_debug("setupnotify got past custom commands check")
|
|
|
|
-- call a function that will notify anyone that meets the requirements every NOTIFY_PERIOD
|
|
AddScheduleRepeating( "chatbase_notifyenabled", CHAT_COMMAND_PERIODIC_NOTIFY_PERIOD, chatbase_notifyenabled )
|
|
end
|
|
|
|
-- wait 10 seconds to setup notification, just to be safe that all commands are registered
|
|
AddSchedule("chatbase_setupnotify", 10, chatbase_setupnotify)
|
|
|
|
function chatbase_notifyenabled()
|
|
chatbase_debug("notifyenabled called")
|
|
-- if notifications are completely disabled, return early
|
|
if CHAT_COMMAND_DISABLE_PERIODIC_NOTIFY then return end
|
|
chatbase_debug("notifyenabled got past disabled check")
|
|
|
|
-- if only default commands exist, then theres no reason to notify
|
|
if not chatbase_customcommandsexist() then return end
|
|
chatbase_debug("notifyenabled got past custom commands check")
|
|
|
|
-- notify any players that deserve it
|
|
for i,v in pairs(chatbase_players) do
|
|
chatbase_debug("checking player ID "..i)
|
|
local player = CastToPlayer(v.player)
|
|
if IsPlayer(player) then
|
|
chatbase_debug("--> IsPlayer")
|
|
-- only notify if they havent set their setting to disable notifications
|
|
if v.settings["disablenotify"] ~= true then
|
|
chatbase_debug("--> disablenotify not true | REPEAT: "..CHAT_COMMAND_PERIODIC_NOTIFY_REPEAT.." numtimesnotified: "..tostring(v.settings["numtimesnotified"]))
|
|
-- check repeat type
|
|
if CHAT_COMMAND_PERIODIC_NOTIFY_REPEAT == 0 and v.settings["numtimesnotified"] == 0 then
|
|
-- only show once
|
|
v.settings["numtimesnotified"] = v.settings["numtimesnotified"]+1
|
|
chatbase_notifyplayer(player)
|
|
end
|
|
if CHAT_COMMAND_PERIODIC_NOTIFY_REPEAT > 0 and v.settings["numtimesnotified"] <= CHAT_COMMAND_PERIODIC_NOTIFY_REPEAT then
|
|
-- repeat a set number of times
|
|
v.settings["numtimesnotified"] = v.settings["numtimesnotified"]+1
|
|
chatbase_notifyplayer(player)
|
|
end
|
|
if CHAT_COMMAND_PERIODIC_NOTIFY_REPEAT < 0 then
|
|
-- repeat infinitely (var is set to a negative number)
|
|
v.settings["numtimesnotified"] = v.settings["numtimesnotified"]+1
|
|
chatbase_notifyplayer(player)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
function chatbase_notifyplayer(player)
|
|
if not IsPlayer(player) then chatbase_error("function chatbase_notifyplayer: Notifying a nonplayer"); return; end
|
|
ChatToPlayer(player, "^"..CHAT_COMMAND_COLOR_MAIN.."Chat commands are enabled for this map. Type "..CHAT_COMMAND_PREFIX.."help to see what is available")
|
|
end
|
|
|
|
-------------------------------------
|
|
-- Player Table Functions
|
|
-------------------------------------
|
|
|
|
function chatbase_addplayer(player)
|
|
if not IsPlayer(player) then chatbase_error("function chatbase_addplayer: Trying to add a nonplayer"); return; end
|
|
|
|
-- add an entry for the player
|
|
chatbase_players[player:GetId()] = {}
|
|
chatbase_players[player:GetId()].player = player
|
|
chatbase_players[player:GetId()].settings = {}
|
|
for setting,values in pairs(chatbase_settings) do
|
|
chatbase_players[player:GetId()].settings[setting] = values.default
|
|
end
|
|
end
|
|
|
|
function chatbase_removeplayer(player)
|
|
-- param could be a player or a playerid
|
|
if tonumber(player) then player = GetPlayerByID(player) end
|
|
if not IsPlayer(player) then chatbase_error("function chatbase_removeplayer: Trying to remove a nonplayer"); return; end
|
|
|
|
-- clear their entry
|
|
chatbase_players[player:GetId()] = nil
|
|
end
|
|
|
|
-------------------------------------
|
|
-- Player Settings Functions
|
|
-------------------------------------
|
|
|
|
function chatbase_getplayersetting( player, setting )
|
|
-- param could be a player or a playerid
|
|
if tonumber(player) then player = GetPlayerByID(player) end
|
|
if not IsPlayer(player) then chatbase_error("function chatbase_getplayersetting: Trying to get setting of a nonplayer"); return nil; end
|
|
|
|
if chatbase_players[player:GetId()] ~= nil then
|
|
return chatbase_players[player:GetId()].settings[setting]
|
|
else
|
|
chatbase_error("function chatbase_getplayersetting: Player not found in the table");
|
|
return nil
|
|
end
|
|
end
|
|
|
|
function chatbase_setplayersetting( player, setting, value )
|
|
-- param could be a player or a playerid
|
|
if tonumber(player) then player = GetPlayerByID(player) end
|
|
if not IsPlayer(player) then chatbase_error("function chatbase_setplayersetting: Trying to set setting of a nonplayer"); return false; end
|
|
|
|
if chatbase_players[player:GetId()] ~= nil then
|
|
chatbase_players[player:GetId()].settings[setting] = value;
|
|
return true
|
|
else
|
|
chatbase_error("function chatbase_setplayersetting: Player not found in the table");
|
|
return false
|
|
end
|
|
end
|
|
|
|
-------------------------------------
|
|
-- Debug/Messaging
|
|
-------------------------------------
|
|
|
|
function chatbase_error( str )
|
|
ConsoleToAll(CHAT_COMMAND_DEBUG_PREFIX.."[ERROR] "..str)
|
|
end
|
|
|
|
function chatbase_debug( str )
|
|
if CHAT_COMMAND_DEBUG then ConsoleToAll(CHAT_COMMAND_DEBUG_PREFIX..str) end
|
|
end
|
|
|
|
--[[
|
|
=====================================
|
|
== DEFAULT COMMAND IMPLEMENTATION
|
|
=====================================
|
|
==
|
|
=====================================
|
|
]]--
|
|
|
|
chatbase_addcommand( "help", "Display a list of all available commands" )
|
|
function chat_help( player )
|
|
ChatToPlayer( player, "^"..CHAT_COMMAND_COLOR_MAIN.."Chat Commands:")
|
|
for command,values in pairs(chatbase_commands) do
|
|
local command_text = "^"..CHAT_COMMAND_COLOR_HIGHLIGHT1..CHAT_COMMAND_PREFIX..command
|
|
if values.description ~= nil then
|
|
command_text = command_text.. " ^"..CHAT_COMMAND_COLOR_MAIN.."- ".."^"..CHAT_COMMAND_COLOR_HIGHLIGHT2..values.description
|
|
end
|
|
if values.example ~= nil then
|
|
command_text = command_text.. " ^"..CHAT_COMMAND_COLOR_MAIN.."(example: "..CHAT_COMMAND_PREFIX..values.example..")"
|
|
end
|
|
ChatToPlayer( player, command_text )
|
|
end
|
|
end
|
|
|
|
if not CHAT_COMMAND_DISABLE_PERIODIC_NOTIFY then
|
|
|
|
chatbase_addcommand( "disablenotify", "Disables the periodic notification that chat commands are enabled" )
|
|
function chat_disablenotify( player )
|
|
chatbase_setplayersetting( player, "disablenotify", true )
|
|
ChatToPlayer(player, "^"..CHAT_COMMAND_COLOR_MAIN.."Periodic \"chat commands are enabled\" notifications disabled")
|
|
end
|
|
|
|
end
|
|
|
|
--[[
|
|
=====================================
|
|
== DEFAULT SETTING IMPLEMENTATION
|
|
=====================================
|
|
==
|
|
=====================================
|
|
]]--
|
|
|
|
chatbase_addplayersetting( "disablenotify", false, "Disables periodic notifications that chat commands are enabled" )
|
|
chatbase_addplayersetting( "numtimesnotified", 0, "Number of times the player has been notified that chat commands are enabled" )
|
|
|
|
--[[
|
|
=====================================
|
|
== CALLBACKS
|
|
=====================================
|
|
==
|
|
=====================================
|
|
]]--
|
|
|
|
-- player_onchat()
|
|
---- handle chat commands
|
|
|
|
-- save parent player_onchat
|
|
local base_player_onchat = player_onchat
|
|
|
|
function player_onchat( player, chatstring )
|
|
|
|
-- call parent onchat function if it exists
|
|
if base_player_onchat ~= nil then base_player_onchat(player,chatstring) end
|
|
|
|
local player = CastToPlayer( player )
|
|
|
|
-- string.gsub call removes all control characters (newlines, return carriages, etc)
|
|
-- string.sub call removes the playername: part of the string, leaving just the message
|
|
local message = string.sub( string.gsub( chatstring, "%c", "" ), string.len(player:GetName())+3 )
|
|
|
|
chatbase_debug("Message: "..message)
|
|
|
|
local prefix = string.sub(message,1,string.len(CHAT_COMMAND_PREFIX))
|
|
|
|
chatbase_debug("Prefix: "..prefix)
|
|
|
|
-- if the first character of the string doesn't match the prefix, then we don't care about it
|
|
if prefix ~= CHAT_COMMAND_PREFIX then return true; end
|
|
|
|
-- strip the prefix character
|
|
message = string.sub( message, 1+string.len(CHAT_COMMAND_PREFIX) )
|
|
|
|
chatbase_debug("Message: "..message)
|
|
|
|
-- if there is no message at all, return
|
|
if string.match(message, "%a+") == nil then return true end
|
|
|
|
-- get command and parameters
|
|
local command = string.lower( string.match(message, "%a+") )
|
|
local paramstring = string.sub(message, string.len(command)+2)
|
|
local params = explode(" ", paramstring)
|
|
-- loop through all params and convert any numbers to actual numbers
|
|
for i,param in pairs(params) do
|
|
-- tonumber() returns nil if it can't convert to a number
|
|
if tonumber(param) ~= nil then
|
|
param = tonumber(param)
|
|
end
|
|
chatbase_debug(" Param "..i..": "..param)
|
|
end
|
|
-- insert the player as the first param always
|
|
table.insert( params, 1, player )
|
|
|
|
-- find function to call
|
|
local func, finderror = findfunction("chat_"..command)
|
|
|
|
if func ~= nil then
|
|
if CHAT_COMMAND_DEBUG then ConsoleToAll(CHAT_COMMAND_DEBUG_PREFIX.."Function for "..command.." found"); end
|
|
-- translates to chat_<command>( <arg1>, <arg2>, ... ) e.g. chat_help() or chat_set( "varname", 5 )
|
|
func(unpack(params))
|
|
else
|
|
ChatToPlayer(player, "^"..CHAT_COMMAND_COLOR_ERROR.."Unexpected error while executing command")
|
|
chat_error("Command function find error for "..command.."("..paramstring.."):".. finderror)
|
|
return true
|
|
end
|
|
|
|
if CHAT_COMMAND_HIDECHATSTRING then
|
|
return false
|
|
else
|
|
return true
|
|
end
|
|
end
|
|
|
|
-- player_connected()
|
|
---- keep track of players
|
|
|
|
-- save parent player_connected
|
|
local base_player_connected = player_connected
|
|
|
|
function player_connected( player )
|
|
|
|
-- call parent onchat function if it exists
|
|
if base_player_connected ~= nil then base_player_connected(player) end
|
|
|
|
local player = CastToPlayer( player )
|
|
|
|
chatbase_addplayer( player )
|
|
end
|
|
|
|
-- player_disconnected()
|
|
---- keep track of players
|
|
|
|
-- save parent player_disconnected
|
|
local base_player_disconnected = player_disconnected
|
|
|
|
function player_disconnected( player )
|
|
|
|
-- call parent onchat function if it exists
|
|
if base_player_disconnected ~= nil then base_player_disconnected(player) end
|
|
|
|
local player = CastToPlayer( player )
|
|
|
|
chatbase_removeplayer( player )
|
|
end
|
|
|
|
--[[
|
|
=====================================
|
|
== HELPERS
|
|
=====================================
|
|
==
|
|
=====================================
|
|
]]--
|
|
|
|
-- Find a function with the given string name in the global table
|
|
function findfunction(x)
|
|
assert(type(x) == "string")
|
|
local f=_G
|
|
for v in x:gmatch("[^%.]+") do
|
|
if type(f) ~= "table" then
|
|
return nil, "looking for '"..v.."' expected table, not "..type(f)
|
|
end
|
|
f=f[v]
|
|
end
|
|
if type(f) == "function" then
|
|
return f
|
|
else
|
|
return nil, "expected function, not "..type(f)
|
|
end
|
|
end
|
|
|
|
-- Explode a string by the given divider
|
|
function explode(div,str)
|
|
if (div=='') then return false end
|
|
local pos,arr = 0,{}
|
|
-- for each divider found
|
|
for st,sp in function() return string.find(str,div,pos,true) end do
|
|
table.insert(arr,string.sub(str,pos,st-1)) -- Attach chars left of current divider
|
|
pos = sp + 1 -- Jump past current divider
|
|
end
|
|
table.insert(arr,string.sub(str,pos)) -- Attach chars right of last divider
|
|
return arr
|
|
end
|