• Do not use Works in Progress as a way of avoiding the releases system! Works in Progress can be used for sharing early betas and for getting suggestions for improvement. Releases of finished content are not allowed in this forum! If you would like to submit a finished addon, click here for instructions on how to do so.

How to create a command in Lua?

Status
Not open for further replies.

amperbee

thunderdome denizen
Retired Staff
I'm trying to reverse-engineer a script I downloaded to make something for myself just to test the new Lua feature but I don't know what should I do.
All I want to make is a command that adds, sets or whatever the momentum of the player to whatever value the player choosed.

Code:
ply_mom = function(op, lolx, loly, lolz)
  if lolx == nil then
    lolx = 0
  end
  if loly == nil then
    loly = 0
  end
  if lolz == nil then
    lolz = 0
  end
  if op == 'add' then
    player.mo.momx = player.mo.momx + lolx
    player.mo.momy = player.mo.momy + loly
    player.mo.momz = player.mo.momz + lolz
    print("You added some momentum.")
  elseif op == 'set' then
    player.mo.momx = lolx
    player.mo.momy = loly
    player.mo.momz = lolz
    print("You set your momentum.")
  elseif op == 'mult' then
    player.mo.momx = player.mo.momx * lolx
    player.mo.momy = player.mo.momy * loly
    player.mo.momz = player.mo.momz * lolz
    print("Stop trying to crash the game with your momentum, will you?")
  else
    print("Placeholder for invalid argument and some quick help.")
  end
end

COM_AddCommand(momentum, ply_mom(op, lolx, loly, lolz), 0)

Now, how do I make this function a console command that takes 4 arguments and executes it to the player?
I'm new to Lua, I read the tutorials and the functions page too.
Also, everytime I load the Lua, it says that the initialization of ply_mom was prevented or something like that.
I don't get the command adding part also.

---------- Post added at 10:58 PM ---------- Previous post was at 10:36 PM ----------

Fixed it!
However I'm still having a problem:

Code:
local function newmom(ignore, op, lolx, loly, lolz)
  if lolx == nil then
    lolx = 0
  end
  if loly == nil then
    loly = 0
  end
  if lolz == nil then
    lolz = 0
  end
  if op == 'add' then
    player.mo.momx = player.mo.momx + lolx
    player.mo.momy = player.mo.momy + loly
    player.mo.momz = player.mo.momz + lolz
    print("You added some momentum.")
  elseif op == 'set' then
    player.mo.momx = lolx
    player.mo.momy = loly
    player.mo.momz = lolz
    print("You set your momentum.")
  elseif op == 'mult' then
    player.mo.momx = player.mo.momx * lolx
    player.mo.momy = player.mo.momy * loly
    player.mo.momz = player.mo.momz * lolz
    print("Stop trying to crash the game with your momentum, will you?")
  else
    print("Placeholder for invalid argument and some quick help.")
  end
end
COM_AddCommand("momentum", newmom, 0)

There was a problem indexing player (a nil value).
What did I do wrong?

EDIT: Fixed it. I had to put "player" as the first argument. Now everytime I use it, I have to put a giant numer to move the player a bit lower, like 555555. What its wrong now?
FINAL EDIT: Fixed it. All I had to do is multiply the value given by the player by 65535.
 
Last edited:
COM_AddCommand takes three arguments; a string denoting the name (for instance, "momentum" quotes included), a reference to a function or an inline function (so if your function is declared local function cheesecake(player, arg1, arg2, ...) then here you'd put cheesecake without the brackets), and an optional number parameter to limit it to admins only (or to make it affect the splitscreen player).

So what you'd want is for your COM_AddCommand statement to look something like COM_AddCommand("momentum", ply_mom). That said, there are two problems with your specific function:


  • player is undefined, and will throw a "tried to index null" error when you access it. However, the first argument passed to any function executed via a console command is the struct of the player that activated it, so all you'd do to fix this issue is add a player argument to your function, so your first line would look something like local ply_mom = function(player, op, lolx, loly, lolz).
  • Lua, despite being a loosely typed language, does not automatically convert strings into their numerical representations when performing math on them. (At least, SRB2's implementation doesn't.) Fortunately, Lua has a tonumber(str) function that can convert this for you, and returns nil if the string doesn't represent a valid number. So what you'd want to do is add three lines to the start of your function that read like lolx = tonumber($1) and similar. (Passing a nil value to tonumber doesn't affect anything, except that it still returns nil.)
And as a little shorthanding technique, you wouldn't have to check for equivalence to nil and set the number to 0 afterward. You can simply append the line I mentioned above to read like lolx = tonumber($1) or 0. That'll return the latter number (0) if the first expression would evaluate to false in a boolean cast. 0 and nil are both cast to false in such a case, while everything else is cast to true. (I use a similar technique in a lot of scripts I make to avoid "tried to perform arithmetic on nil" errors without adding extra statements to my code.)

To answer the question that you edited in right before I posted this (>_>), a lot of math in SRB2, including momentum, is handled using fixed-point arithmetic. This means that an in-game perceived value of 1 isn't actually represented by 1, but by a large number. (The technical value is 65536, but don't use this number directly; use the constant FRACUNIT, which is equal to this value.) So the solution here would be to multiply your add/subtract values by FRACUNIT. (Alternatively, if you'd like you can steal the FloatToFixed function from Terminal - it's all reusable code! - and use that to turn a string representing "1.5" into an integer equal to 3*FRACUNIT/2.)

Multiplication and division of these numbers is handled with the FixedMul and FixedDiv functions, which automatically handles all of the fancy math stuff needed to ensure that multiplying 3*FRACUNIT by 3*FRACUNIT gets you 9*FRACUNIT, and that you don't hit integer overflows in the middle of the multiplication process.
 
Last edited:
Thank you RedEnchilada for your explanation and help.
(By the way, I forgot to refresh the page on several occasions. Hehee)
 
Status
Not open for further replies.

Who is viewing this thread (Total: 1, Members: 0, Guests: 1)

Back
Top