Nathrakus

scripting
Execution Order, Custom Variable, and Console Commands

3 posts in this topic

I recently dug into scripting and noticed that a lot of information is missing from the docs and wiki.

I thought I would go ahead and list off some problems I ran into as I wrote my first widget.

Shoutouts to MAD_JIHAD and SickDownlink.

Where can I find example scripts?

My first heuristic when diving into a new API or code base is to find examples and see how they work. The two main examples (the fade example, and the basic wiki example, are good but generally geared to the visual aspect of widgetcraft.) However, there are more examples tucked away in 

reflexfps\base\internal.pak\internal\ui\widgets\ 

You'll need to open the .pak with an archive viewer like 7zip, or your unlicensed version of WinRAR. This was extremely useful information that I wish I would have known about! So I highly recommend starting there if you're interested in widgets.

What functions were called by the engine for initialization, updating, and enabling?

This information came from Qualx on the Reflex Discord, people are great there, and I highly recommend poking your head in there if you have any additional questions.

The entire code file is executed immediately when the game loads it. This execution will usually define one or more widgets which will exist persistently, and the game will then call widget:draw() every frame on any visible, registered widgets. It'll also call initialize() on every widget, followed by show() and draw() if the widget will be visible, immediately after loading the file, and before continuing to load other files, iirc.

How does scope work?

I've noticed that if you're attempting to call function that are scoped to your Widget (e.g.: MyWidget:SomeFunction(){} ), you'll need to call it from either MyWidget:draw(), MyWidget:initialize(), or MyWidget:show(). I've also noticed that calling my own functions internally require the self: prefix to reference the objects function. (e.g.: MyWidget:draw(){self:SomeFunction();} ).

How do I setup a variable to modify from the game's command line? 

This one was a bit tricky because I needed to change the way I thought about variables. If you want to store a variable for later use, or for use in a console command you'll need to create a variable. This variable is pushed to game.cfg and is persistent. (I believe...) to create a variable, widgetCreateConsoleVariable("myvariablename", "variabletype", 1); where variable type is int, string, float, or any other primitive. Now modifying that variable from the console is a little more interesting. Once you add the variable, you can access it like this: ui_MyWidget_myvariablename 12345678 where 12345678 should represent the type you're trying to modify. Note you can call a console command with consolePerformCommand("bind mousewheeldown UI_MyWidget_MyVariableName DVD");

 

I hope this helps someone out in the future. If I'm wrong about any of this, let me know.

-Nath (pain][world)

MAD_JIHAD and slobo^- like this

Share this post


Link to post
Share on other sites

These are some useful global objects and functions:

  • world: Contains a lot of useful data on the state of the game such as game mode, timer, item timers (if enabled), team data, etc.
  • players: Contains the data for all the players connected to the server.
    • getPlayer: Returns the player object for the player that is currently being played or observed.
    • getLocalPlayer(): Returns the player object for the client's player.
  • deltaTimeRaw: The time (in seconds) since the last frame. Useful mostly for animations.
  • gamemodes: Contains information on the different game modes, such as the mode name and is a team mode.
  • widgets: Contains the names and some information for all the loaded widgets. You can iterate over this to get widget names and use _G[widgetName] to get the object for that widget ("_G" is the global object in Lua).

Note that at least the world and players objects are new objects on each frame (so if you say "foo = world" then inspect foo on a later frame, it will not have changed).

Quote

 

Where can I find example scripts?

It can also be good to check existing scripts in the workshop and these forums.

 

Quote

 

How do I setup a variable to modify from the game's command line? 

This one was a bit tricky because I needed to change the way I thought about variables. If you want to store a variable for later use, or for use in a console command you'll need to create a variable. This variable is pushed to game.cfg and is persistent. (I believe...) to create a variable, widgetCreateConsoleVariable("myvariablename", "variabletype", 1); where variable type is int, string, float, or any other primitive. Now modifying that variable from the console is a little more interesting. Once you add the variable, you can access it like this: ui_MyWidget_myvariablename 12345678 where 12345678 should represent the type you're trying to modify. Note you can call a console command with consolePerformCommand("bind mousewheeldown UI_MyWidget_MyVariableName DVD");

I'm not sure what you mean by the first part. If you have a MyWidget:Foo() function defined, you can call it from anywhere in the file that defines it or any other file that transitively requires the file that defines it. MyWidget:initialize() and MyWidget:draw() are the typical entry points to your code, but not the only possible ones.

The second part is just standard Lua. A function definition that starts like MyWidget:foo() is syntactic sugar for MyWidget.foo(self), and calling MyWidget:foo() is syntactic sugar for calling MyWidget.foo(MyWidget). You could if you wanted (but please don't actually do this) define your function as MyWidget.foo(this), use "this" instead of "self" inside the function, and call it like MyWidget:foo() and it would work. You can also call MyWidget.foo(SomeOtherWidget) and now "self" inside the function foo will be SomeOtherWidget (this is useful for implementing a sort of pseudo-inheritance, where SomeOtherWidget is a subclass of MyWidget).
 

Lastly, the formatting on these forums is still a steaming pile of shit, and whoever is maintaining the forums needs to go back to standard BBCode. I literally had to edit this post five times to make the last two paragraphs not get lumped into the last quote. I would rather use plaintext with no formatting at all than this piece of shit formatting system (but of course, even that is not possible).

Nathrakus likes this

Share this post


Link to post
Share on other sites

Thanks for the info, I struggled quite a bit coming to LUA for some reason. I've worked in engines where LUA is used as a scripting language, but it's been a few years. I'll keep that in mind going forward. I'm sure I can clean the code up quite a bit. I like sugar!

MAD_JIHAD likes this

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now