Simple Tuner Modifications

MouseyPounds

Prince
Joined
Nov 8, 2010
Messages
417
Location
Maryland, USA
I've always been one who wanted a little more information out of my Civ games. I want to know how stuff works and what the AI is doing and if I can change the things that bug me without screwing up my game; in other words, I'm a modder at heart. So I loved playing around in the Civ4 World Builder and Python Console to see what I could do, and now with Civ5 I'd like to do the same. Hence, I've decided to spend some quality time with the enigmatic Fire Tuner. And while the Tuner doesn't do everything that I would like, I've realized that we have quite a bit of freedom to change that. This brief tutorial will hopefully shed some light on the subject and perhaps inspire future modding efforts.

Introduction

If you've never used the Fire Tuner, there are a couple things you need to know. First, it's part of the SDK Download available for free on Steam. And second, to actually use it you need to set the "EnableTuner" option to 1 in your config.ini file which is located at the root of the Civ5 documents folder.

Once it has been enabled and Civ5 is running, you can simply launch the SDK and pick "Fire Tuner" from the menu and it will connect automatically. A connected Tuner will look something like this:



That can be mighty intimidating to a newbie modder but after poking around a bit I found that it's not that bad. It's really just a Console window and a bunch of configurable panels that let you do stuff. The Console lets you run arbitrary Lua commands similar to how the old Civ4 Python Console worked and all the Panels are just a barebones UI hiding some underlying Lua code; and all that code and even the Panels themselves are fully moddable. But before we mod, let's take a quick look around.

Early Exploration

The main caveat with the Lua console is that you can set it to various "States" to access different parts of the game. So if you want to run a function or access a variable from a running mod, you'd select the mod's name in the state dropdown menu first. Other than that the Console is pretty straightforward. If you want to test it, go ahead and switch to the "WorldView" state and type the following:

Code:
print(Players[0]:GetName())



The name of your civ's leader should then be printed out prefaced with "WorldView:" If you have logging turned on (another config.ini option) it will also be output to the Lua.log file in the Logs subdirectory of your Civ5 documents folder. Let's leave off the console for now though and get back to the main topic. That "Active Player" tab sure looks like a good place to start...



So what we have here are a bunch of buttons that appear to give things to the player and also some information such as how much gold and culture the player currently has. Hmm. Make sure your game has been saved and then go ahead and change the money value or award a tech and notice the immediate effects. Okay, nice. But what's the deal with this "Current Research ID?" I sure don't know all the tech IDs; it'd be pretty useful if the output would also show the tech name. And a field for the happy bucket might be useful too. Wouldn't it be nice if we could make such changes? Yes it would; but more importantly, "Yes we can." ;)

Hacking the Tuner

The first clues that we can change the functionality of the Tuner are that it has a "New Control" button next to the State dropdown and a "* New Panel *" tab at the end of the tab list. But before we start going crazy, let's back some stuff up. If you choose "Save Panel As" from the File Menu you'll see that all the panels are actually stored as ".ltp" files in the Debug subdirectory of the Civ5 Installation folder. Repeating for emphasis, they are in the Civ5 folder and not the SDK folder; I'm not sure what this means in terms of Steam updates but it's probably a good idea to do regular backups if you make any changes. In fact, we might as well back everything up somewhere safe right now. Additionally, for extra paranoia and because it serves as a useful example, let's actually save the panel under a new name. I chose "Active Player Plus.lua" but you can call it anything you want. Now we will reopen that file we just saved, which will add a second "Active Player" tab to the end of the list. Let's switch over to that one and start experimenting.



The first thing I'm going to do is rename my new panel so that I don't get too confused. So right-click anywhere in the blue bar below the tabs and choose "Edit Panel." This brings up a tiny "Panel Builder" window with a "Name" field, a slew of checkboxes, and some buttons. I'll change the Name to "Active Player Plus;" it doesn't have to match the filename but it's a good habit. The checkboxes allow you to restrict which Lua States the panel will be used with; "WorldView" should be the only one checked and we have no good reason to change that; BTW you can resize this window which makes it easier to work with the checkboxes since they aren't arranged alphabetically. The "On Enter" and "On Exit" buttons bring up additional windows where you can add Lua code. These code blocks are run when you switch to and away from the Panel respectively and would probably be useful for things like variable initialization and cleanup; for the purposes of this tutorial we'll leave them blank.



Right-clicking on one of the controls (e.g. the "Recalc Building Maint" button) shows us that we can actually Edit or Move that thing in addition to Copying and Deleting. So let's move it somewhere else like a little below the "Player 1 DoW" button. Being able to rearrange the panel at will is quite useful especially when you get String controls which overlap like the Gold/Culture boxes. Feel free to adjust the Culture one too to counteract this. Now let's edit something.

Keeping it simple, I'm gonna take the 1000 Culture button and make it a "5000 Culture" button. So I right-click it and choose Edit:



Well that's simple enough. I can change the name to "5000 Culture" and then change the 1000 to 5000 in the Lua code under the Action section. Note that you can hit the "Test" button right here and the Output will let you know if there was an error, but be warned that if there is no error it will affect the game. So go ahead and try it then check back in Civ5 to verify the 5000 Culture got added.

Now we'll do something a little more complicated and see if we can add a tech name indicator too. We could click the "New Control" menu and select a "String Control" but in this case I think it makes more sense to copy the "Current Research ID" control and modify that we'll probably use similar code. So let's right-click on it and "Copy," then right-click in a bare part of the window and choose "Paste Control." This gives us a box which we can move around and then click to place. I put it next to the control I just copied and then choose "Edit."



This seems pretty straightforward; the Name is the button label, there's a place for a Default value, and there are 2 code boxes for "Set" and "Get" with some Lua filled in. I'm going to change the name to "Tech Name" and leave the default as-is. Since I want this to be basically a read-only control (which can't actually be specified) I'll comment out the "Players..." line of the "Set" function so that it does nothing if the text gets edited. Now let's look at the "Get" function. Currently it gets the tech ID and stores it to a variable eCurrentTech and then returns this variable. What I want to do is lookup that ID and get the actual tech name and then return that instead. We also should add some error-checking since the tech ID is -1 when there is no actual research target. So I'll change the function to read:
Code:
function()
  local pPlayer = Players[Game.GetActivePlayer()];
  local eCurrentTech = pPlayer:GetCurrentResearch();
	 local rStr = "(None)"
	 if eCurrentTech >= 0 then
		  rStr = Locale.ConvertTextKey(GameInfo.Technologies[eCurrentTech].Description)
		end
  return rStr
end

After hitting OK, we should now see the tech name and if we go back into the game and switch techs, the tuner should update appropriately. Note that this isn't perfect and initially the field might remain blank; if this is the case you can force it to update by switching to another Panel and then back to "Active Player Plus." Additionally, we can't actually make the value read-only so you could actually click on the tech name and type something else. While that doesn't affect the game in any way because we made the "Set" function do nothing; you can always force a refresh as discussed previously to get the name back.

Although it won't really do anything, let's add a City List here too to illustrate how lists work. So either right-click in the open area or choose the "New Control" menu and then choose "Selection List."



This is a similar window to the other controls we've seen. The "Name" option and "Sort Alphabetically" checkbox should be self-explanatory but the code boxes may not be. "Populate List" creates the list itself by building and returning a table. If you don't want alphanumeric sorting you can arrange it however you want by how you order your table (I think.) For our purposes we will simply iterate over the list of player's cities and add those to the table with the following code:
Code:
function()
  local listItems = {}
    local pPlayer = Players[Game.GetActivePlayer()] 
  local c
    for c in pPlayer:Cities() do
      table.insert(listItems, c:GetName())
      end
  return listItems
end
Since the list is purely informational, you can leave the "On Selection" function as-is. Normally this would be used to process whatever value was clicked on. After hitting OK, you can place the list wherever you want; note that if you right-click the list-box after it is placed you actually get a resize command to help with fitting it onto the panel.

After rearranging things a bit more and adding some other "missing" controls, my "Active Player Plus" panel now looks like this:



I have attached the "Active Player Plus.ltp" file pictured above to this post. If you want to experiment with it, feel free to download, drop it into the Debug directory, and then Open it up in your Tuner. Note that despite the extension it is actually just an XML file which could be edited in a text editor which could be useful for fine-tuning the layout if you're sorta OCD about such things.

After I return from holiday travel I will do some more experimenting in this area; I'd love to be able to make versions of the "Selected City" and "Selected Unit" Panels that would easily work with any player's stuff or see what else could be done with the "Map" panel and the "ploppers." Thanks for reading and please let me know if there is anything which can be improved and/or about your own Tuner tweaks.
 

Attachments

  • Active Player Plus.zip
    1.9 KB · Views: 1,433
I didn't realize the tuner is this powerful. Thanks for writing this up. :D

It can do anything you can do in a lua file, and more. So yeah, it's pretty powerful.
 
I would be surprised if we could do that since the tuner is a separate program. You could duplicate some of the tuner functionality within the civ5 UI since you can make buttons and such that would run Lua commands, but I don't think you could easily integrate the tuner into the game.
 
Except for the log you can create your own tuner screen but I don't think it's worth the effort, to be honest. Running the game in windowed mode allows you to switch to the tuner when you need to, and the log is written to the logs folder anyways.
 
I figure this is a decent place to put this information...

It's probably intuitively obvious for some people but I didn't realize until now that if you're placing stuff with the Map tab, if you right click it deletes items. That's rather helpful! :lol:

I also personally do a lot of work with promotions, so it was helpful to add a "Promotions" multi-list box to the Selected Unit tab. This shows all promotions and adds/removes by clicking, like buildings on the city tab.

Code:
PopulateList=
function()
  local listItems = {};
  local unit = UI.GetHeadSelectedUnit()
  for promotion in GameInfo.UnitPromotions() do
    local item = {}
    item["Text"] = string.gsub(promotion.Type, "PROMOTION_", "");
    if unit and unit:IsHasPromotion(promotion.ID) then
      item["Selected"] = true;
    else
      item["Selected"] = false;
    end
    
    table.insert(listItems, item)
  end
  return listItems;
end

OnSelected=
function(selection)
  local promotionInfo = GameInfo.UnitPromotions["PROMOTION_"..tostring(selection)]
  local unit = UI.GetHeadSelectedUnit()
  if unit and promotionInfo then
    unit:SetHasPromotion(promotionInfo.ID, true)
  end
end

OnDeselected=
function(selection)
  local promotionInfo = GameInfo.UnitPromotions["PROMOTION_"..tostring(selection)]
  local unit = UI.GetHeadSelectedUnit()
  if unit and promotionInfo then
    unit:SetHasPromotion(promotionInfo.ID, false)
  end
end
 
Thalassicus nice work. You got yourself a nice panel there.;) If the feature plopper is not just for show and working; i admire that espacially.:) I created action buttons for features which i will send with next message for example. I did that because i could not make feature plopper working. I created feature list populating with no problem but on selction part is not working. I`m working for that sometime and in somewhere i found the ploppers list which includes feature and terrain ploppers but only as name with no function info on anything. So I looked the available ploppers and changed every improvement to feature and all needed things. The code is good execpt in on selection part returns an error (Error OnSelection: Runtime Error: [string "return function(selection)..."]:6:attempt to index global 'g_FeaturePlopper' (a nil value)). As i understand it did`t find a g_FeaturePlopper. Here is the On Selection part that`s not working.
Spoiler :
function(selection)
local sFeatureType = "FEATURE_" .. selection;
local i = 0;
while GameInfo.Features ~= nil do
if GameInfo.Features.Type == sFeatureType then
g_FeaturePlopper.FeatureType = i;
break;
end
i = i + 1;
end
end

So deeply need your all code for the feature plopper & route plopper of yours please!:sad: Or anyone else that can help whit the subject. If your feature plopper works; we can also create terrain and plot ploppers too which is the main case for me and important. Please share your ploppers and info about the usage of these functions and/or any document about these things to show proper calling for commands and functions.
 
Add Ice Action button code (

UI.SetInterfaceMode(InterfaceModeTypes.INTERFACEMODE_DEBUG);
-- ID1 : 4 is Feature
UI.SetInterfaceModeDebugItemID1(4);
-- ID2 : 0 is Ice
UI.SetInterfaceModeDebugItemID2(0);
)
ID1 value meanings
Spoiler :
1 = Units
2 = Terrain Improvements/buildings
3 = Terrain Routes (roads and railroads)
4 = Terrain Features


ID2 values

Units
Spoiler :
0 = settler
1 = worker
2 = work boat
3 = Great Artist
4 = Great Scientist
etc


Terrain Improvements/buildings
Spoiler :
0 = City Ruins
1 = Barbarian Encampment
2 = Ancient Ruins
3 = Farm
4 = Mine
etc

Terrain Features
Spoiler :

0 - Ice
1 - Jungle
2 - Marsh
3 - Oasis
4 - Flood Plains
5 - Forest
6 - Fallout
7 - Crater
8 - Fuji
9 - Grand Mesa
10 - Reef
11 - Volcano
12 - Gibraltar
13 - Geyser
14 - Fountain of youth
15 - Potosi
16 - El dorado
17 - Atoll
No Feature = -1
 
If there is no way to make feature or terrain plopper, can someone give info about how to create action buttons to change terrain or plot types. I found plot:SetPlotType & plot:SetTerrainType (http://wiki.2kgames.com/civ5/index.php/TerrainTypes) but I could not make them work in action buttons. If anyone knows how to use these please share info. I want to make any kind of control to change terrain &/or plot types. Any info and help is much appreciated.:sad:
 
I intended to attach the zip file as indicated, but somehow forgot to do so. It's attached now. The feature plopper does work, but feature graphics only update for things that can normally change in an active game: forests, jungles, marsh. I suspect it could be made to work with the immutable features too, but I haven't had a need to explore that.
 
Thalassicus thanks for your quick response and for your help.:) Unfortunately I had problems connecting to site and after those internet problems. I got your files yesterday and they have been very helpful. Now I understand the problem; because of the plopper list on internet I thought all the ploppers were defined so didn`t realize the missing parts in the “worldview.lua”. I created the needed ploppers and going to make some modifications to the feature plopper in the lua file.:D I`m working on it now and I will post the results soon. Again thanks for your help. By the way I have to put the results in many threads; is there a way to put same post to many threads because there are many about the subject.
 
All right do I need to put same picture again and again or when I put it one time, can I link it in many posts.
2nd way to post picture several times from faq
The alternative is to use the uploads link at the bottom of every page which also opens a separate window where you can select the file you want to upload although this time once its uploaded you will have to link the image to your post by using [IMG ] [/IMG ] tags without the space around the link, something like:
[IMG ]http://www.civfanatics.net/uploads8/yourfile.JPG[/IMG ]
Now looking for the same thing for posts.
 
how do you get the files in tunermods to work keep getting error when selecting them

Error OnSelection: Runtime Error: [string "return function(selection)..."]:6:attempt to index global 'g_FeaturePlopper' (a nil value))
 
Top Bottom