• There is NO official Otland's Discord server and NO official Otland's server list. The Otland's Staff does not manage any Discord server or server list. Moderators or administrator of any Discord server or server lists have NO connection to the Otland's Staff. Do not get scammed!

Lua Solved! Table Variable references value from same table

Codinablack

Dreamer
Content Editor
Joined
Dec 26, 2013
Messages
1,557
Solutions
11
Reaction score
774
Ok so this might seem like a super noobie question, but I am stuck, and I can't seem to find the technique or the method I'm trying to use anywhere out there on stackexchange or reddit or anything... So first the code.

Lua:
CustomSkills =
{
    ["Mining"] = {rate = 1, level = 1, tries = 0, maxLevel = 100, triesToNextLevel = (((self:level * 10) + (self:level * 10)) / self:rate), maxed = false},
}

So in this example, what I'm trying to do, is use "self" to reference the values in this table entry. IE. self:level should = 1, as defined in the table (value of "Mining"). As well as pull the rate from the same table or anything else I would like to pull. Yes I already know I can't use "self" this way, as TFS keeps telling me in console errors :D but I'm looking for something that can help me achieve same end result.

Is this possible? There has to be a super easy way to do this that I'm overlooking right?

The reason I need it to pull the information from itself, ofc, I plan on adding methods for this system that could and would alter the values of those variables inside that table on the fly, or when needed.

Any help would be appreciated, I am having some issues relearning this lua stuff after having used C# now for so many years

I still find myself wanting to type the word Void :D
 
Solution
alternatively you can wrap it in a 'class' (or function to do this, if you don't need/want methods or metamethods for this as extra utility in the future)
Lua:
CustomSkill = setmetatable({}, {
    __call = function(self, obj)
        obj.triesToNextLevel = (((obj.level * 10) + (obj.level * 10)) / obj.rate)
        return setmetatable(obj, {__index = CustomSkill})
    end
})

CustomSkills = {
    CustomSkill {rate = 1, level = 1, tries = 0, maxLevel = 100 }
}

for _, customSkill in pairs(CustomSkills) do
    print(customSkill.triesToNextLevel) -- output: 20
end
In Lua the keyword "self" reprecents this object we are working in. It's used in OOP

And while initializing a value, it is considered nil, meaning that in this operation, it would be you would be trying to do "nil * 10", which is invalid code.
This could most likely be done much better, but the point is, that if we are doing it in the same initialization as the table, then we will be referencing nil.

Super useful fiddle online compiler for lua
Lua:
CustomSkills =
{
    ["Mining"] = {
        rate = 1,
        level = 1,
        tries = 0,
        maxLevel = 100,
        maxed = false
    }
}

triesToNextLevel = {
    ["Mining"] = ((CustomSkills["Mining"].level * 10) + (CustomSkills["Mining"].level * 10)) / CustomSkills["Mining"].rate
}

print(triesToNextLevel["Mining"]) -- 20
 
What you want to do is impossible, you cannot get values from a table that has not finished creating / defining
at least in lua you won't be able to do it like this

Why calculate this in the table if you can do it quickly without any problem in the function that needs this calculated value?

Example:
Lua:
local info = {
    skills = 2.0,
    magicLevel = 2.0,
    multiplier = 1.0
}

local ec = EventCallback

function ec.onGainSkillTries(player, skill, tries)
    if skill == SKILL_MAGLEVEL then
        return ((tries * info.magicLevel) * multiplier)
    elseif skill ~= SKILL_LEVEL then
        return ((tries * info.skills) * multiplier)
    end
    return tries
end

ec:register()

instead of ...
Lua:
local info = {
    skills = 2.0,
    magicLevel = 2.0,
    multiplier = 1.0,
    formulaSK = info.skills * info.multiplier, -- ???????? < XD it doesn't even make sense or logic to do this
    formulaML = info.magicLevel * info.multiplier -- ???????? < XD it doesn't even make sense or logic to do this
}

local ec = EventCallback

function ec.onGainSkillTries(player, skill, tries)
    if skill == SKILL_MAGLEVEL then
        return tries * info.formulaML
    elseif skill ~= SKILL_LEVEL then
        return tries * info.formulaSK
    end
    return tries
end

ec:register()

As the guy above mentioned, it is better to separate this configuration into two tables, so that the second table can get values from the first without any problem.
 
what you should be looking for is an anonymous function to call whenever you'd like that information, if you're looking for an inline solution that works while the table is still being defined
Lua:
local t = {
    {a = 5, b = 10, getValues = function(a, b) return a * b end}
}

for k, v in ipairs(t) do
    print(v.getValues(v.a, v.b)) -- 50
end
 
Thanks guys for the fast response! I know I could definitely split the tables and that would work, but the reason I thought this was possible is because of this

Lua:
CustomSkill = setmetatable({}, {__call = function (t, ...) return CustomSkill(...) end})
CustomSkill.__index = CustomSkill
CustomSkill.__tostring = function (s) return string.format("CustomSkill object: %s", s:getName()) end
CustomSkill.__concat = function (s) return tostring(s) end

function CustomSkill.new(name, player, storage, skillTriesStorage)
    local o = {}
    setmetatable(o, CustomSkill)
    o.name = name
    o.player = player
    o.maxed = player:getCustomStorage(name)
    o.storage = storage
    o.skillTriesStorage = skillTriesStorage
    o.skillTries = player:getCustomStorage(skillTriesStorage) >= 0 and player:getCustomStorage(skillTriesStorage) or 0
    o.skillLevel = player:getCustomStorage(storage) >= 1 and player:getCustomStorage(storage) or 1
    o.skillRate = 1
    o.maxLevel = 10
    [B]o.needTriesToLevelUp = (((o.skillLevel * 10) + (o.skillLevel * 10)) / o.skillRate)[/B]
    return o
end

That is an old code I used in my 1.1 project long ago. It most definitely DOES work in this example. This is just part of the little "system" that I modified to work with 1.1, and when I quit it was working just fine. The big problem I had with this approach was passing the "player" userdata, and that is why I kinda tried my new approach.

I suppose I really don't know why the above did work just fine... can someone help me understand why it worked this way and not my way?

I eventually want to release what I'm working on, and I would rather there be one easily configurable table so that people who aren't scripters, can still modify it easily.
 
Thanks guys for the fast response! I know I could definitely split the tables and that would work, but the reason I thought this was possible is because of this

Lua:
CustomSkill = setmetatable({}, {__call = function (t, ...) return CustomSkill(...) end})
CustomSkill.__index = CustomSkill
CustomSkill.__tostring = function (s) return string.format("CustomSkill object: %s", s:getName()) end
CustomSkill.__concat = function (s) return tostring(s) end

function CustomSkill.new(name, player, storage, skillTriesStorage)
    local o = {}
    setmetatable(o, CustomSkill)
    o.name = name
    o.player = player
    o.maxed = player:getCustomStorage(name)
    o.storage = storage
    o.skillTriesStorage = skillTriesStorage
    o.skillTries = player:getCustomStorage(skillTriesStorage) >= 0 and player:getCustomStorage(skillTriesStorage) or 0
    o.skillLevel = player:getCustomStorage(storage) >= 1 and player:getCustomStorage(storage) or 1
    o.skillRate = 1
    o.maxLevel = 10
    [B]o.needTriesToLevelUp = (((o.skillLevel * 10) + (o.skillLevel * 10)) / o.skillRate)[/B]
    return o
end

That is an old code I used in my 1.1 project long ago. It most definitely DOES work in this example. This is just part of the little "system" that I modified to work with 1.1, and when I quit it was working just fine. The big problem I had with this approach was passing the "player" userdata, and that is why I kinda tried my new approach.

I suppose I really don't know why the above did work just fine... can someone help me understand why it worked this way and not my way?

I eventually want to release what I'm working on, and I would rather there be one easily configurable table so that people who aren't scripters, can still modify it easily.
that works because the table is already created, but you add new keys to it manually
so each line of code, it's able to access all the keys which are defined above that line of code
 
what you should be looking for is an anonymous function to call whenever you'd like that information, if you're looking for an inline solution that works while the table is still being defined
Lua:
local t = {
    {a = 5, b = 10, getValues = function(a, b) return a * b end}
}

for k, v in ipairs(t) do
    print(v.getValues(v.a, v.b)) -- 50
end
So using your technique, theoretically I could do this


Code:
CustomSkills =
{
    ["Mining"] = {rate = 1, level = 1, tries = 0, maxLevel = 100, triesToNextLevel = function(rate, level) return (((level * 10) + (level * 10)) / rate)},
}

and it should work as I intended?
Post automatically merged:

hat works because the table is already created, but you add new keys to it manually
so each line of code, it's able to access all the keys which are defined above that line of code

AHAH! I see... very interesting... You have been a great help my friend thank you.
 
So using your technique, theoretically I could do this


Code:
CustomSkills =
{
    ["Mining"] = {rate = 1, level = 1, tries = 0, maxLevel = 100, triesToNextLevel = function(rate, level) return (((level * 10) + (level * 10)) / rate)},
}

and it should work as I intended?
you'd have to call triesToNextLevel with the values from that table whenever you need that value
 
If you are still interested in keeping the format that I publish, you can also do it like this:
Lua:
CustomSkills = {}

CustomSkills["Mining"] = {rate = 1, level = 1, tries = 0, maxLevel = 100, maxed = false}
CustomSkills["Mining"].triesToNextLevel = (((CustomSkills["Mining"].level * 10) + (CustomSkills["Mining"].level * 10)) / CustomSkills["Mining"].rate)

--CustomSkills["Other"] = {rate = 1, level = 1, tries = 0, maxLevel = 100, maxed = false}
--CustomSkills["Other"].triesToNextLevel = (((CustomSkills["Other"].level * 10) + (CustomSkills["Other"].level * 10)) / CustomSkills["Other"].rate)
 
If you are still interested in keeping the format that I publish, you can also do it like this:
I'm thinking I will either have to do it just like that, or add more work to my methods for addingskilltries, probably both., either way much thanks to you and the others for helping clear that confusion up for me, and get me back to being productive :D
 
alternatively you can wrap it in a 'class' (or function to do this, if you don't need/want methods or metamethods for this as extra utility in the future)
Lua:
CustomSkill = setmetatable({}, {
    __call = function(self, obj)
        obj.triesToNextLevel = (((obj.level * 10) + (obj.level * 10)) / obj.rate)
        return setmetatable(obj, {__index = CustomSkill})
    end
})

CustomSkills = {
    CustomSkill {rate = 1, level = 1, tries = 0, maxLevel = 100 }
}

for _, customSkill in pairs(CustomSkills) do
    print(customSkill.triesToNextLevel) -- output: 20
end
 
Solution
Damn man, I wish I could mark more than one as the solution :/

@Sarah Wesker 's technique is a perfect solution, however it does require making a
"triesToNextLevel" for each and every individual "custom skill", which in the end is just basically rewriting the same code over and over, however for user friendliness it is best, and allows more configuration for each skill.

That being said, for anyone who finds this thread @Infernum 's technique fits my "desired" solution more aptly! It also keeps anyone who wants to do this from having to remake the same thing over and over, saving many lines of code.

Both posts work flawlessly
 
Last edited:
Back
Top