1

I'm working on a game where a bunch of characters will be generated on the fly, based on some constraints defined either in the project or externally via mod files. I am using MoonSharp Lua (5.2) interpreter for interfacing with my C# code, and Lua tables to store the constraint presets. As an example:

require "Defaults"
AgePresets = {}

-- Single value
AgePresets.Newborn = 0

-- Simple ranges
AgePresets.Default = defaultAgeRange --referring to the Defaults require
AgePresets.Child = {1, 12} 
AgePresets.Teenager = {13, 19}
AgePresets.YoungAdult = {20, 29}
AgePresets.Adult = {30, 40}
AgePresets.MiddleAge = {40, 60} 
AgePresets.Senior = {61, 80}
AgePresets.Elder = {81, 99}
AgePresets.Methuselah = {100, 150}  
AgePresets.Methuselah2 = {150, 200}

-- Weighted ranges // again referring to previously defined elements to keep things concise
AgePresets.Tween = {
            {weight = 1, minmax = AgePresets.Teenager },
            {weight = 1, minmax = AgePresets.YoungAdult }
         } 

This works fine, but from an end-user point of view, there's a lot of unnecessary typing involved. We are clearly working on AgePresets here but it is still mentioned as a prefix before every member name.

I could of course define AgePresets as an array, like AgePresets = { Child = {}, Teenager = {} } but the problem with that is then I cannot refer to previously defined elements in the array.

This doesn't work:

AgePresets = {
    Child = {1,12},
    RefToChild = Child, //attempt to index a nil value exception
    Teen = {13,19}
}

What I ideally want to achieve is a clean, concise way for users to enter this data in, like in the first example but without having to put AgePresets. prefix before everything. How do I go about declaring a scope in a file such that all succeeding members defined in the file will be within that scope, while maintaining the ability to refer to other members defined previously in the scope?

TaylanK
  • 13
  • 3

2 Answers2

1
AgePresets = setmetatable({}, {__index = _G})

do
   local _ENV = AgePresets
   Newborn = 0
   Child = {1,12}
   RefToChild = Child -- this ref is Ok
   Teen = {13,19}
   YoungAdult = {20,29}
   Tween = {
      {weight = 1, minmax = Teen },
      {weight = 1, minmax = YoungAdult }
   }
   rnd = math.random(10)   -- global functions are available here
end

setmetatable(AgePresets, nil)
Egor Skriptunoff
  • 23,359
  • 2
  • 34
  • 64
  • Thanks a lot! I took the extra step of putting everything other than data definitions in string constants on the C# side, and using string formatter to procedurally build the appropriate Lua syntax based on file name. Now it looks just the way I wanted. :) – TaylanK Jun 20 '17 at 22:51
0

You can mix the two styles: table constructor for fields that don't need to reference variables that aren't in scope yet, followed by assignment statements for the rest.

I would do that unless the order of the fields in the code significantly enhanced comprehension.

Tom Blodget
  • 20,260
  • 3
  • 39
  • 72