Jump to content
Phodex Games

Two Lua Questions

Recommended Posts

Hi Leadwerkers :),

I am wondering for quiet a while now, if and how the two things, I will explain in a second, are possible.

First can I grab the "self" value of an function caller WITHOUT using arguments? I would expect this to work with the lua debug.getinfo() functionality? Maybe I better explain it with pseudo code:

--Script 1:
function Script:Test()
  Script2:CallingThis()
end

--Script 2:
function Script:CallingThis()
	--get self of caller
end

Btw I have no idea how you offically call a "caller" maybe its calle? I dont know :D

Second how to grab an arguments root variable. What I am already aware of is accessing variables like this self["myVariable"] so I could send self as argument 1 and "myVariable" as string in argument 2, but I am looking for a way to prevent this to optimize the code and lower the error rate. Again some pseudo code:

--Script 1:
Script.myVariable = 10

function Script:Test()
  Script2:CallingWithArgument(self.myVariable)
end

--Script 2:
function Script:CallingThis(argument)
	--if I do anything with the variable argument here it only changes the local "argument" variable of course
  	--this is stupid but I guess it will explain what I mean:
  	local rootVariable = argument:GetRoot()
  	rootVariable = 20 --> myVariable is changed to 20 within the Script 1
end

You would do me a great favor if you would give me some input on this. I would be able to improve my code even more :)

Thanks in advance for answering and have a nice day :)

Share this post


Link to post

Interesting questions. I don't know if there is a variable in existence that gets you the callers 'self'. But maybe there is something hidden in the lua meta tables that can do this.

As for getting the root there are probably neat little tricks you can do here, but not without the use of tables. Maybe this way:

--variable is a table
Script.myVar = { ["root"] = self, ["value"] = 10 }

Function Script:Test1()
	self:Test2(self.myVar)
end

Function Script:Test2(myVar)
	myVar.root
    myVar.value
end

Or make a new class object called Variable were you store the above table in. There are probably prettier ways, but I never dug that deep in to lua meta tables.

Share this post


Link to post

Hmm ok thats not a bad idea to store this data directly inside the variable, but to make this work for every variable I would have to change the whole variable management, short, would need to change all variables, which would be a damn lot of work :D. Yeah I am not much into metatable as well, but I guess it would be a good idea to learn more...

Thanks anyway, so for the moment I need to send this data as an argument, just searched for a way to do this automated.

Share this post


Link to post

You can just pass self as an argument:

--Script 1:
function Script:Test()
  Script2:CallingThis(self)
end

--Script 2:
function Script:CallingThis(otherthing)
	local caller = otherthing
end

Example:

--Script 1:
Script.myVariable = 10

function Script:Test()
  Script2:CallingWithArgument(self)
end

--Script 2:
function Script:CallingWithArgument(caller)
  	caller.myVariable = 20 --> myVariable is changed to 20 within the Script 1
end

 

Share this post


Link to post

I think he's saying he doesn't know what the variable name of the object actually is while inside the function that changes it so he can't hardcode that in the function that's changing the variable. To me it seems like he's asking how to pass primitive variables by reference (or a pointer to them) so when the value is changed it's seen outside of the function call.

Josh, the example you have I'm not following. Where is CallingWithArgument() defined? How is doing caller.rootVariable = 20 changing script 1's myVariable?

 

OP: Tables are passed by reference but primitives aren't. The deeper question is why are you thinking you need this? Perhaps there is a different way that isn't so hacky or confusing to anyone reading your code.

Share this post


Link to post
4 minutes ago, Rick said:

Josh, the example you have I'm not following. Where is CallingWithArgument() defined? How is doing caller.rootVariable = 20 changing script 1's myVariable?

Fixed.

Share this post


Link to post

Yeah, see he's saying in script 2's function he doesn't know the name of the variable in script 1.

To build off Aggror's here's a way to do it by wrapping all primitives in a table. If plugged into here you can see it work: https://www.lua.org/cgi-bin/demo

You can do a set/get idea which might make it more readable and understandable

 

Variable = {}

function Variable:create(value)
   local obj = {}

   obj.value = value

   for k,v in pairs(Variable) do
      obj[k] = v
   end

   return obj
end

function Variable:set(value)
   self.value = value
end

function Variable:get()
   return self.value
end

function ChangeMe(v)
   v:set(20)
end

local v1 = Variable:create(10)

print(v1:get())

ChangeMe(v1)

print(v1:get())

I'll see if there is a way to not have to say .value. You might be able to just make v = 20 and have it translate to v.value somehow with meta stuff lua has. That way it would simulate like it's a primitive value instead of a table.

Share this post


Link to post

First of all thanks for your input. 

1 hour ago, Rick said:

The deeper question is why are you thinking you need this?

Well actually its just to make my code more error proof & simple. I would like to turn something like this:

--Example Case
--Script1
Script.health = 100
function Script:SomeFunction()
	Script2:IncreaseHealth(self, 10)
end

--Script2
function Script:ChangeMyVariable(target, healthAdd)
	target.health = callerSelf.health + healthAdd
end

Into this:

--Example Case
--Script1
Script.health = 100
function Script:SomeFunction()
	Script2:IncreaseHealth(10)
end

--Script2
function Script:ChangeMyVariable(healthAdd)
	--automatically get callerSelf here
	callerSelf.health = callerSelf.health + healthAdd
end

I am just asking because I though there may be an easy way of doing this, as debug.getinfo(2).name for example does print the function callers name. So can't you access the self of the caller function with this? All this is just for the sake of improving my code, it is not nessecary in the way of building a mechanic out of it.

@Rick I already have such a Get/Set mechanic, for checking if an variable got changed since the last check, but I would not like to move all my variable management over to this system, I just use it for specific variables. However I guess I would be a good idea to do this longterm...

Share this post


Link to post

In that specific example you might want to think about reversing the flow. Have script2 call script1's IncreaseHealth(10) so that script1 can just increase it's health variable vs the reverse way you have it. The object that owns the variable should really be the thing that controls it directly (encapsulation those variables in the object instead of exposing them for others to change). Functions can be created on that object that other things can call if they want to ultimately manipulate it. Think of these functions as the API to said object. You'll generally  have less confusion and easier debugging if said variable is only ever changed in 1 spot (the object member function) vs exposed all over the place being changed by who knows what.

I know what you have is just an example an maybe you have some bigger system behind the scenes here but all I can go off is the example and seeing that example I'd reverse how you're doing it.

Share this post


Link to post
26 minutes ago, Rick said:

I know what you have is just an example an maybe you have some bigger system behind the scenes here

Exactly, I have multiple systems which would have an advantage of this. For example I have a global character commands class giving my player & my AI access to all actions they need. This makes sense so as I want to change a mechanic I do not have to maintain this for both the AI & the player. As it is global (and I want it to be global so that you do not need to initiate it for any script (I initiate it in the main) and can call it from everywhere) I created a client management system that allows my command class to exectue its actions on as many entites as I desire, but I need to send the self "table" as an argument for every command, so the commands class knows on which entity the command should be executed, and this is what I would like to overcome.

Eitherway I think having the functionality I explained would be a cool tool for creating systems...

Share this post


Link to post

I would check to see if the value you are looking for exists and then modify it if it does. My own scripts do this all the time:

function Script:ChangeMyVariable(object)
	if type(object.health)=="number" then
		object.health = object.health + healthAdd
	end
end

I would say this is my official recommended technique of doing stuff like this.
 

Share this post


Link to post

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...