• Print

Author Topic: ULX XGUI commands: Dynamic drop down?  (Read 9338 times)

0 Members and 1 Guest are viewing this topic.

Offline lynx

  • Jr. Member
  • **
  • Posts: 59
  • Karma: 15
ULX XGUI commands: Dynamic drop down?
« on: February 25, 2014, 01:55:27 am »
I know that's probably not the most descriptive of titles, but I can't think of a better way to explain it.

I'm currently coding a ULX Pointshop administration system (to give, take, set points) and would like to also set up a way to take items the player has.

Basic code structure for this would be like this:

Code: [Select]
function ulx.pointshop_takeitem( calling_ply, target_plys, item )

if !PS then
ULib.tsayError( calling_ply, "Pointshop is not loaded. Cannot set points.", true )
return
end

if !PS.Items[item] then
ULib.tsayError( calling_ply, "Cannot take item. Item \""..item.."\" invalid.", true )
return
end

for k,v in pairs( target_plys ) do
if v:PS_HasItem(item) then
v:PS_TakeItem(item)
else
table.remove(target_plys,k)
ULib.tsayError( calling_ply, v:Name().." does not have "..item.."!", true )
end
end

ulx.fancyLogAdmin( calling_ply, "#A took a #s from #T", item, target_plys )

end
local pointshop_takeitem = ulx.command( "Pointshop", "ulx takeitem", ulx.pointshop_giveitem, "!takeitem" )
pointshop_takeitem:addParam{ type=ULib.cmds.PlayersArg }
pointshop_takeitem:addParam{ type=ULib.cmds.StringArg, hint="item", completes=ulx.pointshop_item_list }
pointshop_takeitem:defaultAccess( ULib.ACCESS_SUPERADMIN )
pointshop_takeitem:help( "Takes away the target player(s) access to the specified pointshop item, forcing them to rebuy it." )

Code has checks for pointshop validity, item validity, and checks if the player has it before actually removing it. If the admin knows the item ID, thats all fine and dandy. And ulx.pointshop_item_list gives a sorted list, by category, of the items. But that shows all the items, and in some cases (such as a server with numerous models/hats/etc) that could be a big problem. What's nice about Pointshop is that it stores all item data for a player in a SHARED table linked to the player object. So, you could easily call Player(30).PS_Items to get the table of items, if it's equipped, and the various modifications they have set.

The problem with this is that I don't know how, if at all possible, to have this bit of code query the players data after they have been selected:
Code: [Select]
pointshop_takeitem:addParam{ type=ULib.cmds.StringArg, hint="item", completes=ulx.pointshop_item_list }
The question is now: is there a way to make what I am thinking of possible? I know I could add the commands, and modify the pointshop system to use Player:query("ulx takeitem") to see if they have access and allow them to use the pointshop admin menu, I just want to try to make a fully ULX solution without needing to edit the Pointshop menu or create a new menu that pops up to populate items in a DermaMenu or something.

Offline Megiddo

  • Ulysses Team Member
  • Hero Member
  • *****
  • Posts: 6214
  • Karma: 394
  • Project Lead
Re: ULX XGUI commands: Dynamic drop down?
« Reply #1 on: February 25, 2014, 06:20:37 am »
This is a question for Stickly Man. I'll point him toward this thread.
Experiencing God's grace one day at a time.

Offline Stickly Man!

  • Ulysses Team Member
  • Hero Member
  • *****
  • Posts: 1270
  • Karma: 164
  • What even IS software anymore?
    • XGUI
Re: ULX XGUI commands: Dynamic drop down?
« Reply #2 on: February 26, 2014, 02:16:49 pm »
I don't think there's a way to do a complex autocomplete based on the player argument.. but it's sounding familiar enough to me to defer that subject to Megiddo.

Otherwise, unless I'm mistaken, XGUI relies on the commands' autocomplete table to display available options, obviously. You can modify this table per client at any time by accessing it through a method like this:
Code: Lua
  1. ULib.cmds.translatedCmds["ulx votemap"].args[2].completes = xgui.data.votemaps
(This is what XGUI uses to update the client's autocomplete when the votemaps change.)

The only problem here is hooking into when a player is selected in XGUI. You want to access this via the cmds tab, correct? *digs through code* oh man this code is a mess.. So I think there are two ways to go about this.


Method 1: Hook into XGUI's cmds module
The easiest and probably most hackish way to do it would be to run some code before XGUI builds the ArgsList panel (which gets called when a player or command without a playerarg is selected). You should be able to "override" this function and add your own code to it, something like this:

Code: Lua
  1. --Grab a reference to the XGUI commands module.
  2. --Note: This will most likely be wrong! You should iterate through xgui.modules.tab to find the index where xgui.modules.tab[i].name == "cmds".
  3. local cmdsModule = xgui.modules.tab[0].panel
  4.  
  5.  
  6. local oldFunction = cmdsModule.buildArgsList
  7. cmdsModule.buildArgsList = function( cmd )
  8.     if (cmd.cmd == "ulx takeitem")
  9.         --Set your code that updates the autocomplete table here.
  10.         --You can get a list of the selected players using cmdsModule.plist:GetSelected()
  11.     end
  12.     oldFunction( cmd )
  13. end
  14.  
Note: This is all clientside code, and should not affect other players. I am also building this advice from memory and looking at the code- none of this has been tested and it's been a long time since worked with this portion of XGUI

One other thing to note, changing the autocomplete like this may impact the autocomplete feature of your command in the client's console- so you may want to consider resetting the completes to the full table after calling oldFunction( cmd ).



Method 2: Create your own XGUI module and/or custom menu
This part is probably excessive and is what you wanted to avoid doing, but there are five types of modules for XGUI:
 - Tab modules (like the bans tab)
 - Settings modules (Like the serverside settings or clientside settings tab)
 - Gamemode modules (Sandbox tab, only shows up if playing a sandbox-enabled gamemode)
 - Server Settings modules (ULX general settings, echos, etc-- the small panels on the "Serverside Settings" tab)
 - Client Settings modules (Panels on the Clientside Settings tab)

Unfortunately, the only one that really fits this particular project would be a full Tab module or gamemode module, but that's probably going to be more real estate than you need (unless you have other point-shop related stuff you could put on there). Which leaves my recommendation to a custom menu, but it's not really integrated with XGUI.



I leave the decision on this up to you. Good luck, and let me know if you have more questions! (I'm 90% sure my above code won't work on first try lol)
Join our Team Ulysses community discord! https://discord.gg/gR4Uye6

Offline lynx

  • Jr. Member
  • **
  • Posts: 59
  • Karma: 15
Re: ULX XGUI commands: Dynamic drop down?
« Reply #3 on: February 28, 2014, 03:28:08 am »
I got it to a point where it's tying into the cmds module. The only thing I can't figure out is how to get the player that is being selected from the little amount of data that the cmd table holds.

Here's what I have so far:

Code: [Select]
if CLIENT then
local cmdModule
-- ULX XGUI Autocomplete hack
for i,m in pairs(xgui.modules.tab) do
if m.name == "Cmds" then
print("Loaded cmdModule for RTLK XGUI autocomplete hack")
cmdModule = xgui.modules.tab[i].panel
end
end

local oldFunc = cmdModule.buildArgsList
cmdModule.buildArgsList = function(cmd)
if ( cmd.cmd == "ulx takeitem") then
for k,v in pairs(cmd.args) do
PrintTable(v)
end
PrintTable(cmd)
end
oldFunc(cmd)
end
end

And the output of that is:
Code: [Select]
type:
parseAndValidate = function: 0x28348d88
invisible = true
x_getcontrol = function: 0x2ce723d0
cmd = ulx takeitem
type:
usage = function: 0x231f9e30
parseAndValidate = function: 0x28344ac8
cmd = ulx takeitem
type:
processRestrictions = function: 0x2bdb9bc8
x_getcontrol = function: 0x2ce71f50
complete = function: 0x2bd69398
parseAndValidate = function: 0x2bd62160
usage = function: 0x28314838
cmd = ulx takeitem
hint = item
completes:
1 = - Followers -
... Snipped for size sake ...
68 = supersize
cmd = ulx takeitem
args:
1:
type:
parseAndValidate = function: 0x28348d88
invisible = true
x_getcontrol = function: 0x2ce723d0
cmd = ulx takeitem
2:
type:
usage = function: 0x231f9e30
parseAndValidate = function: 0x28344ac8
cmd = ulx takeitem
3:
type:
processRestrictions = function: 0x2bdb9bc8
x_getcontrol = function: 0x2ce71f50
complete = function: 0x2bd69398
parseAndValidate = function: 0x2bd62160
usage = function: 0x28314838
cmd = ulx takeitem
hint = item
completes:
1 = - Followers -
... Snipped for size sake ...
68 = supersize
category = Pointshop
fn = function: 0x2c294420
say_cmd:
1 = !takeitem
helpStr = Takes away the target player(s) access to the specified pointshop item, forcing them to rebuy it.

It first iterates through the cmd.args table and prints the data, then the full cmd table. Once I figure out how to get the player (either their name, uniqueid, userid, steamid, something) then I can process the autocomplete for them. So, any clue on how to get the player from that data, or somehow else?

Edit:

I actually figured it out. Had to tie into the plist and add a check for OnRowSelected. It now works :D Should have an update pushed to my plugin in releases soon (aka: this update.)
« Last Edit: February 28, 2014, 05:02:18 am by lynx »

Offline Stickly Man!

  • Ulysses Team Member
  • Hero Member
  • *****
  • Posts: 1270
  • Karma: 164
  • What even IS software anymore?
    • XGUI
Re: ULX XGUI commands: Dynamic drop down?
« Reply #4 on: March 03, 2014, 11:02:43 am »
Glad you got it working! ;D  Your code looks good- I thought I had stored a reference to the player object in a third hidden column on the playerlist, but apparently I didn't:
Code: Lua
  1. local line = cmds.plist:AddLine( ply:Nick(), ply:GetUserGroup() )
Perhaps I'll add it in the future. :P It does store the Nick though, so if for some reason you can't/don't want to use plist:OnRowSelected, you could just iterate through the players and find the one with a matching Nick. Since I'm not using plist:OnRowSelected, you should be fine. :)

I will note that I think you'll still have a problem with the console command autocomplete changing after using the menu. I *think*you can get around that by resetting the autocompletes as soon as the args panel is built:
Code: Lua
  1. cmdModule.buildArgsList = function(cmd)
  2. local oldCompletes = cmd.args[3].completes
  3. if ( cmd.cmd == "ulx takeitem") then
  4.      -- Your already existing code here
  5. end
  6. oldArgsList(cmd)
  7. cmd.args[3].completes = oldCompletes   //The GUI should be built by now with the limited list of items
  8. end
« Last Edit: March 03, 2014, 11:10:21 am by Stickly Man! »
Join our Team Ulysses community discord! https://discord.gg/gR4Uye6

Offline lynx

  • Jr. Member
  • **
  • Posts: 59
  • Karma: 15
Re: ULX XGUI commands: Dynamic drop down?
« Reply #5 on: March 03, 2014, 11:27:44 am »
Yeah, that worked. Completely forgot to check that even though I read what you said. There's a reason I don't like to code after midnight lol.

Added and just pushed the latest update to GitHub

Offline Stickly Man!

  • Ulysses Team Member
  • Hero Member
  • *****
  • Posts: 1270
  • Karma: 164
  • What even IS software anymore?
    • XGUI
Re: ULX XGUI commands: Dynamic drop down?
« Reply #6 on: March 03, 2014, 04:34:49 pm »
I'm genuinely surprised that my input has been helpful (or accurate) since I've just been looking at code on GitHub and making educated guesses. :P It's like I'm always coding after midnight!
Join our Team Ulysses community discord! https://discord.gg/gR4Uye6

  • Print