Hard Light Productions Forums
FreeSpace Releases => Scripting Releases => Topic started by: X3N0-Life-Form on February 10, 2015, 11:07:24 am
-
Greetings, fellow modders
Earlier this year, I started working on a script capable of parsing text files written in the style of Freespace tables. This idea was to have a generic parser that would allow me to read config files for other scripts.
Source code is available here (https://raw.githubusercontent.com/X3N0-Life-Form/AVPoV/master/data/scripts/parse.lua).
How to use it:
Put parse.lua in data/scripts.
In data/tables/init-sct.tbm, under #Conditional Hooks:
$On Game Init: [[parse.lua]]
Call the function parseTableFile(filePath, fileName) on a $On Game Init: hook, and store its results in a variable. The resulting data is basically a big multi-dimensional lua table:
Note: the things in yellow can be change to whatever you want.
- Categories: Begin with #A name, end with #End.
#Ship Classes is accessed by tableObject['Ship Classes'] - Entries: Begin with $Name: some name.
$Name: GTF Ulysses is access by tableObject['Ship Classes']['GTF Ulysses'] - Attributes: Single line that begins with $attribute name: some value.
$Hitpoints: 180 is accessed by tableObject['Ship Classes']['GTF Ulysses']['Hitpoints']['value'], which will have a value of 180.
Note: you can also have an array of values, such as $Hitpoints: 340, 300, 260, 220, 180, which are then access by their index: tableObject['Ship Classes']['GTF Ulysses']['Hitpoints']['value'][0] will return a value of 340. - Sub-attributes: Single line that begins with +sub attribute name: some value.
+Armor: None will be accessed as tableObject['Ship Classes']['GTF Ulysses']['Hitpoints']['sub']['Armor'], and will have a value of "None".
Note : Sub-attributes can also have an array of values.
Since this structure is a bit difficult to manipulate, I recommend splitting that big blob into sub tables or objects or whatever you feel comfortable with. Note that the script doesn't check the type of the parsed data, or whether a required attribute is present or not.
Examples:
I currently have 3 different scripts that use this parser for their config data, so here are a few code samples on how to use it. Note: these are code samples, meaning that they are missing several vital components.
mission-wide ship variant
Here we have a fairly simple table, with multiple categories, each entry has a single attribute, "Variant" with an optional sub-attribute, "Wing". The script function takes a category name, then processes each entry in that category.
Table:
#12th Vasudan BG
; Hatshepsut class
$Name: Apep
$Variant: Combat
; Typhon class
$Name: Pharaoh
$Variant: Combat Refit
; Sobek class
$Name: Blade
$Variant: Standard
+Wing: 2
#End
#A01.fs2
; Rakshasa class
$Name: Haagenti
$Variant: Strike Cruiser
#End
Script:
shipVariantMissionsTable = parseTableFile("data/config/", "ship_variant_missions.tbl")
function setShipVariants(categoryName)
if not (shipVariantMissionsTable[categoryName] == nil) then
for shipName, attributes in pairs(shipVariantMissionsTable[categoryName]) do
local variantName = attributes['Variant']['value']
-- if this is a single ship
if (attributes['Variant']['sub']['Wing'] == nil) then
setVariant(shipName, variantName)
else -- or if this is a wing
local wingSize = attributes['Variant']['sub']['Wing']
for i = 1, i <= wingSize, i = i + 1 do
setVariant(shipName.." "..i, variantName)
end
end
end
else
ba.warning("[shipVariantMissions.lua] Could not find entry "..categoryName)
end
end
auto ssm strikes
Here we a table with a single category. Each entry has two required attributes, "Type" and "Cooldown", one of which accepts either a single value or a list of values, and an optional attribute, "Default Seeking Algorithm". The script sample splits the parsed data into a bunch of one-dimensional tables to make them easier to use afterwards.
Table:
#Automated Strikes
$Name: rr-barrage ; required
$Type: Shivan SSM Barrage ; required, must match ssm.tbl entry
$Cooldown: 22 ; required
$Default Seeking Algorithm: round-robin ; optional, defaults to list
$Name: moloch-std
$Type: Shivan SSM Strike
$Cooldown: 24, 20, 17, 15, 13
$Name: moloch-std-insane
$Type: Shivan SSM Strike
$Cooldown: 13
$Name: moloch-std-hard
$Type: Shivan SSM Strike
$Cooldown: 15
$Name: moloch-std-medium
$Type: Shivan SSM Strike
$Cooldown: 17
$Name: moloch-std-easy
$Type: Shivan SSM Strike
$Cooldown: 20
$Name: moloch-std-very-easy
$Type: Shivan SSM Strike
$Cooldown: 24
#End
Script:
auto_ssm_table = parseTableFile(auto_ssm_filePath, auto_ssm_fileName)
dPrint_autoSSM(getTableObjectAsString(auto_ssm_table))
local id = 0
for name, attributes in pairs(auto_ssm_table['Automated Strikes']) do
-- record the strike's id
strike_info_id[id] = name
dPrint_autoSSM("Name="..name.."\n")
-- for each attribute
for attribute, prefix in pairs(attributes) do
value = prefix['value']
if not (type(value) == 'table') then
dPrint_autoSSM("attribute="..attribute.."; value="..value.."\n")
else
local str = ""
for index, val in pairs(value) do
str = str..val.." "
end
dPrint_autoSSM(str.."\n")
end
-- store this attribute in the relevant array
if (attribute == "Type") then
strike_info_type[name] = value
elseif (attribute == "Cooldown") then
strike_info_cooldown[name] = value
elseif (attribute == "Default Seeking Algorithm") then
strike_info_seeker_algo[name] = value
else
ba.warning("[autoSSM.lua] Unrecognised attribute "..attribute.."\n");
end
end
-- increment id count
id = id + 1
end
I am open to suggestions, remarks, questions regarding both this script and the way it is presented in this thread (in other words: I'm not sure if I'm explaining things properly here).
-
I'm curious what you're using this for.
-
I'm planning on using it for two things right now: an automated SSM strike framework that's still in the works, and for the ship variant script I released earlier this year.
I figured that since I would have at least two data files I need to parse, and that the existing parsing logic and format of the ship variant thing was crap, I might as well rewrite a generic parser, standardize my script data a bit and make it easier to read and use for FSO modders. That way, I could re-use the parsing logic for whatever I want in the future.
-
Neat. Axem should take note of this for his scripts like System Viewer and Journal... (Yeah, Axem, I said it again. I hate your JSON tables. :p )
-
Yeah, it would be simpler for people to edit but if I did make a switch over, I'd have to ask for a way to put data into numerical arrays real easy.
For instance defining the color of something would be easier to go
$Color: 128,128,128,192
rather than
$Color:
+R: 128
+G: 128
+B: 128
+A: 192
So if there where comma delimiting allows entries to go into a numerical based table, that would be so neat.
-
I'll add that to the TODO list then.
-
:bump:
Updated the script so that it stuffs comma delimited values into tables.
-
Okay, I have a few questions now on how it works with regards to sub-attributes.
So you have this...
$Attribute2: attribute 2 value
+sub attribute: sub value
which is supposed to generate this...
tab['entry name']['Attribute2'] = attribute 2 value
tab['entry name']['Attribute2']['sub']['sub attribute'] = sub value
Where does that 'sub' come from? Is that something the script generates?
And I'd like to be able to do this...
$AI:
+MinCloak: 50
+ActionTimeout: 10
Where it would generate...
tab['entry name']['AI'] = table (object only)
tab['entry name']['AI']['MinCloak'] = 50
tab['entry name']['AI']['ActionTimeout'] = 10
Possible maybe?
-
Ugh, looks like I need to rethink my attribute/sub attribute handling a tiny bit. I don't have time to do that this week (or probably even next week), but the idea I have right now would be to have something like this:
$Attribute name: some value ==> table['entry name']['Attribute name']['value'] = some value
+sub1: other value ==> table['entry name']['Attribute name']['sub']['sub1'] = other value
+sub2: yet another value ==> table['entry name']['Attribute name']['sub']['sub2'] = yet another value
-
Alright, since I'm obviously not going to have much spare time to work on FSO modding stuff, I've decided to take 10-15 minutes of my time to try and cook up something.
The modified script basically work as described in the post above: $Attribute: value results in ['Attribute']['value'] = value.
Note that it's received rather extensive testing (read: "launching the game to see if something chokes up on parsing"), so I'm still flagging this as beta for now.
EDIT - yup, it seems to be pretty broken right now
EDIT 2 - Should have been fixorized now. I'm probably going to review the category system before pushing out a 1.0.
-
Bumping for 1.0 release, see first post (http://www.hard-light.net/forums/index.php?topic=89168.msg1776654#msg1776654).
-
If this had been available 4 years ago I probably would have used it for my ship save/load script instead of that mess I ended up coding myself.
When I think about it adding reversed read functions as write functions would be enough. The script already creates one large table for each ship anyway.