Results 1 to 13 of 13

Theory: LUA Inheritance Explained

  1. General Discussions Senior Member Modding Senior Member Dawn of War Senior Member  #1
    Why shout... Octopus Rex's Avatar
    Join Date
    Jul 2006
    Location
    UK

    Theory: LUA Inheritance Explained

    Rating: Competent to Advanced modders

    Inheritance is the major difference between LUAs and RGDs, but most people don't really understand its power, convenience and general effect on modding. Here I will lay the spine and guts of the Attribute Editor (AE) on the table and unlock many of its deeper secrets. To do this we need to look at the LUAs through a text editor.

    Inheritance

    The LUA file set for attribute editing has an inheritance-tree structure. Each file inherits the data from the last file and adds some more data of its own. At the root of the tree (or the top depending on which way you look at it) there are slightly different files with the extension NIL. These are essentially the same as LUAs but they don't necessarily have to inherit any data, they have the ability to start the branches of the tree off (although many NILs do inherit from other NILs).

    Open the AE and you will see how each file has one parent but may have many children, and how the trees open up.

    A child (also called a subtype) may not have less information that its parent. It may alter the data of any of the existing tables and extensions and it may add news ones too, but it may not remove any inherited from the parent. A good, simple example of inheritance is the "eldar_singing_spear_farseer.lua" weapon file. The only change/difference from its parent is the min and max damage that it does. The file inherits all the data from its parent (i.e. armour piercing types, recharge rate, morale damage) but it alters the min/max damage. Because these are the only differences they are the only lines that appear, the LUA doesn't need to re-iterate the information that it has inherited and it also doesn't need to specifically mention where this new information goes as all this is contained in the references at the beginning of the line.

    Code:
    ----------------------------------------
    -- File: 'weapon\eldar_singing_spear_farseer.lua'
    -- Created by: AttributeEditor v2.0
    -- Note: Do NOT edit by hand!
    -- (c) 2001 Relic Entertainment Inc.
    
    GameData = Inherit([[weapon\eldar_witchblade_farseer.lua]])
    MetaData = InheritMeta([[weapon\eldar_witchblade_farseer.lua]])
    
    GameData["area_effect"]["weapon_damage"]["armour_damage"]["max_damage"] = 161.25000
    GameData["area_effect"]["weapon_damage"]["armour_damage"]["min_damage"] = 143.75000
    
    
    MetaData["$METADATATAG"] = {desc = [[]], type = 7, category = [[]], dispval = [[]], isLocked = false, }
    MetaData["$METACOLOURTAG"] = 
    {
    
    }
    This is the entire LUA for the Singing Spear opened up in a text editor. First it has the file name at the top. Followed by a warning from Relic - ignore this warning, it's for Relic Staff and not for modders (cheers FinalDeath for clearing that up ) Next is the inheritance information (2 lines). This is the parent file. You can edit this if you the need arises - more on this later. Then we come to the damage information. Notice the path at the beginning which is basically a list of all the tables you would expand in the AE to get to this information. Last is the MetaData.

    If we decided to change the armour penetration values on the parent file then the changes would also apply to the Singing Spear. If however we changed the max/min damage on the parent it would not affect this file as this file has its own damage values as notated above.

    Referencing

    References are similar to ineritances but they refer to component parts of the LUA file instead. Think of it as a call for building blocks. Take the "research_ext" for example. In the AE you 'add' the "research_ext" to a building entity and all the elements appear. What happens in the text documents is slightly different, all you are adding is one line:
    Code:
    GameData["research_ext"] = Reference([[ebpextensions\research_ext.lua]])
    This calls the "research_ext.lua" which is found in the EBPextensions folder as stated in the reference.This is what the research_ext.lua looks like:
    Code:
    ----------------------------------------
    -- File: 'ebpextensions\research_ext.lua'
    -- Created by: AttributeEditor v2.0
    -- Note: Do NOT edit by hand!
    -- (c) 2001 Relic Entertainment Inc.
    
    GameData = Inherit([[ebpextensions\extension.nil]])
    MetaData = InheritMeta([[ebpextensions\extension.nil]])
    
    GameData["research_limit"] = 0.00000
    GameData["research_table"] = Reference([[tables\research_table.lua]])
    
    
    MetaData["$METADATATAG"] = {desc = [[]], type = 7, category = [[]], dispval = [[]], isLocked = false, }
    MetaData["$METACOLOURTAG"] = 
    {
    
    }
    MetaData["research_limit"] = {desc = [[]], type = 1, category = [[]], dispval = [[]], min = -340282346638528860000000000000000000000.000, max = 340282346638528860000000000000000000000.000, }
    MetaData["research_table"] = {desc = [[]], type = 4, category = [[]], dispval = [[]], }
    There's the obligatory info at the top and MetaData at the bottom. Notice how this is an LUA file and it too inherits data from a parent file, in this case "extension.nil", the base extension NIL file. The meat of the file is those two lines in the middle. Notice how that doesn't actually look like a full research_ext, notice how there is a reference line in there too. The second line in research_ext.lua calls "research_table" from the tables folder. Here it is:
    Code:
    ----------------------------------------
    -- File: 'tables\research_table.lua'
    -- Created by: AttributeEditor v2.0
    -- Note: Do NOT edit by hand!
    -- (c) 2001 Relic Entertainment Inc.
    
    GameData = Inherit([[tables\table.nil]])
    MetaData = InheritMeta([[tables\table.nil]])
    
    GameData["research_01"] = ""
    GameData["research_02"] = ""
    GameData["research_03"] = ""
    GameData["research_04"] = ""
    GameData["research_05"] = ""
    GameData["research_06"] = ""
    GameData["research_07"] = ""
    GameData["research_08"] = ""
    GameData["research_09"] = ""
    GameData["research_10"] = ""
    GameData["research_11"] = ""
    GameData["research_12"] = ""
    GameData["research_13"] = ""
    GameData["research_14"] = ""
    GameData["research_15"] = ""
    GameData["research_16"] = ""
    GameData["research_17"] = ""
    GameData["research_18"] = ""
    GameData["research_19"] = ""
    GameData["research_20"] = ""
    
    
    MetaData["$METADATATAG"] = {desc = [[]], type = 7, category = [[]], dispval = [[]], isLocked = false, }
    MetaData["$METACOLOURTAG"] = 
    {
    
    }
    MetaData["research_01"] = {desc = [[]], type = 2, category = [[]], dispval = [[]], baseType = [[research\research.nil]], stringType = 1, extensions = 0, shortnames = 0, }
    MetaData["research_02"] = {desc = [[]], type = 2, category = [[]], dispval = [[]], baseType = [[research\research.nil]], stringType = 1, extensions = 0, shortnames = 0, }
    MetaData["research_03"] = {desc = [[]], type = 2, category = [[]], dispval = [[]], baseType = [[research\research.nil]], stringType = 1, extensions = 0, shortnames = 0, }
    MetaData["research_04"] = {desc = [[]], type = 2, category = [[]], dispval = [[]], baseType = [[research\research.nil]], stringType = 1, extensions = 0, shortnames = 0, }
    MetaData["research_05"] = {desc = [[]], type = 2, category = [[]], dispval = [[]], baseType = [[research\research.nil]], stringType = 1, extensions = 0, shortnames = 0, }
    MetaData["research_06"] = {desc = [[]], type = 2, category = [[]], dispval = [[]], baseType = [[research\research.nil]], stringType = 1, extensions = 0, shortnames = 0, }
    MetaData["research_07"] = {desc = [[]], type = 2, category = [[]], dispval = [[]], baseType = [[research\research.nil]], stringType = 1, extensions = 0, shortnames = 0, }
    MetaData["research_08"] = {desc = [[]], type = 2, category = [[]], dispval = [[]], baseType = [[research\research.nil]], stringType = 1, extensions = 0, shortnames = 0, }
    MetaData["research_09"] = {desc = [[]], type = 2, category = [[]], dispval = [[]], baseType = [[research\research.nil]], stringType = 1, extensions = 0, shortnames = 0, }
    MetaData["research_10"] = {desc = [[]], type = 2, category = [[]], dispval = [[]], baseType = [[research\research.nil]], stringType = 1, extensions = 0, shortnames = 0, }
    MetaData["research_11"] = {desc = [[]], type = 2, category = [[]], dispval = [[]], baseType = [[research\research.nil]], stringType = 1, extensions = 0, shortnames = 0, }
    MetaData["research_12"] = {desc = [[]], type = 2, category = [[]], dispval = [[]], baseType = [[research\research.nil]], stringType = 1, extensions = 0, shortnames = 0, }
    MetaData["research_13"] = {desc = [[]], type = 2, category = [[]], dispval = [[]], baseType = [[research\research.nil]], stringType = 1, extensions = 0, shortnames = 0, }
    MetaData["research_14"] = {desc = [[]], type = 2, category = [[]], dispval = [[]], baseType = [[research\research.nil]], stringType = 1, extensions = 0, shortnames = 0, }
    MetaData["research_15"] = {desc = [[]], type = 2, category = [[]], dispval = [[]], baseType = [[research\research.nil]], stringType = 1, extensions = 0, shortnames = 0, }
    MetaData["research_16"] = {desc = [[]], type = 2, category = [[]], dispval = [[]], baseType = [[research\research.nil]], stringType = 1, extensions = 0, shortnames = 0, }
    MetaData["research_17"] = {desc = [[]], type = 2, category = [[]], dispval = [[]], baseType = [[research\research.nil]], stringType = 1, extensions = 0, shortnames = 0, }
    MetaData["research_18"] = {desc = [[]], type = 2, category = [[]], dispval = [[]], baseType = [[research\research.nil]], stringType = 1, extensions = 0, shortnames = 0, }
    MetaData["research_19"] = {desc = [[]], type = 2, category = [[]], dispval = [[]], baseType = [[research\research.nil]], stringType = 1, extensions = 0, shortnames = 0, }
    MetaData["research_20"] = {desc = [[]], type = 2, category = [[]], dispval = [[]], baseType = [[research\research.nil]], stringType = 1, extensions = 0, shortnames = 0, }
    Once again we have the usual info at the top and this time a substantial amount of MetaData at the bottom. Also, notice how even this table inherits information from a parent again too. The meat of the file is those 20 entries in the middle and those are what makes up that table that you are familiar with in the AE where you can select various researches in the drop boxes for your building. The large lump of MetaData at the bottom is what turns those fields into drop boxes and sets various values for them. Notice the part that says: [[research\research.nil]] - this is what causes only the researches to appear in the dropbox.

    So when all the pieces are brough together the research_ext is kind of like this: (of course without the colours and indents)
    Code:
    GameData["research_ext"] = Reference([[ebpextensions\research_ext.lua]])
      GameData["research_limit"] = 0.00000
      GameData["research_table"] = Reference([[tables\research_table.lua]])
        GameData["research_01"] = ""
        GameData["research_02"] = ""
        GameData["research_03"] = ""
        GameData["research_04"] = ""
        GameData["research_05"] = ""
        GameData["research_06"] = ""
        GameData["research_07"] = ""
        GameData["research_08"] = ""
        GameData["research_09"] = ""
        GameData["research_10"] = ""
        GameData["research_11"] = ""
        GameData["research_12"] = ""
        GameData["research_13"] = ""
        GameData["research_14"] = ""
        GameData["research_15"] = ""
        GameData["research_16"] = ""
        GameData["research_17"] = ""
        GameData["research_18"] = ""
        GameData["research_19"] = ""
        GameData["research_20"] = ""
    Looking more familiar now right? Research_ext is pretty simple though, combat_ext has many more references and tables.

    Like I said eariler, referencing is similar to inheritance. It has the same feature whereby it only needs to notate the changes from the original and the fact that it is referencing it. If a parent has refenced it already that it doesn't even need to that bit either.

    This is a real example of the research_ext taken from the Necron Energy Core LUA
    Code:
    GameData["research_ext"] = Reference([[ebpextensions\research_ext.lua]])
    GameData["research_ext"]["research_table"]["research_01"] = "research\\necron_night_bringer_research.lua"
    It calls the research_ext.lua with the first line, which in turn calls the research_table.lua but that goes without needing saying, and it states the one change it has made: it has put the night_bringer_research in to slot 01 of the table. This is the only change that it's made so other than calling the research_ext itself that's all that needs to appear in the LUA.

    In this way the LUA system is huge network of inter-referencing and inheriting files. The files all sit in simple folders, yes, that group together the different sections of files, but beneath the folder system the web is vast and intricate. The main point of this tutorial is for you to understand this concept as you don't really need to play around with it that much, it's just that it affects your files in ways you might not have expected (eg not being allowed to remove extensions that are inherited from the parent). Also, you can edit many many files at once with inheritance if you edit the correct parent file as the children may be using that information as well (although they may have their own - be careful!)Global changes are made much easier through inheritance.

    AE Symbols

    Those little symbols in the AE means things. On the left: circles denote LUAs, circles with a cross in denote an LUA that can't be edited yet and circles with a T in are NIL files.

    On the right: A tick means the info is inherited and unchanged. A cross means that field is changed. A plus means a new extension has been added. And a star thing means that something inside this table/extension has been changed, but not the table/extension itself.

    Editing Inheritance

    Why would you do this? Ok, you don't need to do this very often at all but one example would be when you're creating a veteran marine squad, but you DON'T want it to inherit all the info from the Tac Marines, sure they're going to be similar and normally you would just create a child, but in this instance you've decided you'd rather they were autonomous from each other once created. Creating a new subtype in the AE will created a child, which is not what you want in this case. Creating a child from the space_marine_trooper.nil will leave you with a shitload of extensions to add before the EBPS in complete - lots of room for errors.
    Easiest solution:
    -close the AE (shock horror!)
    -copy and paste the Tac Marines LUA
    -rename it to veterans or whatever (don't forget the .lua extension)
    -open up the veteran LUA with a text editor
    -change the file name at the top to match
    -change both inheritance lines to match those of the Tac Marines
    -save it and fire up the AE again.

    You will now have an identical copy in all but name, ready for editing without inheriting any changes you make to the Tac Marines.

    (in fact that example is wrong in so much as the new LUA will already have the correct inheritance as it is an exact copy of the Space Marine one - I can't really think of a useful example of why you'd edit inheritance so I'll just leave it anyway)

    Editing Tables and Extensions (adding slots etc)

    Why do this? Well, this is generally only really needed for pretty advanced modders because it has wide reaching effects. Take the research_ext: let's say you have a building that you want to put more than 20 reseraches on. Unlikely, but it may happen if you have tripled Tiered researches (i.e. Bionics 1,2 and 3). to get those extra researches on you can simply add extra slots (21 onwards) to the research_table.lua. You must be very careful to get it exactly right and to also add the MetaData too, anything missing or spelt wrong will cause the file to not load. DoW:Firestorm have added many many slots onto the "armour_piercing_table.lua" as they go way beyond the standard 14 armour types. My Codex Dreads mod adds a couple of slots onto the "weapon_table.lua" which allows me to give it all those juicy combos. These changes will affect EVERY appearance of that table as it's that table which is being called everytime. Also, you can input a default value for them all to use unless otherwise told and usually this can be done in the AE. One example is if you want to give the armour types more accurate descriptions on the units like in DoWpro; you can go direct to the armour type and edit the UCS link in there to link them all to custom text string (i.e Medium Building, Fortified Building Light Structure etc.). When you edit these tables make sure you keep your original and put the new one in the correct folder in YOURMOD's attrib folder, don't overwrite the DXP2 ones. This tutorial shows you how and why you might need to do this.

    Limitations

    Inheritance can catch you unawares. Sometimes things will change in the child files that you didn't expect. Sometimes the child will have an undesirable extension that you can't get rid of (although all the data on it can be changed to whatever you want). Also, if you are copying files and such the file will not load if the inheritance is screwed, if an extension is being altered in the child that is in fact missing from the parent or if the target parent doesn't exist. This can get annoying.

    So, that's how all this crazy shit works. Hope you were listening!
    Last edited by Octopus Rex; 27th Oct 07 at 4:31 PM.
    "Life is not full of successes, it is full of failures from which we learn" - Tony Benn
    Octopus Blog (14.02.10)DOW2 GridKeys
    DOW1 Modding Tutorial ListDOW2 Tactical Primer

  2. Modding Senior Member Dawn of War Senior Member  #2
    Father of Death Croaxleigh's Avatar
    Join Date
    Jun 2006
    Location
    A forgettable little corner of southwestern Kentucky
    Wow... very informative post. I've run into inheritance issues a time or two, when I go to change something in the AE (especially getting rid of something) and get that little warning saying that I can't do it because whatever it is comes from the inherited file.
    I has a Blurb. And one of those Tweeter things.
    Quote Originally Posted by roflmao
    I'd run with a shotgun to go hijack a private airplane and fly to Belgium. Nothing interesting ever happens in Belgium, so there's definitely no zombie apocalypse there.

  3. #3
    Aden
    Guest
    Great post, very informative. Gonna take a few reads for me to soak that up

    This couldn’t have come at a better time for me as I am in the process of creating a complete and working inheritance for a bunch of RGD files I dumped to lua’s using Corsix tools.

    I quick question for anyone who has done the same with corsix’s editor;
    When the lua files are created by the editor it seems to drop a hell of a lot more information (coding) than is actually necessary. The lines of coding that aren’t necessary all appear to have no value at all, all ending with "[[]]", therefore lacking any purpose as far as I can tell.

    Can anyone explain to me why dumping RGD files to lua files does this? And what the extra information is?
    My guess is that it is either the parent file info, or all the possible editable values, as see with the RGD file editor part of Corsix tools. But I’m pretty green so I’m probably way off.

    But more importantly, can I just delete the un-necessary info with note pad without damaging the file or any inherency?

    Thanks for another great read Rex

  4. General Discussions Senior Member Modding Senior Member Dawn of War Senior Member  #4
    Why shout... Octopus Rex's Avatar
    Join Date
    Jul 2006
    Location
    UK
    Aden: in fact it was your PM that was the inspiration for this tutorial. I figured it was about time someone got round to cracking this one. It was also Corsix who, without realising, challenged me to write it a long time ago.

    The RGD --> LUA thing is that the RGDs contain ALL the information, even the blank stuff, and do not have the inheritance info (I think, or at least the tools don't read it). When they AE burns them it takes into account the inheritance and burns it all onto one file. The LUAs only contain the changes as explained above, this makes them smaller and most likely quicker to load. When Corsix Tools dump to LUA it simply spews out ALL the info that's on the RGD, it doesn't read the inheritance or take it into account. The RGDs can work on their own, the LUAs cannot. The RGD editors have smaller load times because they only load one file at a time and don't need the inheritance (again, ALL the info is on the RGD), the AE loads several thousand because it needs all the inheritance info to fill in the blanks on all the files.

    Corsix: clarification please? RGDs are slightly more of a grey area for me.

  5. #5
    Aden
    Guest
    Here is an example of what I mean,

    Original file entry;

    GameData = Inherit([[abilities\guard_let_it_burn_child_1.lua]])
    MetaData = InheritMeta([[abilities\guard_let_it_burn_child_1.lua]])

    GameData["child_ability_name"] = "guard_let_it_burn_child_6"
    GameData["initial_delay_time"] = 15.00000


    MetaData["$METADATATAG"] = {desc = [[]], type = 7, category = [[]], dispval = [[]], isLocked = false, }
    MetaData["$METACOLOURTAG"] =
    {

    }
    Dumped RGD>Lua file entry; (spoiler tagged because its huge)

    Spoiler



    As you can see it's a bit of a difference. How much of that needs to be there and how much of that is a by-product of the dump process?




    Sorry Rex, didn't see your post until I had posted my second.

    Little ol' me inspired you, I'm touched dude

    Thanks again for the info m8.

  6. #6
    The 22nd Hyperspace Core Corsix's Avatar
    Join Date
    Sep 2004
    Location
    Oxford
    RGDs contain the full data tree (eg, after all inheritance has been applied). They also contain the name of the Reference()d file for each table, apart from GameData.

    My LUA dumper (IIRC) uses this Reference information to remove as much redundant data from the dumped LUAs as possible, but each file still Inherit()s from "" (blank/null file) as neither the name of the inherited file, nor the NILs themselves are present in the RGDs. The major hurdle is therefore rebuilding the NILs and the inheritance tree itself from the RGDs.

  7. #7
    Mystecore
    Guest
    @ Aden;

    Not sure if it'll help but I dumped the RGD>LUA, copied everthing after

    GameData = Inherit([[]])

    and pasted it into a fresh blank LUA I'd created in AE (between the inherit info and the metadata). Presto, working LUA.

  8. #8
    Aden
    Guest
    I have been doing it a little different than that Mystecore but with the same end result. I have been editing the new dumped RGD's>lua files with notepad and adding in the inherit info and the metadata at the top and bottom.

    It works well but it's very time consuming. The end result is the same basically.

    Your method sounds a bit more reliable (less chance of mistakes and such like). I'll try it that way and see if it's any quicker.

    Thanks for the info Mystecore.



    @ Corsix,

    Thanks for clarifying how the lua dump works. I am starting to understand this stuff... slowly but I'm getting there

  9. General Discussions Senior Member Modding Senior Member Dawn of War Senior Member  #9
    Why shout... Octopus Rex's Avatar
    Join Date
    Jul 2006
    Location
    UK
    Added a note about what the symbols in the AE mean.

  10. #10
    Senior Member horusheretic's Avatar
    Join Date
    May 2006
    Location
    United Kingdom
    heh, maybe we should try to understand a bit more about the meta data. i bet theres a few shiny things hidden under that.
    as it basically is a bunch of table info, it can sometimes help to know what some of it does when trying to get something changed.(like changing what entites can be used for execute ability as it only does IG with out changing table info)
    Tutorials_And_Helpful_Sites_Here <-link
    Want a 3d model commissioned? I may do so. Pm me!
    http://steamcommunity.com/groups/dow40k2-woa Join up for updates and view other members.

  11. General Discussions Senior Member Modding Senior Member Dawn of War Senior Member  #11
    Why shout... Octopus Rex's Avatar
    Join Date
    Jul 2006
    Location
    UK
    Yeah, more MetaData would be good definitely

    It's funny, as soon as we figured out that one about IG execute I always see all the drop boxes and think "oooh, what can I change in those too?" and then realise that nothing would be useful.

    However....I do have a few ideas...


  12. #12
    Member Jon383's Avatar
    Join Date
    Jul 2012
    Location
    Lithuania
    Hey.
    I have a very simple but bothersome issue.
    Everywhere I read is mentioned .nil files. No files, are clear, but the forums.
    And others find them. And I find a Corsix probably all the files but not .nil files.
    Please help me with this problem.

    Thanks in advance

  13. Modding Senior Member Tabletop Senior Member Boardwars Senior Member Forum Subscriber  #13
    Retired Compliance Fairy Gorb's Avatar
    Join Date
    Jul 2006
    Location
    In the past
    Corsix's Mod Studio does not create .NIL files. They are included with your Mod Tools installation, along with the .LUA files.
    I am an Iron Warrior! Iron Within, Iron Without!

Thread Information

Users Browsing this Thread

There are currently 1 users browsing this thread. (0 members and 1 guests)

     

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •