1. We have added a Gift Upgrades feature that allows you to gift an account upgrade to another member, just in time for the holiday season. You can see the gift option when going to the Account Upgrades screen, or on any user profile screen.
    Dismiss Notice

Adding xml tags that work through Lua (eg, policy-dependent units & buildings)

Discussion in 'Civ5 - Modding Tutorials & Reference' started by Pazyryk, Dec 19, 2011.

  1. Pazyryk

    Pazyryk Deity

    Joined:
    Jun 13, 2008
    Messages:
    3,584
    If you want to do this through DLL rather than Lua, see Adding new XML Tags/Tables to work through the DLL.

    Let's say you want a simple policy prerequisite to build a building (there isn't one in the base game).

    You can add columns to existing core tables via SQL. Here's the code you need in an SQL file:

    Code:
    ALTER TABLE Buildings ADD COLUMN 'PrereqPolicy' TEXT DEFAULT NULL;
    SQL is added exactly as you add XML files (as an OnModActivated). Just make sure that the above file runs before your XML where you are using the new "PrereqPolicy" tag.

    Now you need to add some Lua code to tell the dll what to do with this new table column:
    Code:
    GameEvents.PlayerCanConstruct.Add(
    function(iPlayer, buildingTypeID)
    	local prereqPolicy = GameInfo.Buildings[buildingTypeID].PrereqPolicy
    	if prereqPolicy then
    		local player = Players[iPlayer]
    		local policyID = GameInfo.Policies[prereqPolicy].ID
    		if not player:HasPolicy(policyID) then
    			return false
    		end
    	end
    	return true
    end)
    That's it! You can now use this new tag to make any building construction dependent on having any particular policy, just like you use any other xml tag.

    Following the example above, you should be able to add PolicyPrereq tags to Units and Techs in a similar way using these GameEvents:

    GameEvents.PlayerCanTrain.Add(function(iPlayer, unitTypeID) ... end)
    GameEvents.PlayerCanResearch.Add(function(iPlayer, techTypeID) ... end)

    One suggestion: I actually add the above tag as "PrereqPolicy_paz". This is so that there are no problems down the road if the developers add a tag with this exact name (or perhaps a dll modder, once that is possible).

    Also note that the above prereq will not be added to the pedia. You'll have to do that yourself. Otherwise, there will be no indication in the game why the building cannot be built.

    **************************************************************
    Added 12/29


    OK, let's say you want to run a conditional test of your own using a tag "LuaReq". Some of you may remember many such tags in FFH (and mods thereof). They are extremely powerful because you can write short Lua functions to create whatever condition you want.

    As above, you add another column to Buildings like this:

    Code:
    ALTER TABLE Buildings ADD COLUMN 'LuaReq' TEXT DEFAULT NULL;
    Now let's make a Monument conditional on something, say turn > 5 (you can do this in XML of course, but I do everything in SQL so it's much easier for me this way):

    Code:
    UPDATE Buildings SET LuaReq='Game.GetGameTurn() > 5' WHERE Type='BUILDING_MONUMENT';
    That works, but it's pretty limited. What you really want to do is this:

    Code:
    UPDATE Buildings SET LuaReq='RunUserTestFunction()' WHERE Type='BUILDING_MONUMENT';
    If RunUserTestFunction() returns true, then Monument can be built. If it reuturns false, then Monument cannot be built. (Example code below returns true when turn is > 5 and iPlayer == 0.) The code to make this all work for Buildings is below (adds both LuaReq and PrereqPolicy). The only thing you need to do is supply your own Lua condition test functions and call the compile function during game init (the very last line below). If you want to add LuaReq to other tables, hopefully you can use this as skeleton code to do it (be sure to add any Lua callback tags to the two tables on lines 2 and 3).

    Code:
    --add any tags and their tables to the two tables below in matching pairs (only for tags that "call" a Lua function)
    local luaCallbackTable =	{ "Buildings"}
    local luaCallbackTag =		{ "LuaReq"}
    ---------------------------------------------------------------
    -- Compile Lua callback text (run once at game init)
    ---------------------------------------------------------------
    local bLuaCallbacksCompiled = false
    local LuaCallback = {}	--will hold all lua functions (as function values) keyed by function text exactly as it appears in table
    args = {}	--loadstring always compiles in global environment, so use this global to hold arguments for function call
    
    function CompileTableLuaCallbacks()
    	-- this must run after functions defined!
    	print("Compiling table Lua callbacks...")
    	for i, callbackTable in ipairs(luaCallbackTable) do
    		local callbackTag = luaCallbackTag[i]
    		for item in GameInfo[callbackTable]() do
    			local functText = item[callbackTag]
    			if functText and not LuaCallback[functText] then
    				print("Table "..callbackTable..", tag "..callbackTag..", function "..functText)
    				local funct = assert(loadstring("return "..functText))
    				LuaCallback[functText] = funct
    			end
    		end
    	end
    	bLuaCallbacksCompiled = true
    end
    
    ---------------------------------------------------------------
    -- Functions for new tags added to tables (including Lua callbacks)
    ---------------------------------------------------------------
    -- Building requirements
    GameEvents.PlayerCanConstruct.Add(
    function(iPlayer, buildingTypeID)
    	local player = Players[iPlayer]
    	local building = GameInfo.Buildings[buildingTypeID]
    	local prereqPolicy = building.PrereqPolicy
    	if prereqPolicy then
    		local policyID = GameInfo.Policies[prereqPolicy].ID
    		if not player:HasPolicy(policyID) then
    			return false
    		end
    	end
    	local functText = building.LuaReq
    	if functText and bLuaCallbacksCompiled then
    		local funct = LuaCallback[functText]
    		args.iPlayer = iPlayer
    		args.buildingTypeID = buildingTypeID
    		if not funct() then	--!!! that was the function call, so make sure args holds whatever you need !!!
    			return false
    		end
    	end
    	--add any additional restrictions to buildings here
    	return true
    end)
    
    
    ---------------------------------------------------------------
    -- An example user defined function (can be in another file but must be same state)
    -- Note that any arguments must be passed through a global (I use args here)
    ---------------------------------------------------------------
    
    function RunUserTestFunction()
    	print("called RunUserTestFunction")
    	iPlayer = args.iPlayer
    	buildingTypeID = args.buildingTypeID
    	print(iPlayer)
    	print(buildingTypeID)
    	if Game.GetGameTurn() > 5 and iPlayer == 0 then
    		return true
    	end
    	return false
    end
    
    
    ---------------------------------------------------------------
    -- !!! Important !!! Put this somewhere in your program where it runs
    -- at game init (after all functions above have been defined)
    ---------------------------------------------------------------
    CompileTableLuaCallbacks()
    Edit: One correction, you should (in theory) be able to add an argument to a LuaReq function call. Just be aware that it will be compiled in a global environment. So ReqTurn(5) should work and ReqTurn(g) should work if g is a global, but ReqTurn(x) won't work if x is local. Of course, if the value you want is in a global, you can get it from within the function anyway (that's how I use args above) so I'm not sure if that will be useful. But the ability to supply a hard value would certainly be useful. For example, you could have many buildings call the same ReqTurn function, but each has a different turn requirement. Or you could require different gold levels in treasury. Or different total culture. Or... The possibilities are really endless. (I haven't actually tested this yet.)

    **************************************************************
    There were a bunch of "Can" game events added in patch 1.0.1.332. Here's the whole list:
    Code:
    (Lua) Added GameEvents.CityCanBuyAnyPlot(ownerID, cityID) (TestAll)
    (Lua) Added GameEvents.CityCanBuyPlot(ownerID, cityID, plotX, plotY) (TestAll)
    (Lua) Added GameEvents.CityCanCreate(ownerID, cityID, projectTypeID); (TestAll)
    (Lua) Added GameEvents.CityCanMaintain(ownerID, cityID, processTypeID); (TestAll)
    (Lua) Added GameEvents.CityCanPrepare(ownerID, cityID, specialistTypeID); (TestAll)
    (Lua) Added GameEvents.CityCanTrain(ownerID, cityID, unitTypeID); (TestAll)
    (Lua) Added GameEvents.PlayerAdoptPolicy(playerID, policyTypeID); (Hook)
    (Lua) Added GameEvents.PlayerAdoptPolicyBranch(playerID, policyBranchTypeID); (Hook)
    (Lua) Added GameEvents.PlayerCanAdoptPolicy(playerID, policyTypeID); (TestAll)
    (Lua) Added GameEvents.PlayerCanAdoptPolicyBranch(playerID, policyBranchTypeID); (TestAll)
    (Lua) Added GameEvents.PlayerCanConstruct(playerID, buildingTypeID); (TestAll)
    (Lua) Added GameEvents.PlayerCanCreate(playerID, projectTypeID); (TestAll)
    (Lua) Added GameEvents.PlayerCanEverReseearch(playerID, techtypeID); (TestAll)
    (Lua) Added GameEvents.PlayerCanMaintain(playerID, processTypeID); (TestAll)
    (Lua) Added GameEvents.PlayerCanPrepare(playerID, specialistTypeID); (TestAll)
    (Lua) Added GameEvents.PlayerCanResearch(playerID, techTypeID); (TestAll)
    (Lua) Added GameEvents.PlayerCanTrain(playerID, unitTypeID); (TestAll)
    (Lua) Added GameEvents.TeamSetHasTech(teamID, techID); (Hook)
    **************************************************************
    Edit 11/2012: Thanks to DonQuiche, we now have a complete wiki listing all of the GameEvents. (A few errors here and there, but on the whole it is an awesome resource...)
     
  2. Sneaks

    Sneaks Brooklyn Bum

    Joined:
    Oct 15, 2010
    Messages:
    1,877
    Location:
    NYC
    This is certainly a helpful little snippet. But seriously, give us some sneak peaks into what you are working on. I am practically jumping out of my seat after seeing all your code.
     
  3. Pazyryk

    Pazyryk Deity

    Joined:
    Jun 13, 2008
    Messages:
    3,584
    Here's a teaser from the 1st line of my mod's description: "You begin knowing only that you are a small tribe, belonging to one of three races, without name, leader or history." I still have about 10 items on the checklist before alpha release, and each is a full day of work. Perhaps 4 - 8 weeks away.

    Back on thread topic: I've also figured out a simple generic way to add "LuaReq" as a table column. So you add something like "ReqLuaExample()" as LuaReq for a building. The building can only be built if your function ReqLuaExample() returns a true value. I'll post this in the next couple days.
     
  4. Pazyryk

    Pazyryk Deity

    Joined:
    Jun 13, 2008
    Messages:
    3,584
    Added code for a new LuaReq tag to the original post. This allows you to specify any Lua function (that you supply) that must return true for a building to be buildable.
     
  5. Pouakai

    Pouakai It belongs in a museum. Moderator

    Joined:
    Jun 16, 2010
    Messages:
    7,158
    Location:
    Aotearoa
    Awesome work right here, free to use I suppose?

    Also, you wouldn't happen to know where I can find a tutorial on adding new tables, would you?
     
  6. Moriboe

    Moriboe King

    Joined:
    Nov 30, 2010
    Messages:
    659
    Location:
    Belgium
    This example code sure helped me a lot, thanks! :)

    I added building and unit restrictions based on the current state of world diplomacy, to create an alternative path to diplomatic victories (rather than buying everyone out). If interested, check here.
     
  7. Pazyryk

    Pazyryk Deity

    Joined:
    Jun 13, 2008
    Messages:
    3,584
    Yes, of course.

    No. I'll probably write a general SQL tutorial at some point that includes table creation (I don't do any of this in xml so I've forgotten how). I'll edit this post later with an example when I have access.
     
  8. Moriboe

    Moriboe King

    Joined:
    Nov 30, 2010
    Messages:
    659
    Location:
    Belgium
    @Pouakai: with some examples available, adding new tables in XML is pretty straightforward. You can look for instance at the one I posted in the "culture per population" topic, then look at CIV5Buildings.xml. You will see it's the same thing really.
     
  9. Pouakai

    Pouakai It belongs in a museum. Moderator

    Joined:
    Jun 16, 2010
    Messages:
    7,158
    Location:
    Aotearoa
    Thanks. My main concern is the lua telling it what to do.
     
  10. xxhe

    xxhe Prince

    Joined:
    Mar 10, 2008
    Messages:
    370
    Location:
    IN.
    Thank you Paz. Very good example! I have a further question here: how to make this policy requirement shown in tooltips (such as the one in techtree when our pointer hang over the buiding)?
     
  11. Pazyryk

    Pazyryk Deity

    Joined:
    Jun 13, 2008
    Messages:
    3,584
    Some of these you can do by modifying "Help" fields in the existing xml files. But others are generated "on the fly" within the UI Lua files. I haven't done a lot of this yet so you're going to have to figure it out on a case-by-case basis.
     
  12. Nutty

    Nutty Deity

    Joined:
    Mar 9, 2011
    Messages:
    3,178
    Gender:
    Male
    Location:
    Orange County, California, U.S.A.
  13. Pazyryk

    Pazyryk Deity

    Joined:
    Jun 13, 2008
    Messages:
    3,584
    There is a player:GetCurrentEra() at the wiki. I would assume that it returns current era ID as an integer, but I haven't used it.
     
  14. Nutty

    Nutty Deity

    Joined:
    Mar 9, 2011
    Messages:
    3,178
    Gender:
    Male
    Location:
    Orange County, California, U.S.A.
    You're right, it returns 0-6.

    What content type do you publish this lua as?


    EDIT:
    If it's not obvious what I'm trying to do... Your post above got me thinking I could replicate, in LUA, the variation by era of units (like workers and great people). But it could also be useful to, e.g., simply obsolete a unit/building by era rather than a specific tech. I imagine you could do some interesting things with tech subtrees that don't have prerequisites as such.

    But... I'm no good with LUA modding, and this isn't working:

    SQL:
    Spoiler :
    Code:
    ALTER TABLE Units ADD COLUMN 'UnitArtInfoEraVariationStartEra_RED' TEXT DEFAULT NULL;
    ALTER TABLE Units ADD COLUMN 'UnitArtInfoEraVariationStopEra_RED' TEXT DEFAULT NULL;
    
    -- Spanish knight
    INSERT INTO "Units" ('Type', 'Description', 'Civilopedia', 'Strategy', 'Help', 'Requirements', 'Combat', 'RangedCombat', 'Cost', 'Moves', 'Immobile', 'Range', 'BaseSightRange', 'Class', 'Special', 'Capture', 'CombatClass', 'Domain', 'CivilianAttackPriority', 'DefaultUnitAI', 'Food', 'NoBadGoodies', 'RivalTerritory', 'MilitarySupport', 'MilitaryProduction', 'Pillage', 'Found', 'FoundAbroad', 'CultureBombRadius', 'GoldenAgeTurns', 'IgnoreBuildingDefense', 'PrereqResources', 'Mechanized', 'Suicide', 'CaptureWhileEmbarked', 'PrereqTech', 'ObsoleteTech', 'GoodyHutUpgradeUnitClass', 'HurryCostModifier', 'AdvancedStartCost', 'MinAreaSize', 'AirUnitCap', 'NukeDamageLevel', 'WorkRate', 'NumFreeTechs', 'RushBuilding', 'BaseHurry', 'HurryMultiplier', 'BaseGold', 'NumGoldPerEra', 'SpreadReligion', 'IsReligious', 'CombatLimit', 'RangeAttackOnlyInDomain', 'RangeAttackIgnoreLOS', 'RangedCombatLimit', 'XPValueAttack', 'XPValueDefense', 'SpecialCargo', 'DomainCargo', 'Conscription', 'ExtraMaintenanceCost', 'NoMaintenance', 'Unhappiness', 'UnitArtInfo', 'UnitArtInfoCulturalVariation', 'UnitArtInfoEraVariation', 'ProjectPrereq', 'SpaceshipProject', 'LeaderPromotion', 'LeaderExperience', 'DontShowYields', 'ShowInPedia', 'MoveRate', 'UnitFlagIconOffset', 'PortraitIndex', 'IconAtlas', 'UnitFlagAtlas', 'UnitArtInfoEraVariationStartEra_RED', 'UnitArtInfoEraVariationStopEra_RED')
    	SELECT	("UNIT_SPANISH_KNIGHT"), ("TXT_KEY_UNIT_SPANISH_KNIGHT"), "Civilopedia", "Strategy", "Help", "Requirements", "Combat", "RangedCombat", "Cost", "Moves", "Immobile", "Range", "BaseSightRange", "Class", "Special", "Capture", "CombatClass", "Domain", "CivilianAttackPriority", "DefaultUnitAI", "Food", "NoBadGoodies", "RivalTerritory", "MilitarySupport", "MilitaryProduction", "Pillage", "Found", "FoundAbroad", "CultureBombRadius", "GoldenAgeTurns", "IgnoreBuildingDefense", "PrereqResources", "Mechanized", "Suicide", "CaptureWhileEmbarked", "PrereqTech", "ObsoleteTech", "GoodyHutUpgradeUnitClass", "HurryCostModifier", "AdvancedStartCost", "MinAreaSize", "AirUnitCap", "NukeDamageLevel", "WorkRate", "NumFreeTechs", "RushBuilding", "BaseHurry", "HurryMultiplier", "BaseGold", "NumGoldPerEra", "SpreadReligion", "IsReligious", "CombatLimit", "RangeAttackOnlyInDomain", "RangeAttackIgnoreLOS", "RangedCombatLimit", "XPValueAttack", "XPValueDefense", "SpecialCargo", "DomainCargo", "Conscription", "ExtraMaintenanceCost", "NoMaintenance", "Unhappiness",
    			("ART_DEF_UNIT_U_SPANISH_KNIGHT"), "UnitArtInfoCulturalVariation", "UnitArtInfoEraVariation", "ProjectPrereq", "SpaceshipProject", "LeaderPromotion", "LeaderExperience", "DontShowYields", "ShowInPedia", "MoveRate", "UnitFlagIconOffset", "PortraitIndex", "IconAtlas", "UnitFlagAtlas", NULL, 5
    	FROM "Units" WHERE (Type = "UNIT_KNIGHT");
    INSERT INTO "Language_en_US" ( 'Tag', 'Text' )
    	VALUES ( 'TXT_KEY_UNIT_SPANISH_KNIGHT', 'Knight Spain' );
    INSERT INTO "Unit_AITypes" ('UnitType', 'UnitAIType')
    	SELECT ("UNIT_SPANISH_KNIGHT"), "UnitAIType"
    	FROM "Unit_AITypes" WHERE (UnitType = "UNIT_KNIGHT");
    INSERT INTO "Unit_ClassUpgrades" ('UnitType', 'UnitClassType')
    	SELECT ("UNIT_SPANISH_KNIGHT"), "UnitClassType"
    	FROM "Unit_ClassUpgrades" WHERE (UnitType = "UNIT_KNIGHT");
    INSERT INTO "Civilization_UnitClassOverrides" ( 'CivilizationType', 'UnitClassType', 'UnitType' )
    	VALUES ( 'CIVILIZATION_SPAIN', 'UNITCLASS_KNIGHT', 'UNIT_SPANISH_KNIGHT' );
    INSERT INTO "Unit_Flavors" ('UnitType', 'FlavorType', 'Flavor')
    	SELECT ("UNIT_SPANISH_KNIGHT"), "FlavorType", "Flavor"
    	FROM "Unit_Flavors" WHERE (UnitType = "UNIT_KNIGHT");
    INSERT INTO "Unit_FreePromotions" ('UnitType', 'PromotionType')
    	SELECT ("UNIT_SPANISH_KNIGHT"), "PromotionType"
    	FROM "Unit_FreePromotions" WHERE (UnitType = "UNIT_KNIGHT");
    INSERT INTO "Unit_ResourceQuantityRequirements" ('UnitType', 'ResourceType', 'Cost')
    	SELECT ("UNIT_SPANISH_KNIGHT"), "ResourceType", "Cost"
    	FROM "Unit_ResourceQuantityRequirements" WHERE (UnitType = "UNIT_KNIGHT");
    


    LUA:
    Spoiler :
    Code:
    GameEvents.PlayerCanTrain.Add(
    function(iPlayer, unitTypeID)
    	local player = Players[iPlayer]
    	local eraID = player:GetCurrentEra()
    	local eraStop = GameInfo.Units[unitTypeID].UnitArtInfoEraVariationStopEra_RED
    	local eraStart = GameInfo.Units[unitTypeID].UnitArtInfoEraVariationStartEra_RED
    	if eraStop then
    		if eraID >= eraStop then return false
    		end
    	end
    	if eraStart then
    		if eraID < eraStart then return false
    		end
    	end
    	return true
    end)
     
  15. Pazyryk

    Pazyryk Deity

    Joined:
    Jun 13, 2008
    Messages:
    3,584
    For SQL, some aesthetic issues with quotes (not fatal but ugly and confusing):

    Don't use double quotes. That's advice from the SQLite documentation itself.

    Change this: INSERT INTO "Unit_AITypes" ('UnitType', 'UnitAIType')
    To this: INSERT INTO Unit_AITypes (UnitType, UnitAIType)
    --you don't need any quotes for Tables and Columns that already have been defined.

    To be honest, I don't really understand what you are doing with this:

    INSERT INTO "Unit_AITypes" ('UnitType', 'UnitAIType')
    SELECT ("UNIT_SPANISH_KNIGHT"), "UnitAIType"
    FROM "Unit_AITypes" WHERE (UnitType = "UNIT_KNIGHT");

    But then, I never use very complicated SQL statements like this, so I might not understand something very basic. I've been able to add all of my game elements with a simple repetitive syntax that allows many (100s) of rows per INSERT statement. I'm actually fairly ignorant when it comes to more advanced SQL logic (I haven't needed it), which is I guess what you are doing here.


    I don't see any errors in the Lua. In fact, I'm pretty sure it has no errors. When I run into this situation, the first question I always ask is: Did my changes/additions get into the DB correctly? You should be looking at the DB everytime you alter it (with SQlite Manager), or else you will be wasting time troubleshooting something that is perfectly correct.

    I don't understand this part of your question. Do you mean: how do I add a Lua file?
     
  16. Nutty

    Nutty Deity

    Joined:
    Mar 9, 2011
    Messages:
    3,178
    Gender:
    Male
    Location:
    Orange County, California, U.S.A.
    The quotes are from Gedemon's R.E.D. modpack. It works, so I have not played with them.

    Again, from Gedemon. It's the same thing for most of the entries. I'm making a copy of the rows where UNIT_KNIGHT is the UnitType, and changing it to UNIT_SPANISH_KNIGHT instead. So in this case, UNIT_SPANISH_KNIGHT gets 2 rows for 2 UnitAITypes, just like UNIT_KNIGHT does, one for UNITAI_DEFENSE and one for UNITAI_FAST_ATTACK.

    The unit is my own with some art I've been playing with, but the SQL entries are a copy-paste job. The unit itself works fine. The only thing I added to the SQL that was at all different from my usual setup was the first 2 lines, and the references to them in the add to the Units table. The columns are added successfully, and the entries for those columns are added successfully.

    Thanks for taking a look... it's certainly simple enough, and I can't see why it wouldn't be working. To the extent I can bend FireTuner to my will, it looks like everything is working. But I can still train a unit before the 'UnitArtInfoEraVariationStartEra_RED' and after the 'UnitArtInfoEraVariationStopEra_RED'.

    The question was basically whether this is using content type "InGameUIAddin."

    I know the state of LUA modding has changed since Kael's guide came out. My understanding is no one makes changes to InGame.lua or InGame.xml anymore. Is this incorrect? I've hardly used LUA, and never in CiV, so I'll go take a look at some tutorials and/or recent prior art.

    Thanks again, Pazyryk!
     
  17. Pazyryk

    Pazyryk Deity

    Joined:
    Jun 13, 2008
    Messages:
    3,584
    I see. I tend to delete everything and re-add. It's just easier for me to keep it straight in my head that way.

    Put a print statement in there so you know exactly what values Lua sees when it is called, or if it is being called at all.

    EaMain.lua is added as "InGameUIAddin", yes, with VFS=false. Then I have EaInit.lua, EaFunctions.lua, EaAI.lua, etc., all of which are included by "include" statements in EaMain.lua and have VFS=true.

    No need anymore to worry about InGame.lua/InGame.xml.
     
  18. Catalonia

    Catalonia Warlord

    Joined:
    Jan 4, 2012
    Messages:
    118
    And can I do it in a XML file?
     
  19. Pazyryk

    Pazyryk Deity

    Joined:
    Jun 13, 2008
    Messages:
    3,584
    I don't know if you can add a column in XML or not. Maybe someone else has an answer.

    (I gave up XML modding a while ago. Too hard for me.;))
     
  20. Nutty

    Nutty Deity

    Joined:
    Mar 9, 2011
    Messages:
    3,178
    Gender:
    Male
    Location:
    Orange County, California, U.S.A.
    Sure, but if Firaxis patches something in that table, that way the mod may just upgrade gracefully.

    Well, yeah, if you want to get technical about it. :hammer2: I have no idea why, but the LUA wasn't being executed. I set up a brand new mod, with almost the exact same setup, and suddenly it works. Very odd. :wallbash: Regardless...

    It works! :woohoo: The only issue I had was that the numbers in the new columns were being stored as strings (though I had no quotes surrounding them), and comparison operators like greater/less than don't coerce strings to equivalent numbers. So, tonumber() function to the rescue, and the darn thing works.

    Now. On to world domination! :mwaha:

    :nono: (smily overload!)



    :thanx:
     

Share This Page