Forums » Community Projects

Turbo Lock - Auto Shut Down plugin

«12
Jun 27, 2008 Scuba Steve 9.0 link
This is silly:
RegisterUserCommand("reinstallttog", function() reinstallttog() end)

This would do the same thing, with less silliness:
RegisterUserCommand("reinstallttog", reinstallttog)

This is not silly:
RegisterUserCommand("ttog3", function() ttog[1]=1;ttog[2]=GetActiveShipEnergy();TurboOn() end)

And oh dear god why would you write this in Lexor?
I'm going to cut out useless binds and give the same thing in lua*:

--[[-----------------DISCLAIMER: This code has not been tested. It may be riddled with syntactical mistakes or bugs-----------------]]
--Get out of my global table, jerk. Bad practice.
declare("ttog", {})
ttog.timer = Timer()
ttog.lock = 1
ttog.energy = GetActiveShipEnergy()
ttog.gkpc = GKProcessCommand --Way too long to type ._.
function ttog.install()
     RegisterUserCommand("+ttog", ttog.On)
end

function ttog.switch()
     if ttog.lock == 1 then
          ttog.gkpc("alias +t +ttog;-t ''")
          ttog.lock = 0
     elseif ttog.lock == 0 then
          ttog.gkpcs("alias +t +turbo; alias -t '+turbo 0'")
     end
end

function ttog.uninstall()
     UnregisterUserCommand("+ttog")
     ttog.gkpc("alias +t ''; alias -t ''")
end

function ttog.On() --Oops, I forgot how to declare a function in a timer and have the function call itself, but oh well.
     ttog.energy = GetActiveShipEnergy()
     ttog.gkpc("+turbo")
     ttog.active()     
end

function ttog.active()
     if not ttog.timer then ttog.timer = Timer() end
     ttog.timer:SetTimeout(50, ttog.active) --Not function() ttog.On() end, that's silly.
     if ttog.energy < GetActiveShipEnergy() then
          ttog.gkpc("+turbo 0")
          ttog.timer = nil --Done our job, time to kill the timer.
     end
     ttog.energy = GetActiveShipEnergy()
end

--[[The original version of this function is below. Kept for demonstation purposes only
MyntX is not even declared as a timer, so it creates a hidden dependency which breaks your nasty
code unless someone has whatever other plugin you wrote with that timer declared it in.
Second, using a global timer for more than one plugin is a horrible idea in the first place.
Scratch that, globals in general are horrible.
--[[function TurboOn() if ttog[1]~=nil then MyntX:SetTimeout(50, function() TurboOn() end); if ttog[2]<GetActiveShipEnergy() then gkinterface.GKProcessCommand("ttog2") end end;ttog[2]=GetActiveShipEnergy() end]]

--And this
function ttog.help() print("ttog reinstall - Reinstall turbo bind.");print("ttog uninstall - Removes the bind used for turbo lock.");print("ttog switch - Swaps locked turbo and normal mode");print("Bind +t to a button for switchable turbo, +ttog for plain locked") end

--Used to be Slime's stuff function
local function stuff(unused, blah)
     if not blah then print("you suck") return end
     local cmd = blah[1]:lower()
     if cmd == "reinstall" then
          ttog.install()
     elseif cmd == "uninstall" then
          ttog.uninstall()
     elseif cmd == "switch" then
          ttog.switch()
     else
          print("you suck, furthermore:")
          ttog.help()
     end
end

RegisterUserCommand("ttog", stuff)

ttog.install()

print("autottog v1.no - type /ttog for a list of commands. Original horrible mess was Eldrad's turbolock modified by Mynt")
Aug 03, 2008 SuperMegaMynt link
I forgot to type in MyntX=Timer(); it does that in my skeleton. My mistake, and thanks for catching it. It's fixed as of 10 minutes from now.

Are you sure RegisterUserCommand("reinstallttog", reinstallttog) is the same as RegisterUserCommand("reinstallttog", function() reinstallttog() end)? reinstallttog doesn't seem like a function to me. I agree, it's rather silly, and I might add that I when I learned I needed to type out the seemingly vestigial function() every time, I found it rather frustrating (as I couldn't find the bug in my plugins) and I certainly hope it's unnecessary.

The reason why it articulates with the binds is that I figured a sizable demographic would have Eldrad's bind already installed. With this plugin, the user merely needs to put it in the right folder, and run VO. No new binds, no console, no knowledge of programming whatsoever. You might notice that of the three installing commands, none of them are 'install'; it does that automatically, and if I'm going to screw with people's binds automatically, I damn well better put in a way to redo any damage. But I don't know how to make the script intelligent to how the user modifies his wgaf.cgf file, so if the user does, I let the user be intelligent, and offer him some options. As you said yourself, binds do the same thing, so there's no reason not to use them if it presents an advantage.

What is Lexor?
Aug 04, 2008 MSKanaka link
alias whatislexor "echo Lexor is the name of the alias and bind interpreter, you newb!"
bind "LMBUTTON" whatislexor
Aug 04, 2008 Scuba Steve 9.0 link
I was originally wondering why the code up there sounded so annoyed, and then I went back to read the original block.

Anyway,

Are you sure RegisterUserCommand("reinstallttog", reinstallttog) is the same as RegisterUserCommand("reinstallttog", function() reinstallttog() end)? reinstallttog doesn't seem like a function to me.

Yes, they're functionally the same. You declared resinstallttog() as a function in the code block. It's easier to see with proper whitespacing.
Beyond that, if it wasn't a function then this part would throw an error:

RegisterUserCommand("reinstallttog", function() reinstallttog() end)

If you can call it like a function, then chances are that it's a function and you don't need to wrap it in a function.

As far as the original design decision to keep the original binds, I somewhat see where you're coming from. However, it's unnecessary to reimplement the Lexor script. In the version of the code I posted above, the binds are automatically already installed and functional as +t and +ttog(they do they same thing) and have the same functionality as Eldrad's binds. As it stands, the plugin code overwrites Eldrad's old binds, and provides the same functionality. If it bugs you too much, you can always add a line to the /ttog interpreter function that calls ttog.uninstall() and then gkpc's eldrad's old binds in.

In this case, binds do not present any advantage I can see in terms of usability, readability, functionality, or extendability.

Notes:
- After looking at the code, it's not clear in the gkpc calls which are double and which are single quotes. My mistake. The calls themselves appear to have the correct syntax.

- Miharu didn't actually know what the Lexor was until a little while ago, though does now. Personally, I think the last time I heard the devs talk about it was in VO Test 3.2.x

- Try to make your code readable. It benefits your users and yourself in the long run.

Edit: A quote from IRC, regarding this post

<Eonis> It's not reverse engineering if you're SUPPLYING THE SOURCE CODE
Aug 04, 2008 Eonis Jannar link
These forums need a [code] tag.

Anyway, for Mynt and any other people who are kind of confused about the "function()" vs. "function" aspect of Lua syntax:

In Lua, unlike in many other languages, functions are first-class values. What this means is that, while they function normally in terms of calling and returning values and such, they can also be used as values of their own.

(Chorus of "wut?")

Think of it this way. This is the standard syntax for declaring a function:

-----------------------------------------
function foo()
  print("bar")
end
-----------------------------------------

And that works great. But it's actually just syntactic sugar; an easier, clearer way of writing how you actually declare a function. If you were to do it the non-sugared way, it would look like:

-----------------------------------------
foo = function() print("bar") end
-----------------------------------------

That syntax, while not as clean as the previous version, illustrates the concept of functions as first-class values a lot better: when you create a function, you're actually creating a variable, and assigning it a function as its value. You can, in fact, reassign function variables completely different values, since Lua is dynamically typed:

-----------------------------------------
function foo()
  print("bar")
end

foo = "not a function anymore!"
-----------------------------------------

But by far the most important aspect of functions as first-class values is that they can be passed as variables, instead of called, simply by leaving off the () at the end. Scuba's code offers a great example right up at the top:

-----------------------------------------
ttog.energy = GetActiveShipEnergy()
ttog.gkpc = GKProcessCommand
-----------------------------------------

There are parentheses after GetActiveShipEnergy. Therefore, Scuba is calling GetActiveShipEnergy(), and assigning its returned value to ttog.energy. But there are no parentheses after GKProcessCommand. That means that, instead of calling GKProcessCommand and assigning its returned value to ttog.gkpc, Scuba is assigning GKProcessCommand itself to ttog.gkpc. This means that, whenever Scuba calls ttog.gkpc() in that code, he's effectively calling GKProcessCommand(). This is a tactic often used in Lua code where speed is an issue; since calling local functions is much faster than calling global ones, a commonly used global function may be assigned to a local variable to speed things up:

-----------------------------------------
local iowrite = io.write
-- this means that whenever the code calls
-- iowrite("foobar"), it's the same as
-- calling io.write("foobar"), except
-- faster.
-----------------------------------------

So, this is why RegisterUserCommand("reinstallttog", function() reinstallttog() end) is the same as RegisterUserCommand("reinstallttog", reinstallttog). You're passing a function to RegisterUserCommand as the second argument, so instead of creating a useless wrapper function like you do in the former version, you can just pass the function itself, as in the latter version.

I hope the way Lua deals with functions is a little clearer now!

--Eonis