LeeS
Imperator
City Nearby Map Datas
City Nearby Map Datas Utility CFC Download
City Nearby Map Datas Utility CFC Download
Important:
- The discussion on use of this utility does not assume you are expert in manipulating complexly-structured lua tables, but it does assume you are familiar with basic table-scanning methods of using "pairs()" and "ipairs()"
- If you do not understand what an lua table is, nor how a scan through an lua-table works using either the "pairs()" method or the "ipairs()" method, then this utility is not for you.
Description:
- Performs all lua code logic and instructions for gathering data from the game-map within the 3-tile working-range of a single city:
- Units (Enemy, Friendly, etc)
- Map Resources
- Map Improvements
- Other Cities
- The data to be collected can be configured so that if you want your mod's main lua to only scan for nearby units, the code can be configured to only collect unit information. The same is true for Resources, Improvements, and Other Cities.
- The code allows collection of multiple types of data. So you can collect data only about Units and Improvements, or only about Units and Resources, or only about Resources, or only about Resources and Improvements, as examples.
- If no 'selection' for the type of data to be collected is made, the code defaults to collecting data for all four types specified in #1.
- Data is collected for an individual city into one 'giant' lua-table that has multiple lua sub-tables.
- For advanced users of lua-tables, documentation is provided here on all the subtable structures and the provided 'keys' and 'values' within these tables.
- For those not so versed in the use of complex lua-tables, "interface" routines are included as part of this system to make it simple for you to extract the data you want from the larger table of data
- Data is gathered for a single specified city.
- For lua code that needs to run through each of a player's cities in turn, you simply use the same data-collection routine(s) for each city in turn.
- This is actually no different efficiency-wise than writing all the lines for inspecting an individual city's plots within a larger loop through all of the player's cities.
- What this routine does is handle all the code busy-work of inspecting a city's nearby plots, while allowing your code to gather all information about those nearby plots that pertains to units, resources, improvements, and other cities.
- You should see some processing improvements as compared to scanning a city's plots first to look through for units, and then scanning the same city's plots for resources, and then scanning the same city's plots for Farms, and then scanning the same city's plots looking for Mines on Iron, for example.
- You will not see much if any processing speed difference as compared to only looking for at a city's plots for Improved Iron plots, for example.
- The utility also contains the code for a few general-use toolkit-type functions which you might find useful. These can be found here
How to Add the System to Your Mod:
- Download the Utility from the CFC Download Database: City Nearby Map Datas Utility CFC Download
- Unzip the utility's folder, and add file CityNearbyMapDatas.lua to your mod using ModBuddy's Add Exiting File menus.
- In Modbuddy, set file CityNearbyMapDatas.lua as ImportIntoVFS=true in the file's properties. (See Common Novice-Modder Mistakes -- "NOT GIVING DDS FILES AN "IMPORT INTO VFS=TRUE"" where there are detailed instructions under the spoiler for more detailed instructions)
- In your mod's main lua file, add the following line at the top:
Code:
include("CityNearbyMapDatas.lua")
- You can now make use of the utility's functions in your mod's main lua file
Some Notes About the Download and the Files Within It:
- The download contains two files within an LUA folder:
- CityNearbyMapDatas.lua
- This is the actual utility and all its code.
- This is the only file you actually need in any of your mods
- DO NOT makes any changes whatever to the code within this file.
- Lua Script1.lua
- This is an example of how to make use of the utility within the lua-file of your mod.
- It is set up to make various print statemenet to the game's lua.log but not otherwise actually do anything
- It contains several different examples of how to apply various functions that are part of the utility
- As Packaged, the utility is a fully functioning mod that you can copy into your game's MODS folder, and enable.
- The mod is set to allow it to be added to a game in progress with no ill effects. You can activate the mod, load a game in progesss, and see the effects in the game's lua log. Other than the fact the code makes a lot of print statements into the lua log there is no other affect of the example usage of the utility.
- CityNearbyMapDatas.lua
- The download contains one file within an Instructions folder:
- ListOfFunctions.lua
- This file is meant to be a quick reference to the various functions you can use in relation to the utility, and has no other purpose.
- The file is no way activated by the mod and has no effect whatever on the game.
- This file is meant as an additional quick-reference in your programming, and is not meant to be added to any of your actual mods.
- You do not need this file to be part of your mod in order for the utility to work
- ListOfFunctions.lua
- The download contains one file within a ToolkitFiles folder:
- ToolkitFiles.lua
- This file contains a few general toolkit functions that you can use in your other mods without needing the utility.
- The file is in no way activated by the mod and has no effect whatever on the game.
- This file is meant for your convenience in your other mods if you want to make use of the general toolkit-type functions mentioned elsewhere in this thread. (just add the file to a mod, set it as ImportIntoVFS=true, and add an "include" statement into your mod's lua-code)
- You do not need this file to be part of your mod in order for the utility to work.
- ToolkitFiles.lua
Basic Use of the Utility:
- The utility gathers map-related data near an individual city, so to use the utility you must program your lua to run the utility's primary function for each city where you want to collect data.
- Since the utility collects the map-related data pertaining to the specified city and places the results into an lua table, you need to call the primary function of the utility as like:
Code:
local tNearbyDatas = GetCityMapDatas(pCity)
This would store all the results of the data collection into an lua-table called tNearbyDatas. Thereinafter whenever we want to grab some part of the collected data back out of this lua-table, we must reference table tNearbyDatas.- It does not matter what we call the table where we collect the city's nearby map data. We could just as easily call the table "Cheeseburgers", as like this:
Code:
local Cheeseburgers = GetCityMapDatas(pCity)
- We just have to be consistent in how we refer to the table where the city's nearby map data is collected.
- Either of these two methods for "naming" the city's table of collected map-data would work:
Code:local Cheeseburgers = GetCityMapDatas(pCity) if Cheeseburgers.CityResource ~= nil then print(Cheeseburgers.CityResource) end
orCode:local tNearbyDatas = GetCityMapDatas(pCity) if tNearbyDatas.CityResource ~= nil then print(tNearbyDatas.CityResource) end
Note that in both examples the naming used within a single example is consistent throughout the example
- It does not matter what we call the table where we collect the city's nearby map data. We could just as easily call the table "Cheeseburgers", as like this:
- For clarity's sake I will always use tNearbyDatas as the table where a single city's nearby map data is collected.
Primary Function of the Utility: GetCityMapDatas(pCity)
- Function Name: GetCityMapDatas()
- Required Argument:
- City Object in place of variable "pCity", as in:
Code:
GetCityMapDatas(pCity)
- No other arguments are required, though optional arguments may be included.
- City Object in place of variable "pCity", as in:
- Optional Arguments: Up to 4 text-string arguments can be included AFTER the city-object argument, in any order.
- Each of these tells the code which type of data to collect.
- When no additional arguments are added, all data is collected
- The additional text-string arguments allowed are:
- "Units"
- "Resources"
- "Improvements"
- "Cities"
- As mentioned, these can be stated in any order following the city object.
- If any valid optional argument is used, then ONLY data that corresponds to those listed optional arguments will be collected.
- If oddball text-string data is included, such as "Lettuce", the code will ignore such, and the argument where such an oddball designation appears will be treated as if it did not exist.
- Note that when "Resources" is selected by default or by adding it as an active argument-selection, the plot of the city passed to the function will always get data collected for it if the city is located on a plot with a map resource.
- Example 'Call' Statements:
- Using only the required argument:
Code:
local tNearbyDatas = GetCityMapDatas(pCity)
- Gathering only data about units near the city:
Code:
local tNearbyDatas = GetCityMapDatas(pCity, "Units")
- Gathering only data about resources near the city:
Code:
local tNearbyDatas = GetCityMapDatas(pCity, "Resources")
- Gathering only data about resources and units near the city:
Code:
local tNearbyDatas = GetCityMapDatas(pCity, "Resources", "Units")
orCode:local tNearbyDatas = GetCityMapDatas(pCity, "Units", "Resources")
- Gathering only data about units near the city because "Resources" is mispelled:
Code:
local tNearbyDatas = GetCityMapDatas(pCity, "Rehorses", "Units")
orCode:local tNearbyDatas = GetCityMapDatas(pCity, "Units", "Rehorses")
- Gathering data about all data-types near the city because "Cheeseburgers" is not recognized as valid:
Code:
local tNearbyDatas = GetCityMapDatas(pCity, "Cheeseburgers")
In this case the code reverts to collecting all data because no valid limiting argument was stated.
- Using only the required argument:
- For Map Plot Information, Data is only collected about plots that adhere to the following rules:
- only plots that have a map resource, or a terrain improvement, or a unit, or a city are included
- are not being worked by some other city (whether of the same player or a different player)
- are not owned by some other player (except that some limited data is gathered about cities)
- For those not well-versed in using complex lua tables, a series of data-filtering functions is described here. All of these functions are included as an integral part of the utility.
- For advanced users of lua tables, the exact data and structuring of the date collected can be found here.
Using the Utility to Scan Near a Single City:
- For purposes of discussion, let's assume we want to give a civilization called CIVILIZATION_WHEATGRABBERS the ability to grab any unclaimed wheat tiles within the 3-tile-range of any newly founded city. We can use this utility to gather a list of all such plots, and give them to the player whenever they found a city.
- PlayerCityFounded seems like the best hook event to use, so for the purposes of this example we'll use that event as our lua-hook.
- Our code is thus as this:
Code:
local iWheatGrabberCivilization = GameInfoTypes.CIVILIZATION_WHEATGRABBERS local iWheatResource = GameInfoTypes.RESOURCE_WHEAT function WheatGrabberCityFounded(iPlayer, iCityX, iCityY) local pPlayer = Players[iPlayer] if pPlayer:GetCivilizationType() ~= iWheatGrabberCivilization then return end local pCity = Map.GetPlot(iCityX, iCityY):GetPlotCity() local iCityID = pCity:GetID() local tNearbyDatas = GetCityMapDatas(pCity, "Resources") local tUnClaimedWheat = GetCityResourcePlots(tNearbyDatas, iWheatResource, "UnclaimedPlots") if #tUnClaimedWheat > 0 then for k,pPlot in pairs(tUnClaimedWheat) do pPlot:SetOwner(iPlayer, iCityID) end end end GameEvents.PlayerCityFounded.Add(WheatGrabberCityFounded) print("Our Code for CIVILIZATION_WHEATGRABBERS PlayerCityFounded has loaded properly")
- I've used a function called GetCityResourcePlots() which I have not explained as yet. Info on how this function works as part of the utility is explained here.
- GetCityResourcePlots() is a data-handling routine that looks through the data collected by GetCityMapDatas() and returns a simpler lua table that holds only the type of information specified.
- The lua table returned by GetCityResourcePlots() will always be in a format where within each pair of data the 'k' is an integer and the 'v' is a plot object for an individual plot that met the desired conditions.
- The contents of the lua table returned will always be in the form of an array table.
- This portion of the code is the part you will normally have to come up with for your self:
Code:
if #tUnClaimedWheat > 0 then for k,pPlot in pairs(tUnClaimedWheat) do pPlot:SetOwner(iPlayer, iCityID) end end
This portion of the code is where the data acquired by this utility is actually used to create an effect, and will vary wildly from one mod creator to another
Using the Utility to Scan Near all of a Player's Cities:
- For purposes of discussion, let's assume we want to give a civilization called CIVILIZATION_WHEATGRABBERS the ability to get 1 culture every turn for every wheat plot they own that is within 3-tiles of any of their cities, regardless of whether they are working the wheat plot.
- We can use this utility to gather a list of all such plots, and give this extra culture to the player.
- However, since we are allowing 1 culture for every owned plot (not just those being worked) and two cities could potentially "grab" the same plot, we need to keep a running tally of all plots we have already given the culture for, and filter out any plots already processed.
- The utility has a function written to ease the mechanics of tracking just such issues. It is called FilterTableContents(), and details about it can be found here.
- I've also used the function called GetCityResourcePlots() again, though with slightly different settings. Info on how this function works as part of the utility is explained here.
- GetCityResourcePlots() is a data-handling routine that looks through the data collected by GetCityMapDatas() and returns a simpler lua table that holds only the type of information specified.
- The lua table returned by GetCityResourcePlots() will always be in a format where within each pair of data the 'k' is an integer and the 'v' is a plot object for an individual plot that met the desired conditions.
- The contents of the lua table returned will always be in the form of an array table.
- PlayerDoTurn seems like the best hook event to use, so for the purposes of this example we'll use that event as our lua-hook.
- Our code is thus as this:
Code:
local iWheatGrabberCivilization = GameInfoTypes.CIVILIZATION_WHEATGRABBERS local iWheatResource = GameInfoTypes.RESOURCE_WHEAT function WheatGrabberTurnFunction(iPlayer, iCityX, iCityY) local pPlayer = Players[iPlayer] if pPlayer:GetCivilizationType() ~= iWheatGrabberCivilization then return end local tMyWheatPlotsThisTurn = {} for pCity in pPlayer:Cities() do local tNearbyDatas = GetCityMapDatas(pCity, "Resources") local tCityWheatPlots = GetCityResourcePlots(tNearbyDatas, iWheatResource, "Plots") tCityWheatPlots, tMyWheatPlotsThisTurn = FilterTableContents(tCityWheatPlots, tMyWheatPlotsThisTurn) for Item,pPlot in pairs(tCityWheatPlots) do pPlayer:ChangeJONSCulture(1) end end end GameEvents.PlayerDoTurn.Add(WheatGrabberTurnFunction) print("Our Code for CIVILIZATION_WHEATGRABBERS WheatGrabberTurnFunction has loaded properly")
- This portion of the code is the part you will normally have to come up with for your self:
Code:
for Item,pPlot in pairs(tCityWheatPlots) do pPlayer:ChangeJONSCulture(1) end
This portion of the code is where the data acquired by this utility is actually used to create an effect, and will vary wildly from one mod creator to another - As a general rule when running through all of a player's cities, you want your code effects to be shown within the loop so that everything pertaining to an individual city is processed before the loop moves on to the next player city.
- Note that in the example shown, the variable tNearbyDatas is re-created in turn for each city as the loop runs through each of the player's cities in succession. This is both on purpose and the methodology needed.
- An alternative method is to make the processing for adding the culture after the scan through all cities is completed:
Spoiler :Code:local iWheatGrabberCivilization = GameInfoTypes.CIVILIZATION_WHEATGRABBERS local iWheatResource = GameInfoTypes.RESOURCE_WHEAT function WheatGrabberTurnFunction(iPlayer, iCityX, iCityY) local pPlayer = Players[iPlayer] if pPlayer:GetCivilizationType() ~= iWheatGrabberCivilization then return end local tMyWheatPlotsThisTurn = {} for pCity in pPlayer:Cities() do local tNearbyDatas = GetCityMapDatas(pCity, "Resources") local tCityWheatPlots = GetCityResourcePlots(tNearbyDatas, iWheatResource, "Plots") tCityWheatPlots, tMyWheatPlotsThisTurn = FilterTableContents(tCityWheatPlots, tMyWheatPlotsThisTurn) end if #tMyWheatPlotsThisTurn > 0 then local iNumWheat = #tMyWheatPlotsThisTurn pPlayer:ChangeJONSCulture(iNumWheat) end end GameEvents.PlayerDoTurn.Add(WheatGrabberTurnFunction) print("Our Code for CIVILIZATION_WHEATGRABBERS WheatGrabberTurnFunction has loaded properly")
Last edited: