I'm adding support for wire-mod cvars with ULX Admin Menu. Simple (or so I thought, lol) tweaks to cl_menu.lua
Thing is, I have been staring at the code for a little while, and I KNOW that I have made just a simple mistake somewhere. So simple that I can't even see it. With your fresh eyes and knowledge of ULX, hope you guys can help me.
The error code I'm getting is
LC: ulx/cl_menu.lua:445: bad argument #1 to 'ipairs' (table expected, got nil)
Line 445 looks like this:-
for _, key in ipairs( ulx.wiresmenu_values ) do
And here is the chunk of code it is in (aping the AdminMenu style).
--------------
--Wires Menu--
--------------
local function rcvValues( um, updateFn )
local values = {}
for _, key in ipairs( ulx.wiresmenu_values ) do
values[ key ] = um:ReadShort()
end
updateFn( values )
end
-- No hook! We'll hook this later so we can tell it what to call for update.
local wiresRes = [["wires"
{
"window"
{
"ControlName" "Frame"
"fieldName" "window"
"xpos" "-200"
"ypos" "100"
"zpos" "290"
"wide" "1000"
"tall" "600"
"autoResize" "0"
"pinCorner" "0"
"visible" "1"
"enabled" "1"
"tabPosition" "0"
"settitlebarvisible" "1"
"title" "ULX Wires Menu"
"sizable" "0"
}
"divider"
{
"ControlName" "Divider"
"fieldName" "divider"
"xpos" "180"
"ypos" "20"
"wide" "2"
"tall" "460"
"autoResize" "0"
"pinCorner" "0"
"visible" "1"
"enabled" "1"
"tabPosition" "0"
}
"applylimits"
{
"ControlName" "Button"
"fieldName" "applylimits"
"xpos" "385"
"ypos" "430"
"zpos" "290"
"wide" "100"
"tall" "40"
"autoResize" "0"
"pinCorner" "0"
"visible" "1"
"enabled" "1"
"tabPosition" "0"
"labelText" "Apply"
"textAlignment" "center"
"dulltext" "0"
"brighttext" "0"
"font" "Default"
"wrap" "0"
"Command" "apply"
"Default" "0"
}
]]
local buttons = {
{ var="sbox_allownpcs", off="Allow NPCs", on="Disallow NPCs" },
{ var="sbox_godmode", off="Enable Global Godmode", on="Disable Global Godmode" },
{ var="sbox_plpldamage", off="Disable PvP Damage", on="Enable PvP Damage" },
{ var="sbox_noclip", off="Enable Noclip", on="Disable Noclip" },
}
for mul, info in ipairs( buttons ) do
wiresRes = wiresRes .. [[
"]] .. info.var .. [["
{
"ControlName" "Button"
"fieldName" "]] .. info.var .. [["
"xpos" "20"
"ypos" "]] .. 50 + (mul-1)*30 .. [["
"zpos" "290"
"wide" "150"
"tall" "24"
"autoResize" "0"
"pinCorner" "0"
"visible" "1"
"enabled" "1"
"tabPosition" "0"
"labelText" ""
"textAlignment" "center"
"dulltext" "0"
"brighttext" "0"
"font" "Default"
"wrap" "0"
"Command" "]] .. info.var .. [["
"Default" "0"
}
]]
end
local limits = {
{ name="wire_wheels", max=32 },
{ name="wire_waypoints", max=32 },
{ name="wire_values", max=32 },
{ name="wire_twoway_radioes", max=32 },
{ name="wire_turret", max=32 },
{ name="wire_thrusters", max=32 },
{ name="wire_target_finders", max=32 },
{ name="wire_speedometers", max=32 },
{ name="wire_emitters", max=32 },
{ name="wire_simple_explosive", max=32 },
{ name="wire_sensors", max=32 },
{ name="wire_screens", max=32 },
{ name="wire_relays", max=32 },
{ name="wire_rangers", max=32 },
{ name="wire_radioes", max=32 },
{ name="wire_sockets", max=32 },
{ name="wire_plugs", max=32 },
{ name="wire_pixels", max=32 },
{ name="wire_panels", max=32 },
{ name="wire_outputs", max=32 },
{ name="wire_oscilloscopes", max=32 },
{ name="wire_locators", max=32 },
{ name="wire_lights", max=32 },
{ name="wire_inputs", max=32 },
{ name="wire_indicators", max=32 },
{ name="wire_hoverballs", max=32 },
{ name="wire_gyroscopes", max=32 },
{ name="wire_gpss", max=32 },
{ name="wire_gate_trigs", max=32 },
{ name="wire_gate_times", max=32 },
{ name="wire_gate_selections", max=32 },
{ name="wire_gate_memorys", max=32 },
{ name="wire_gate_logics", max=32 },
{ name="wire_gate_comparisons", max=32 },
{ name="wire_gates", max=32 },
{ name="wire_explosive", max=32 },
{ name="wire_dual_inputs", max=32 },
{ name="wire_detonators", max=32 },
{ name="wire_buttons", max=32 },
{ name="wire_adv_inputs", max=32 },
}
for mul, info in ipairs( limits ) do
local name = info.name
local mulx = math.floor( (mul-1) / 14 ) -- Make rows of 14
local muly = math.fmod( mul-1, 14 )
wiresRes = wiresRes .. [[
"]] .. name .. [[lbl"
{
"ControlName" "Label"
"fieldName" "]] .. name .. [[lbl"
"xpos" "]] .. 10 + mulx*250 .. [["
"ypos" "]] .. muly*50 + 20 .. [["
"wide" "128"
"tall" "24"
"autoResize" "0"
"pinCorner" "0"
"visible" "1"
"enabled" "1"
"tabPosition" "0"
"labelText" "Max ]] .. string.upper( name:sub( 1, 1 ) ) .. name:sub( 2 ) .. [[:"
"textAlignment" "west"
"dulltext" "0"
"brighttext" "0"
"wrap" "0"
}
"]] .. name .. [[slider"
{
"ControlName" "Slider"
"fieldName" "]] .. name .. [[slider"
"xpos" "]] .. 10 + mulx*250 .. [["
"ypos" "]] .. muly*50 + 40 .. [["
"wide" "200"
"tall" "20"
"autoResize" "0"
"pinCorner" "0"
"visible" "1"
"enabled" "1"
"tabPosition" "0"
}
"]] .. name .. [[num"
{
"ControlName" "Label"
"fieldName" "]] .. name .. [[num"
"xpos" "]] .. 210 + mulx*250 .. [["
"ypos" "]] .. muly*50 + 40 .. [["
"wide" "64"
"tall" "24"
"autoResize" "0"
"pinCorner" "0"
"visible" "1"
"enabled" "1"
"tabPosition" "0"
"labelText" ""
"textAlignment" "west"
"dulltext" "0"
"brighttext" "0"
"wrap" "0"
}
]]
end
wiresRes = wiresRes .. "}"
local wiresMenu
function ulx.showwiresMenu()
if GetConVarString( "sv_gamemode" ) ~= "sandbox" then
ULib.csay( LocalPlayer(), "Sorry, this menu is only available in sandbox mode." )
return
end
-- We COULD use this line if we weren't taking such a hackish approach with the checkboxes.
-- if wiresMenu then wiresMenu:SetVisible( true ) return end
if wiresMenu then wiresMenu:SetVisible( false ) end
wiresMenu = vgui.Create( "Frame" )
wiresMenu:SetName( "window" )
local btns = {}
local function button_route( panel, action, cvar )
local value = math.fmod( btns[ cvar ].value + 1, 2 )
ULib.redirect( LocalPlayer(), "ulx", _, string.format( "rcon %s %i\n", cvar, value ) ) -- Garry broke our best way to do this.
btns[ cvar ].value = value
local info
for _, data in ipairs( buttons ) do
if data.var == cvar then
info = data
break
end
end
if value == 1 then
btns[ cvar ].panel:SetText( info.on )
else
btns[ cvar ].panel:SetText( info.off )
end
end
for _, info in ipairs( buttons ) do
local button = vgui.Create( "Button", wiresMenu, info.var )
button:SetText( info.off )
button:SetActionFunction( button_route )
btns[ info.var ] = { panel=button, value=0 }
end
local sliders = {}
for _, info in ipairs( limits ) do
local name = info.name
local cvar = "sbox_max" .. name
local max = info.max
local num = vgui.Create( "Label", wiresMenu, name .. "num" )
num:SetText( "0" )
local slider = vgui.Create( "Slider", wiresMenu, name .. "slider" )
slider:PostMessage( "SetInteger", "b", "1" )
slider:PostMessage( "SetLower", "f", "0" )
slider:PostMessage( "SetHigher", "f", max )
slider:SetActionFunction( function ( panel, action, value )
sliders[ cvar ].new = value
num:SetText( tostring( value ) )
end )
sliders[ cvar ] = { panel=slider, num=num, value=0, new=0 } -- So we can reference it in our update
end
local button = vgui.Create( "Button", wiresMenu, "applylimits" )
button:SetActionFunction( function ()
for cvar, _ in pairs( sliders ) do
local value = sliders[ cvar ].new
if value ~= sliders[ cvar ].value then
ULib.redirect( LocalPlayer(), "ulx", _, string.format( "rcon %s %i\n", cvar, value ) ) -- Garry broke our best way to do this.
sliders[ cvar ].num:SetText( value )
sliders[ cvar ].value = value
end
end
end )
wiresMenu:LoadControlsFromString( wiresRes )
wiresMenu:SetKeyBoardInputEnabled( true )
wiresMenu:SetMouseInputEnabled( true )
wiresMenu:SetPos( ScrW()*0.3, ScrH()-500 )
wiresMenu:SetVisible( true )
-- Update function...
local function update( values )
for cvar, value in pairs( values ) do
if sliders[ cvar ] then -- This is a cvar
local slider = sliders[ cvar ]
slider.value = value
slider.panel:PostMessage( "SetValue", "f", value )
slider.num:SetText( value )
else
local info
for _, data in ipairs( buttons ) do
if data.var == cvar then
info = data
break
end
end
if value ~= 0 then
local btn = btns[ cvar ]
btn.panel:SetText( info.on )
btn.value = 1
else
local btn = btns[ cvar ]
btn.panel:SetText( info.off )
btn.value = 0
end
end
end
end
usermessage.Hook( "ulx_menuvalues", rcvValues, update ) -- The hook will get our function and call it.
LocalPlayer():ConCommand( "ulx_valueupdate\n" )
end