• 🏆 Texturing Contest #33 is OPEN! Contestants must re-texture a SD unit model found in-game (Warcraft 3 Classic), recreating the unit into a peaceful NPC version. 🔗Click here to enter!
  • 🏆 Hive's 6th HD Modeling Contest: Mechanical is now open! Design and model a mechanical creature, mechanized animal, a futuristic robotic being, or anything else your imagination can tinker with! 📅 Submissions close on June 30, 2024. Don't miss this opportunity to let your creativity shine! Enter now and show us your mechanical masterpiece! 🔗 Click here to enter!

Lua - Retrieve values from a table within a table

Status
Not open for further replies.
Level 1
Joined
Apr 8, 2020
Messages
110
My setup:
local self = {}
self[field] = {}
self[field][level] = value
print(self[field][level]) ---> properly prints value

Later in a different function:
return self[field][level]

...returns nil

It recognizes self[field] as a table but I cannot get any values from this subtable using [level].
What is the issue? What needs to be done?
 
Level 1
Joined
Apr 8, 2020
Messages
110
Here is the full code:
Lua:
//      --------------------
//      -- 'ability module':
//      --------------------
//! i   ability = {}

//      -- Global private variables:
//! i   local idcounter = 0

//      -- Global public variables
//! i   level = 'alev'

//! i   function ability.new(base)
//! i       setobjecttype("abilities")
//! i       local self = {}

//          -- Create new ability
//! i       if idcounter < 10 then
//! i           newID = 'A00'..idcounter
//! i       elseif idcounter < 100 then
//! i           newID = 'A0'..idcounter
//! i       else
//! i           newID = 'A'..idcounter
//! i       end
//! i       createobject(base, newID)
//! i       self.aid = newID
//! i       idcounter = idcounter + 1

//          -- Private methods:
//! i       local function reset()
//! i           setobjecttype("abilities")
//! i           modifyobject(self.aid)
//! i       end

//! i       local function replace(field, lvl, value)
//! i           if type(value) == 'string' then
//! i               value = string.gsub(value, level, lvl)
//! i               makechange(current, field, lvl, value)
//! i           end
//! i           return value
//! i       end

//          -- Public methods:
//! i       function self.get(field, subfield, lv)
//! i           if lv == nil then
//! i               return self[field][subfield] or self[field]
//! i           else
//! i               return self[field][subfield][lv] or self[field][lv]
//! i           end
//! i       end

//! i       function self.setlv(field, lv, value)
//! i           reset()
//! i           if not value then
//! i               value = lv
//! i               if type(value) == 'table' then
//! i                   for i = 1,#value do
//! i                       self[field] = {}
//! i                       self[field][i] = replace(field, i, value[i])
//! i                   end
//! i               else
//! i                   for i = 1,self.level do
//! i                       self[field] = {}
//! i                       self[field][i] = replace(field, i, value)
//! i                   end
//! i               end
//! i           else
//! i               if type(lv) == 'table' then
//! i                   for i = 1, #lv do
//! i                       if type(value) == 'table' then
//! i                           self[field] = {}
//! i                           self[field][i] = replace(field, lv[i], value[i])
//! i                       else
//! i                           self[field] = {}
//! i                           self[field][i] = replace(field, lv[i], value)
//! i                       end
//! i                   end
//! i               else      
//! i                   self[field] = {}
//! i                   self[field][lv] = replace(field, lv, value)
//! i               end
//! i           end
//! i       end

//! i       function self.set(field, value)
//! i           reset()
//! i           makechange(current, field, value)
//! i           self[field] = value
//! i       end

//! i       function self.setlevel(int)
//! i           self.level = int
//! i           self.set('alev', self.level)
//! i       end

//! i       return self
//! i   end

//      ---------------
//      -- Application:
//      ---------------
//! i   local a1 = ability.new('AEsf')
//! i   local a2 = ability.new('AEsf')

//! i   a1.setlevel(2)
//! i   a1.setlv('aub1', level..'Gonzales '..level..' Gonzales')

//! i   a2.setlevel(7)
//! i   print(a1.get('aub1', 1))
 
Last edited:
Level 18
Joined
Oct 17, 2012
Messages
826
The problem is that you are setting self[field] to a new table each time you are looping through levels. Therefore, ultimately, only the last level will not return nil upon calling self.get().

The solution is to move the setting of self[field] outside the loops. You should also make sure self[field] has not been set before.
 
Level 12
Joined
Jan 30, 2020
Messages
875
Don't worry, with Lua, nothing is easier than making dumb mistakes, I paid my share in the matter more than once.

Anyways, I had a question :
What the hell are those "//! i" at the beginning of each line ?

Is it something related to an old special Word Editor with Lua support before it was officially implemented ?

Sorry if the question seems dumb, but I stopped map making for 16 years and only came back last December and I have never seen this.
 
Level 12
Joined
Jan 30, 2020
Messages
875
Oh nice, I was not aware of this Object Generator !

I suppose it is not compatible with Reforged. Still really impressive stuff.
 
Level 18
Joined
Oct 17, 2012
Messages
826
Not necessary. You can use JNGP Lua Edition or any other version of JNGP (as long as you replace the code in findpath.lua with the one bundled with the Lua edition) to generate the objects via code and then find a way to merge object data if your map is already in development.

Otherwise, import object date files via mpq to your map or through the object editor by first making the map with the generated objects compatible with Reforged (by simply saving the map in Reforged editor I believe) and then exporting and importing the object data files via the object editor functions.

One thing to note about the Object Merger plugin is that it cannot retrieve data from the object editor.
Better tools exist for the purpose of object generation (not to mention maintainability):
GMSI (requires a different script/programming language)
Ceres
 
Last edited:
Level 12
Joined
Jan 30, 2020
Messages
875
Thanks for this information.

What the wc3 modding community has come up with over the years when I was away never ceases to amaze me.

It makes me think we were all a bunch of amateurs back in 2004. Hell with my very limited knowledge many used to come to me for advice as if I was a master of something.

Now I realize what true masters are. And I have discovered quite a few since my return.


I can see Ceres has been updated in February. I also noticed it can use a TypeScript to Lua transpiler. I plan to switch to TS for my next project, and I wonder how Ceres would compare to the TS template that @TriggerHappy recommended : cipherxof/wc3-ts-template

Anyways, I still need to understand Lua further before going back to a strongly typed scripting language, as Lua really makes me feel insecure with its obscene type tolerance. I will also have to experiment with these tools as there is so much information to assimilate for the novice I have become.

Now about tool chains like Ceres, I suppose they can easily read / convert all wc3 maps/mpqs object files?
My concern is about my current map :

I took my old map in the state of development it was back in 2004, and started changing / improving it from there. And although it is so different from the original today, and completely converted to Lua, there are strange things happening in this map that I can not trace, although the map overall works perfectly.

The most relevant example is the fact that my map completely refuses to play weathereffects. The original map used to do it in 2004, but I tested it yesterday and it was unable to do it. So I guess my map inherited this from its ancestor as it used the base map file.
The problem is that to make my map uncommon back in the days, I was heavily relying on slk modifications, and I start to believe that there are settings I messed up with that became incompatible with the many patches wc3 has known since.

But I can't seem to trace the origin of the issue, and I wonder if there isn't a hidden setting somewhere that I can not access with World Editor.

You know, the same issue as when you use an edited AbilityData.slk or metadata to edit some ability properties, and then go back to the default wc3 setup with no custom SLK, then the changed settings are still there, but they do not show in WE.

Any idea if using something like Ceres would allow me to find out all settings lying in my object files that WE cannot show me ?
 
Status
Not open for further replies.
Top