I have a main loop in my lua script, and i am including 2 objects like this:
local Menu = require("menu")
local InputHandler = require("inputhandler")
Here are the scripts for each object:
menu.lua
Menu = {
Active = false,
Initialise = function(self)
end,
ToggleMenu = function(self)
self.Active = not self.Active
print(self.Active)
end
}
return Menu
and inputhandler.lua
InputHandler = {
KeyBinds = {
q = { scancode = 16, bind = "q", action = "Menu:ToggleMenu" }
},
RunKeyAction = function (self, key)
for k, v in pairs(self.KeyBinds) do
if (v.bind == key) then
_G[v.action]()
end
end
end
}
return InputHandler
Basically I am trying to map keyboard keys to various functions within my script, so when someone presses "Q", it will run the method associated with that key.
So if I do something like this:
InputHandler:RunKeyAction("q")
It will run this method:
Menu:ToggleMenu()
When I run this script as it is now, I get this error:
lua: ./classes//inputhandler.lua:8: attempt to call field '?' (a nil value)
stack traceback:
./classes//inputhandler.lua:8: in function 'RunKeyAction'
[string "<eval>"]:20: in main chunk
Can anyone please tell me that correct way of doing this?
Thank you for reading
Use
q = { scancode = 16, bind = "q", action = Menu.ToggleMenu }
and
v:action()
Related
Lua seems to pass parameters' memory adress to function instead of value
Is that a standard behaviour ?
Following code can be tested at https://www.lua.org/cgi-bin/demo
local t = {
Give = {"original"},
Etapes = {},
}
function check (obj)
for k, v in pairs(obj) do
if k == "Give" then
obj[k] = {"modified"}
end
end
-- return obj
end
print ("BEFORE t.Give[1]="..t.Give[1])
check(t)
print ("AFTER t.Give[1]="..t.Give[1])
print result :
BEFORE t.Give[1]=original
AFTER t.Give[1]=modified
I have been working on a survival game base on "Booga Booga" but i cant seem to find out how to load player data on the game. The data im trying to load is saved in the for loop that follows:
module.SaveData = function (player, DT)
local data_saved = {}
local setData = player.inventory.Inv:GetChildren()
for i, v in pairs(setData) do
table.insert(data_saved, {[v] = {
value = v.Value,
name = v.Name
}})
end
Data_Store:SetAsync(player.UserId, data_saved)
end
I've done multiple things to attempt to solve this problem
I've tried load with http service
I've already attempted loading the raw table
and I've tried to use a global data store instead
here is my code that loads the data as of now:
game.Players.PlayerAdded:Connect(function(plr)
CF.PlayerInventorySetup(plr) -- not relavent
p = plr -- not relavent
local PD =require(game.ServerScriptService.DataHandler)
local plrdata =PD.FetchData(plr)
for i, v in pairs(plrdata) do -- this is what im having trouble with
if not plr.inventory.Inv:FindFirstChild(v) then
local newint = Instance.new("NumberValue")
newint.Name = v.name -- the ouput says: string expected, got nil
newint.Value = v.value --
newint.Parent = plr.inventory.Inv
end
end
end)
I actually don't know wtf to do.
Before we talk about a solution, let's talk about what's happening when you save the data. Let's say for example, your inventory is a list of NumberValues like this :
Fish (value of 3)
Iron (value of 10)
Grass (value of 8)
Your FetchData function expects that the saved player data is formatted like this :
{
{ value = 3, name = "Fish" },
{ value = 10, name = "Iron" },
{ value = 8, name = "Grass" },
}
However, the result of the loop in the SaveData function would be this :
{
{ Fish(NumberValue) = { value=3, name="Fish" }},
{ Iron(NumberValue) = { value=10, name="Iron" }},
{ Grass(NumberValue) = { value=8, name="Grass" }},
}
On every step of the loop, you are pushing a new dictionary into the data_saved table.
The FetchData function expects that dictionary to have keys for "name" and "value". But, you've pushed that data one layer deeper, so those keys don't exist where the FetchData code expects them to and it throws errors.
So to fix your issue in the SetData function, remove the outer layer of that table, and just use the raw data.
table.insert(data_saved, {
value = v.Value,
name = v.Name
})
return{
initime = 1;
isneed= true; -- need to modify
testfn=function()
isneed = false; ---how to modify the "isneed" value?
end
}
i wanna modify the isneed's value,i have try like this
local testdata;
testdata={
initime = 1;
isneed= true;
testfn=function()
testdata.isneed = false;
end
}
return testdata;
but the code that i dont want,i think have another way to set the value.
Building on #luther's comment, the code you have in your second example should work.
local testdata = {
initime = 1,
isneed = true,
testfn = function()
testdata.isneed = false
return
end
}
print(testdata.isneed)
testdata.testfn()
print(test.data.isneed)
This should output the following:
true
false
Alternatively, if you wanted to get a little fancier, you could use a metatable to overload the call operator for your table testdata:
local testdata = {
initime = 1,
isneed = true,
testfn = function()
testdata.isneed = false
return
end
}
testdata = setmetatable(testdata, {
__call = function(self)
return self.testfn()
end
})
print(testdata.isneed)
testdata()
print(testdata.isneed)
This example's output is equivalent to the above output. Depending on what exactly you wish to accomplish with your code, overloading the call operator with a metatable could offer you some more flexibility. Using this approach, you could change your code slightly like this, making use of the self parameter in the __call function:
local testdata = setmetatable({initime = 1, isneed = true}, {
__call = function(self)
self.isneed = false
return
end
})
print(testdata.isneed)
testdata()
print(testdata.isneed)
This will produce the same output as the first example.
No matter how I approach Lua, I run into this error all the time, so I must not understand something inherit to the language:
attempt to call method 'func' (a nil value)
I've seen the error here a few times as well but the problem doesn't seem clear to me.
Here's my module:
actor.lua
Actor = {
x = 0,
mt = {},
new = function()
local new_actor = {}
new_actor.x = Actor.x
new_actor.mt = Actor.mt
return new_actor
end,
test = function(self, a, b)
print(a, b)
end
}
I'm using Löve.
main.lua
require "game/actor"
local a = Actor:new() --works fine
function love.load()
a.x = 10
print(a.x) --output: 10
a:test(11, 12) --error: attempt to call method 'test' (a nil value)
end
I'm also not sure when it's appropriate to use the previous styling over this in a module.
Actor = {
x = 0
}
Actor.mt = {}
function Actor.new()
print(42)
end
I'm honestly not sure what is more correct than the other but considering I run into a simple error either way, there's probably something I'm missing entirely?
It looks like you're trying to instance a kind of class made of metatables. You basically need to assign new_actor's metatable with Actor.mt. (Resuming the problem: when you're indexing new_actor you're not indexing Actor in this case)
setmetatable(new_actor, Actor.mt);
Even if the metatable is being added, it won't work until you put the meta "__index" event to index a table containing your class methods/values, in this case:
Actor.mt = {
__index = Actor
};
I'd suggest moving your class methods/values into a new table, like Actor.prototype, Actor.fn, etc... avoiding conflicts:
Actor.fn = {
test = function(self, a, b)
print(a, b)
end
};
Actor.mt = {
__index = Actor.fn
};
More about metatables in Lua 5.3 manual.
I was working on this project about a year ago. I came back to it and now it throws an error when I run it the error is "attempt call field "drawers"(a table value)".
This is where the drawers field is
local Renderer = {}
local num_of_layers = 2
local insert = table.insert
local remove = table.remove
function Renderer:create()
local render = {}
render.drawers = {}
for i = 0, num_of_layers do
render.drawers[i] = {}
end
function render:addRenderer(obj, layer)
local l = layer or 0
insert(self.drawers(l), i, obj)
end
return render
end
return Renderer
This is where it is being called
local tlm = {}
function tlm:load()
renderer:addRenderer(self)
gameloop:addLoop(self)
end
This is not correct:
insert(self.drawers(l), obj)
self.drawers is not a function but a table. therefor a function call like self.drawers(1) results in an error.
If you wanted to insert an element to the table self.drawers at index l using Luas standard functions you should call:
table.insert(self.drawers, i, obj)
If you want to replace the value at index l you can simply write self.drawers[l] = obj
http://www.lua.org/manual/5.3/manual.html#pdf-table.insert