Need some advice on Lua-Table Structuring

LeeS

Imperator
Joined
Jul 23, 2013
Messages
7,241
Location
Illinois, USA
I'm building a mod where if a city has a resource local to it, production of specified wonders and buildings is increased. So far in lua I have created lua-tables for Marble-Wonders, Marble-Buildings, Stone-Wonders, Stone-Buildings, Copper-Wonders, Copper-Buildings, Iron-Wonders, and Iron-Buildings. I 'populate' the k,v pairs in all these tables from a new DataBase table when the mod loads. Currently I am pulling the BUILDING_SOMETHING name from the BUILDINGCLASS_SOMETHING name, and using the BUILDING_SOMETHING name as my lua-table "key". But I have cases where the same building or wonder is affected by both Marble and Stone (hence the differing tables for Marble wonders and Stone wonders). But you can see the two main problems here:
  1. Boat-loads of lua-table creation lines if I fill-in all the lua-tables needed for all the existing game resources.
  2. Isn't very adaptable if mod-author-X* adds a RESOURCE_TIMBER to the game that appears on the game-map, and then adds <Row> entries in the new table <Resource_BuildingClassProductionModifiers> that I have added to the game.
Here is the table definition of the added DataBase table:
Spoiler :
Code:
	<Table name="Resource_BuildingClassProductionModifiers">
		<Column name="ResourceType" type="text" reference="Resources(Type)"/>
		<Column name="BuildingClassType" type="text" reference="BuildingClasses(Type)"/>
		<Column name="BuildingProductionModifier" type="integer" default="0"/>
		<Column name="WonderProductionModifier" type="integer" default="0"/>
	</Table>
And a sampling of the <Rows> as seen in the 'operating' part of the XML:
Spoiler :
Code:
	<Resource_BuildingClassProductionModifiers>
<!--	Marble Wonders	-->
<Row ResourceType="RESOURCE_MARBLE" BuildingClassType="BUILDINGCLASS_GREAT_LIGHTHOUSE" WonderProductionModifier="10" />
<Row ResourceType="RESOURCE_MARBLE" BuildingClassType="BUILDINGCLASS_GREAT_LIBRARY" WonderProductionModifier="10" />
<Row ResourceType="RESOURCE_MARBLE" BuildingClassType="BUILDINGCLASS_CIRCUS_MAXIMUS" WonderProductionModifier="10" />
<!-- Marble-affected Buildings -->
<Row ResourceType="RESOURCE_MARBLE" BuildingClassType="BUILDINGCLASS_COURTHOUSE" BuildingProductionModifier="10" />
<Row ResourceType="RESOURCE_MARBLE" BuildingClassType="BUILDINGCLASS_TEMPLE" BuildingProductionModifier="10" />
<Row ResourceType="RESOURCE_MARBLE" BuildingClassType="BUILDINGCLASS_UNIVERSITY" BuildingProductionModifier="10" />
	</Resource_BuildingClassProductionModifiers>
Here's the current operating version of the lua (note that I pulled all my debugging print statements out of the code as well as three or four other lines that weren't actually doing anything or were just comments clutter):
Spoiler :
Code:
gWonderProductionModiferBldg = GameInfoTypes.BUILDING_WONDER_PROD_MOD
gBuildingProductionModiferBldg = GameInfoTypes.BUILDING_BUILDING_PROD_MOD

gMarbleWonders = {}
gStoneWonders = {}
gCopperWonders = {}
gIronWonders = {}

gMarbleBuildings = {}
gStoneBuildings = {}
gCopperBuildings = {}
gIronBuildings = {}

--xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
--xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx Construct Needed Wonder and Building Modifier Data LUA Tables on Game Load xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
--xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx


function InsertBuildingForBuildingClassIntoTable(sTableName, sBuildingClassType, iProductionModifier)
	--get building(s) for buildingclass
	for row in GameInfo.Buildings() do
		local sBuildingName = tostring(row.Type)
		local sBuildingClassName = tostring(row.BuildingClass)
		if sBuildingClassName == sBuildingClassType then
			sTableName[sBuildingName] = iProductionModifier
		end
	end
end




for row in GameInfo.Resource_BuildingClassProductionModifiers() do
	local sResourceType = tostring(row.ResourceType)
	local sBuildingClassType = tostring(row.BuildingClassType)
	local iBuildingProductionModifier = row.BuildingProductionModifier
	local iWonderProductionModifier = row.WonderProductionModifier

	if sResourceType == "RESOURCE_MARBLE" then
		if iWonderProductionModifier ~= 0 then
			InsertBuildingForBuildingClassIntoTable(gMarbleWonders, sBuildingClassType, iWonderProductionModifier)
		else InsertBuildingForBuildingClassIntoTable(gMarbleBuildings, sBuildingClassType, iBuildingProductionModifier)
		end
	elseif sResourceType == "RESOURCE_STONE" then
		if iWonderProductionModifier ~= 0 then
			InsertBuildingForBuildingClassIntoTable(gStoneWonders, sBuildingClassType, iWonderProductionModifier)
		else InsertBuildingForBuildingClassIntoTable(gStoneBuildings, sBuildingClassType, iBuildingProductionModifier)
		end
	elseif sResourceType == "RESOURCE_COPPER" then
		if iWonderProductionModifier ~= 0 then
			InsertBuildingForBuildingClassIntoTable(gCopperWonders, sBuildingClassType, iWonderProductionModifier)
		else --InsertBuildingForBuildingClassIntoTable(gCopperBuildings, sBuildingClassType, iBuildingProductionModifier)
		end
	elseif sResourceType == "RESOURCE_IRON" then
		if iWonderProductionModifier ~= 0 then
			InsertBuildingForBuildingClassIntoTable(gIronWonders, sBuildingClassType, iWonderProductionModifier)
		else InsertBuildingForBuildingClassIntoTable(gIronBuildings, sBuildingClassType, iBuildingProductionModifier)
		end
	end
end

--xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
--xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx Wonder and Building Production Modifier Code xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
--xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx




function CityProductionNameCheck(sTableName, iCityProduction)
	modifier = 0
	for k,v in pairs(sTableName) do
		if GameInfoTypes[k] == iCityProduction then
			modifier = v
		end
	end
	return modifier
end

function ResourceProductionModifierCheck(pCity, iCityProduction, iResource, sResourceTableName, sTableNameForPrinting)
	iModifierAmount = 0
	result = 0
	iModifierAmount = CityProductionNameCheck(sResourceTableName, iCityProduction)
	if iModifierAmount > 0 then
		if pCity:IsHasResourceLocal(iResource) then
			result = iModifierAmount
		else --removed print statement
		end
	end
	return result
end



function WonderResources(iPlayer)
	local pPlayer = Players[iPlayer]
	if pPlayer:GetCivilizationType() == GameInfoTypes["CIVILIZATION_BARBARIAN"] then return end
	if not pPlayer:IsAlive() then return end
	if pPlayer:IsMinorCiv() then return end
	for pCity in pPlayer:Cities() do
		local iCityBuildingProductionModifier = 0
		local iCityWonderProductionModifier = 0
		iCityProduction = pCity:GetProductionBuilding()
		--sCityProduction = tostring(pCity:GetProductionNameKey())
		if gPrintStatements == 1 then print(iCityProduction) end


		--xxxxxxxxxxxxxxxxxxx code for Marble enhanced wonders or buildings xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
		iCityWonderProductionModifier = ResourceProductionModifierCheck(pCity, iCityProduction, GameInfoTypes.RESOURCE_MARBLE, gMarbleWonders, "gMarbleWonders")
		iCityBuildingProductionModifier = ResourceProductionModifierCheck(pCity, iCityProduction, GameInfoTypes.RESOURCE_MARBLE, gMarbleBuildings, "gMarbleBuildings")

		--xxxxxxxxxxxxxxxxxxx code for Stone enhanced wonders or buildings xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
		iWonderModifierAddition = ResourceProductionModifierCheck(pCity, iCityProduction, GameInfoTypes.RESOURCE_STONE, gStoneWonders, "gStoneWonders")
		iCityWonderProductionModifier = iCityWonderProductionModifier + iWonderModifierAddition
		iBuildingModifierAddition = ResourceProductionModifierCheck(pCity, iCityProduction, GameInfoTypes.RESOURCE_STONE, gStoneBuildings, "gStoneBuildings")
		iCityBuildingProductionModifier = iCityBuildingProductionModifier + iBuildingModifierAddition

		--xxxxxxxxxxxxxxxxxxx code for Copper enhanced wonders or buildings xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
		iWonderModifierAddition = ResourceProductionModifierCheck(pCity, iCityProduction, GameInfoTypes.RESOURCE_COPPER, gCopperWonders, "gCopperWonders")
		iCityWonderProductionModifier = iCityWonderProductionModifier + iWonderModifierAddition
--		iBuildingModifierAddition = ResourceProductionModifierCheck(pCity, iCityProduction, GameInfoTypes.RESOURCE_COPPER, gCopperBuildings, "gCopperBuildings")
--		iCityBuildingProductionModifier = iCityBuildingProductionModifier + iBuildingModifierAddition

		--xxxxxxxxxxxxxxxxxxx code for Iron enhanced wonders or buildings xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
		iWonderModifierAddition = ResourceProductionModifierCheck(pCity, iCityProduction, GameInfoTypes.RESOURCE_IRON, gIronWonders, "gIronWonders")
		iCityWonderProductionModifier = iCityWonderProductionModifier + iWonderModifierAddition
		iBuildingModifierAddition = ResourceProductionModifierCheck(pCity, iCityProduction, GameInfoTypes.RESOURCE_IRON, gIronBuildings, "gIronBuildings")
		iCityBuildingProductionModifier = iCityBuildingProductionModifier + iBuildingModifierAddition

		pCity:SetNumRealBuilding(gWonderProductionModiferBldg, iCityWonderProductionModifier)

		pCity:SetNumRealBuilding(gBuildingProductionModiferBldg, iCityBuildingProductionModifier)

	end
end
GameEvents.PlayerDoTurn.Add(WonderResources)

print("At least the lua loaded")
So Here's the Big Question(s):
Do you have any suggestions for a better / more-adaptable method of building the lua-tables I need?
Is there a method to throw all the info I need into one lua-table that would be better than the one I am using? But would also allow (as example) Stone and Marble to both have an increasing affect on the same wonder or building?

If in order to give me a usable answer you need to look at the whole mod, let me know and I will add it as an attachment to the OP.

---------------------------------------------------------------
[footnote] * mod-author-X could very well turn out to be me at some point if I decide I'm up to that challenge.
 
Read the Resource_BuildingClassProductionModifiers table into a two dimensional array (technically an array of arrays), either

gWonderModifiers[sBuildingClassType][sResourceType] or gWonderModifiers[sResourceType][sBuildingClassType]

depending on if you want to answer the question "I'm building X, I have resource Y, what's the modifier" or "I have resource X, I'm building Y, what's the modifier"
 
Read the Resource_BuildingClassProductionModifiers table into a two dimensional array (technically an array of arrays), either

gWonderModifiers[sBuildingClassType][sResourceType] or gWonderModifiers[sResourceType][sBuildingClassType]

depending on if you want to answer the question "I'm building X, I have resource Y, what's the modifier" or "I have resource X, I'm building Y, what's the modifier"
After a bit of stumbling around and :wallbash: I got it to work on the lua internet demo page so that I can load information to and retrieve from a two-dimensional array. Now that I've figured out the basic required mechanics I can see how it will be way simpler than creating and tracking 187 different lua tables (or whatever the number would have been).

Though I think I might still make life a little easier on myself and use both a gWonderModifiers and a gBuildingModifiers table. I know, I know, a WONDER is a BUILDING and so on....but it makes it a little easier in my head to keep the two types of modifiers seperated, since I need to use <WonderProductionModifier> and <BuildingProductionModifier> in their appropriate conditions anyway.

And, as usual, THX for the guidance.
 
Back
Top Bottom