Options Menu

SpoiledFruit

Chieftain
Joined
Mar 11, 2006
Messages
72
Location
Boise, Idaho
Taking a look at what needed to be done; I have begun the creation of a new options tab that will allow players to select which features they would like to be used when using the new DLL. I will update the new menu as features are added.

It will be initially just one checkbox turning the modifications on or off until it nears final beta or more advance features are added.

If anyone has any sudggestions, feel free to give your two cents
 
Do you mean that all our functions should check the status of this flag when they are run?

My impression was that we would be adding hooks that are only going to have an effect on the game when they are called in Python or referenced in XML. For example the Diplomatic and Happiness traits I added wont have an effect unless the Leaderhead.xml file uses one of thouse new tags. Someone (probably me) can then create a traditional Mod and put a disclaimer on it "THIS MOD REQUIRES CCC DLL v2.5 OR HIGH!!". The feature is then going to be turned on/off by the XML/Python files just like any other feature.

Our goal should be to create a DLL thats completly back-compatable with vanilla 1.61 and any traditional (python/XML only) mod. If a moder used some of our new features then their mod is "SDK based" and will require some minimum version of the new dll to run. But all feature activation would be controled by their Mod. If we had a very complex feature that changed the game is a big way then it should by default be off when the game loads with the potential for a Python call to activate it at game start. In the absense of such a call the feature remains dormant and the game runs and responds in a totaly vanilla mannor.
 
I think the both of you speak of different things.
For example could an enhanced AI be completly back compatible to Vanilla. But switching it on via a phyton call sounds rather pointless as each Mod would have to include that Pyton call. Therefor an switch in the Option Tag would allow each Player to Play with the Enhanced AI whenever he likes.

The Option would of course be rather fruitless if the new Feature requires new XML Tags or something. Then of course it has to be switched active by the Mod.

The only thing that is really bad about backward compatibility are the checks that we have to add when introducing new XML-Tags.
Has someone already writen a routine to read new tags form the file or not dependend on a switch or is planning to?
That one might be less easy as one thinks especially when using tags that are filled by something like PROMOTION_COMBAT1.
Maybe we should include a XML file that defines the used components and is read as first xml-file when available? That might be better then Phython hooks and easier to handle for mod makers.
 
I see no reason why both methodologies should not be applied as each situation warrants. I think an options panel is cool. Heck, we might want it to contain a tabbed set of subpanes so that individual components of the SDK could register their own configuration panels.

Similarly, a nice SDK component would be the addition of a similar options panel controlled by a Python file which would allow a module to have it's own configuration menu. Adding everything as map options gets cumbersome after a while, and not all module options should be required to be set in an .ini file.
 
Impaler,
It should be a simple if(bool) function that is not to hard to add to major changes (those for the AI, function, or interface changes). Performance, bug fixes or really simple changes should not need the bool check.

Also...

After delving into the project, I was also thinking of adding another main tab for mod activations such as what Ghost Recon has. This way, players have a more intuitive way to activate or deactivate mods as well as setting specific options for those mods while not having to change the files themselves.

Though this requires a bit more work in the source code, it would make adding and managing mods much easier.

I am also looking to make an interface in the source code so that I can add new Python and XML code in a brand new file so that code changes are not dispersed over 20, 30 or more files where maybe one or two lines were changed on the majority.

While I have gotten the new tab pretty much finished in terms of initialization, the code that actually makes the changes is still being written and I am still trying to find where the python calls interact in the C++ code. Unfortunately I think some calls are going to the boost_python-vc71-mt-1_32.dll and python24.dll. Now if the source code for these DLLs are unchanged from the open source libraries, then that is fine, but if they have been altered, it might be tougher.

This all depends if the option calls are not in the SDK. If they are, please let me know because I somehow have not found them (probably looking in the wrong spot).
 
SpoiledFruit said:
Impaler,
While I have gotten the new tab pretty much finished in terms of initialization, the code that actually makes the changes is still being written and I am still trying to find where the python calls interact in the C++ code. Unfortunately I think some calls are going to the boost_python-vc71-mt-1_32.dll and python24.dll. Now if the source code for these DLLs are unchanged from the open source libraries, then that is fine, but if they have been altered, it might be tougher.

This all depends if the option calls are not in the SDK. If they are, please let me know because I somehow have not found them (probably looking in the wrong spot).

What are you looking for exactly? A way to pass data from SDK to PythonAPI and back?
 
SpoiledFruit said:
Taking a look at what needed to be done; I have begun the creation of a new options tab that will allow players to select which features they would like to be used when using the new DLL. I will update the new menu as features are added.

It will be initially just one checkbox turning the modifications on or off until it nears final beta or more advance features are added.

If anyone has any sudggestions, feel free to give your two cents

I already implemented custom option tab way back from update v 1.09. That mod adds additional custom option tab.
Modder can add mod-specific option check box or dropdown list on-the-fly in run-time... No need to manually edit "CvOptionsScreen.py".
It also has INI file parser and writer which is integrated with Custom Option Screen setting and "Civilization.ini" setting.
This facility was mainly aimed for Python mod. but I guess that it can be improved to be used in SDK ( access value of Ini/Option Screen option from the SDK...)

See this post : http://forums.civfanatics.com/showpost.php?p=3863360&postcount=8
This version is for 1.52, But I am updating it for v 1.61 (Firaxis changed an API behavior in v1.61 which is piviotal to use custom callback handler module. I think that is BUG, not improvement.) I will publish 1,61 complient version soon.. ( next week? )

I suggest to add some kind of SDK DLL version/ fearure set management API. We should have some unified DLL SDK API call that identidies itself. This API will tell Python module that..
1) Who build this DLL and when? what version is this DLL? ( apart from base 1.61 version number). Note that DLL builder/integrator may be different from specific SDK mod author in case of combined SDK mod DLL.
2) What features does it include? Say, does it has talchas's Action button 2.0 facility? It will list all features (mod-unit) included in this DLL build. Python module can identify it and change its behavior accoding to this result. ( disabling some unsupported fatures or emulating it in Python or just give up and complain on DLL version loaded)
3) Save file vsersion. This is very important. adding any member variable to CvUnit or any persisent class will change saved file size of the class. We should have unified way to (at least) identify extended size so that other SDK mod writer can skip unsupported data part and continue loading supported data part.
This API don't have to be complex. Just it will return long text string with "name=value" pairs which is delimetered by comma like CSV. It can be easyly converted to Python dict or Python list in Python module with eval().
 
Sound good SimCutie, my only consern is will this put a significant burden on the Moders? No system is going to be idiot proof, our standard of what constitutes "easy" can never cover everyone (Everyday I see a new post by someone asking to be taught what XML is!). If we adopt a standard methodology we want to spread the word and make the documentation/tutorial very easy. The worst thing would be for us to do all this codeing and have it ignored because people are too :confused:

Theirs a good chance this what you propose will be some or all of what we need (it definatly sounds impressive to a relative noob like myself). I'm just saying we should think this stuff out and come up with a realy bullet-proof interface that takes as much load off the Python only Mod makers as possible.
 
Right - regarding SC's options menu. I thought I'd bring the discussion here, as the other thread is getting a bit complicated.

Thoughts:

Fixed options. Some (lots of) mods will need options set before you start the game to work properly. While they may work if you change the option mid-game, they may not. There should be a special subset of options that cannot be changed mid-game.

This in inself shouldn't be too hard - you just tweak the way the options are drawn for your mod so that they are greyed out if you are currently running a game, rather than producing checkboxes/dropdown menus. This would mean that you'd have to set them either in the "custom game" panel, or in the options screen from the main menu.

However, this will only work if the options are tied to the savegame. If they are tied to the user then it just won't work - it would be quite easy to accidently change the options in a save-game which was already running by simlpy starting up a new game with different options.

So I suppose the question is - are the options attached to the save game, or are they merely consistant for the user?

Attaching them to the savegame has the additional advantage that if somebody comes back to us with a problem, we can just ask for the savegame, and everything will be loaded exactly how it was, rather than the potential for weird options.
 
Good point TGA, my GreatPeoplePoint Pooling mod is one of the type that should NOT be turned on or off durring the games progress, it wouldn't crash the game or anything like that but it would cause the player to loss a ton of progress in GreatPeople which would just be weird and anoying. I will set up a read/write for the control boolean so it goes into the savegame.

I am still a bit unshure what I must set up to get the this to plug into the options screen that were using. Do I need to make a get & set function and export them to Python. If so how would you recomend that I block that set function from working once a game is in progress, what call can tell me when the player is in game vs just in the option menu shell?

I was also thinking, would it be a good idea to create an XML boolean under Global defines or such to control the mod as well, The options screen can over-ride that after loadup ofcorse so it just serves as a default. I think the ideal solution is to save this type of thing in the same place/way that the game keeps your last used mapsize and Difficulty level between play sessions. We can just piggyback out Mod control data their and it would be used as default settings when a new game is instantiated, this is done with Init file I think?
 
Impaler[WrG] said:
I am still a bit unshure what I must set up to get the this to plug into the options screen that were using. Do I need to make a get & set function and export them to Python. If so how would you recomend that I block that set function from working once a game is in progress, what call can tell me when the player is in game vs just in the option menu shell?
I'm not sure...

SimCutie - any chance we could have a quick guide on using this?

From what I can gather, the options are created dynamically when the options screen is opened by seeing which mods want to create an option. Each mod has it's own function for drawing it's option, which is written in python. All you would have to do to disable it is to change it so that the option was disabled (but still visible - greyed out or something) if the game was active. I think gc.getGame() should only return something if the game is active, so you could just use:
Code:
if gc.getGame():
       <grey out option>
else:
       <draw option>
Anyway, as above, could you give us a quick guide to using this please SimCutie?
 
STEP TO ADD CUSTOM OPTION
I will explain general step to add/use custom option in Python mod frist and next, explain how to add/use custom option for DLL runtime configuraion option in SDK.

1. first, dedcide your option secton name and option name.
Let's assume that section name "MY_MOD" and it has two option.
One is "my_enable_feature" which is boolean checkbox option (True/False). default is True.
Another is "my_selection_choice" which is dropdown selection listbox which has three list item, "First Chice", "Second Choice", "Third Choice", and represented as integer index value 0, 1, 2, respectively. Default value is index 0 ("First CHoice").

2. Add EventHandlerRegister() global funtion to *your* python mod file.
Put this Pyton file into CustomAssets/Python/{custom, screen} or MOD/<mod-name>/Assers/Python folder or subdirectory trees of these folders.
Code:
in "Your_ModMain.py":
....

def EventHandlerRegister( evt_mgr, unused = None ):
    import CvCustomEvent
    # CvUtil.pyPrint(__name__ + ": MY Mod Event Register OK.")	
    return { CvCustomEvent.EVENT_OPTIONBEGIN: onMyDrawOption, }

def onMyDrawOption(argsList):
    optscr, canvas, Unused = argsList[:3]

    # Show  Checkbox
    optscr.addGenericCheckbox( canvas, "MyEanleFeatureCheckbox",
        "TXT_KEY_OPTIONS_MY_MOD_ENABLE_FEATURE", "MY_SECTION", 
        "my_enable_feature", True ) # default is True

    #  If you want gray out the checkbox, 
    #    add bEnable argument as False like below.
    # optscr.addGenericCheckbox( canvas, "MyEanleFeatureCheckbox",
    #    "TXT_KEY_OPTIONS_MY_MOD_ENABLE_FEATURE", "MY_SECTION", 
    #    "my_enable_feature", True, bEnable=False )
 
    # Show Dropdown list	
    aszDropdownElements = ( 
        "TXT_KEY_OPTIONS_SELECTION_CHOICE_FIRST",
        "TXT_KEY_OPTIONS_SELECTION_CHOICE_SECOND",
        "TXT_KEY_OPTIONS_SELECTION_CHOICE_THIRD" )

    optscr.addGenericDropdown( canvas, "MySelectionDropdown", 
        "TXT_KEY_OPTIONS_MY_SELECTION", aszDropdownElements, "MY_SECTION",
        "my_selection_choice", 0 ) # default is index 0 ("First Choice")
3. Then add these TEXT_KEY' entries to your CIV4GameText_Your_MOD.xml in "CustomAssets\xml\text" XML file in "CIV4GameText_Your_MOD.xml"

TXT_KEY_OPTIONS_MY_MOD_ENABLE_FEATURE (Enable feature checkbox label)
TXT_KEY_OPTIONS_MY_MOD_ENABLE_FEATURE_TT (Enable feature checkbox Tooltip help text)
TXT_KEY_OPTIONS_MY_SELECTION (Selection Dropdown title label)
TXT_KEY_OPTIONS_MY_SELECTION_TT (Selection Dropdown Tooltip help text)
TXT_KEY_OPTIONS_SELECTION_CHOICE_FIRST (Selection Dropdown item 0 "First Choice")
TXT_KEY_OPTIONS_SELECTION_CHOICE_SECOND (Selection Dropdown item 1 "Second Choice")
TXT_KEY_OPTIONS_SELECTION_CHOICE_THIRD (Selection Dropdown item 2 "Tird Choice")

Now when you start up option screen and click "Custom" tab. You will see your Enable fature check box and selection Dropdown.

4. Now I will explain how to get a the option value in your python file.
Use following 3 functions from PyCivSim.py
Code:
useOptionSection ( "section_name")
getCustomOption ( "section_name", "option_name", default_value = None)
setCustomOption ( "section_name", "option_name", newValue)
Code:
example) in your Python file
....
import PyCivSim

def Your_init_func():
    PyCivSim.useOptionSection("MY_SECTION")

def Your_Working_func():
    .......
    if PyCivSim.getCustomOption("MY_SECTION", "my_enable_feature", True) :
        do blaba.........
	
    choice = PyCivSim.getCustomOption("MY_SECTION", "my_selection_choice", 0)
    if cjoice == 0 :
        do First Choice bla bla...
    elif cjoice == 1:
        do Second Choice bla bla
    elif cjoice == 2:
        do Third Choice bla bla
    else :
        error....
useOptionSection("MY_SECTION") loads the section data into memory or create the section if it does not exist in ".ini" file. So called it before using getCustomOption("MY_SECTION"...) and need to call only once through out Civ game and MOD run.

These player profile Ini configuration option parser and custom option screen are written in pure Python.
So you can use these facility without custom DLL installed and use them in pure-python MODs

.
 
Now I will explain how to add DLL runtime configuration option.

To add SDK DLL configuration runtime option from C++ code,
Call addExtDLLConf() of "CvExtention.cpp" in SimCutie's SDK DLL code.
Call it in 'Init' event time. It is recommanded in add it in CyExtGC:: onInit() function in CvExtension.cpp file
Please add appropiate comment there and explain what the config option does.
Then, the option checkbox will displayed when player opens Option Screen from Civ4 aplication main menu.
Code:
SYNOSIS:
extern void addExtDLLConf( LPCTSTR szConfKey, bool bInitValue, 
     LPCWSTR wszCheckboxLabel =NULL, LPCWSTR wszCheckboxToolTip =NULL)
szConfKey = config name string ex) "UNITNAME_TYPEFIRST", "MY_MOD_ENABLE"
bInitValue = initial value set when user installed the MOD or DLL first time.
wszCheckboxLabel = Checkbox label displayed on Option screen. wide char. string
wszCheckboxToolTip = Checkbox tooltip. wide char. string

If this wszCheckboxLabel is not specified or NULL string, check box will not displayed in Custom Option Screen.
So player can not change it during running Civ4 game. Python mod can change it, though.
Config option without Option screen checkbox can be chnaged by editing "<User-profile>.ini" file.
Code:
example )
// Display full unit name as "UnitType, Custom name" instead of "Custom name (UnitType)"
// Addedfor SIMCUTIE_GAMETEXT feature by SimCutie
addExtDLLConf( "UNITNAME_TYPEFIRST" ,	true,
	L"Type first in Unit Name",
	L"Display full unit name like \n'UnitType, Unique Name" );

// unitCreated/unitLost/unitUpgrade event behavior. If true, restore old behavior.
// Added for SIMCUTIE_UNITEXT feature by SimCutie
addExtDLLConf( "LEGACY_EVENT",	false );	// no checkbox
To access the option value from your C++ SDK, use GETEXTCONF(conf_name) macro.
It is definded in "CvExtension.h" or "CvExtGlobal.h"
Code:
ex)  if ( !GETEXTCONF(LEGACY_EVENT))
		do new action;
	else
		old action;
Note that conf_name argument of GETEXTCONF(conf_name) is not enclosed in double quotation.

To access it in Python, use below function in CustomAssets/python/custom/PyCivSim.py
Code:
PyCivSim.getExtDLLConf(szConfKey) 
PyCivSim.setExtDLLConf(szConfKey, bNewvalue )

example)
    import PyCivSim
	isLegacy = PyCivSim.getExtConf( "LEGACY_EVENT")
	PyCivSim.setExtConf( "UNITNAME_TYPEFIRST", True)
 
Befor you start to use SDK DLL runtime DLL config and custom option screen described above, check if this is really what you want.
If your the runtime DLL configuration option should not changed from start of new game to final victory/defeat of the game (I'll call it one game match) and all player should playe under same option, and player should be able to choose the configuration option by game match by game match, at start of new game, my custom option is not what you want.

In such case, I recommand to use GC.getGameOptionInfo().
Player can choose the option from CUSTOM GAME menu of Civ4 Main menu -> Custom game OPTIONS screen.
To add new CvGameOptionInfo, do following step.

1) Add new option constant (like GAMEOPTION_MY_MOD_ENABLE) to "enum GameOptionTypes" definition in "CvEnum.h".
2) Add Python interface of the constant value to python::enum_<GameOptionTypes> in CyEnumInterface.cpp
.value("GAMEOPTION_COMPLETE_KILLS", GAMEOPTION_COMPLETE_KILLS)
3) Copy "Assets\XML\GameInfo\CIV4GameOptionInfos.xml" XML file to "CustomAssets\xml\gameinfo\"
folder.
Edit "CIV4GameOptionInfos.xml" and add your XML entry like this.
Code:
	<GameOptionInfo>
		<Type>GAMEOPTION_MY_MOD_ENABLE</Type>
		<Description>TXT_KEY_GAME_OPTION_MY_MOD_ENABLE</Description>
		<Help>TXT_KEY_GAME_OPTION_MY_MOD_ENABLE_HELP</Help>
		<bDefault>0</bDefault>
	</GameOptionInfo>
4) Add TXT_KEY_GAME_OPTION_MY_MOD_ENABLE, TXT_KEY_GAME_OPTION_MY_MOD_ENABLE_HELP
text info to Text XML file in \CustomAssets\xml\text. (like "CIV4GameText_EXTDLL.xml")

5) And recompile the DLL and install it to your CustomAssets folder.
That's it,
Then player can see the new Game option in the Custom game OPTIONS screen.
In C++ SDK, Modder can get/set the value these API. It has python counterpart too.
Code:
bool GC.getGameINLINE().isOption(GameOptionTypes eIndex) const
void GC.getGameINLINE().setOption(GameOptionTypes eIndex, bool bEnabled)

CyGame().isOption(GameOptionTypes eIndex)
CyGame().setOption(GameOptionTypes eIndex, bool bEnabled)
----------------------------------------

If your configuration can be changed freely in the middle of the game on runtime,
and it maybe choosen by player and maybe different from player by player. (like graphic option)
Then my runtime DLL config is not what you want. Then use CvPlayerOptionInfo.
To add new CvPlayerOptionInfo, do following step.

1) Add new option constant (like PLAYEROPTION_MY_MOD_ENABLE) to "enum PlayerOptionTypes" definition in "CvEnum.h".
2) Add Python interface of the constant value to python::enum_<PlayerOptionTypes> in CyEnumInterface.cpp
3) Copy "Assets\XML\GameInfo\CIV4PlayerOptionInfos.xml" XML file to "CustomAssets\xml\gameinfo\"
folder.
Edit "CIV4PlayerOptionInfos.xml" and add your XML entry like this.
Code:
	<PlayerOptionInfo>
		<Type>PLAYEROPTION_MY_MOD_ENABLE</Type>
		<Description>TXT_KEY_PLAYEROPTION_MY_MOD_ENABLES</Description>
		<Help>TXT_KEY_PLAYEROPTION_MY_MOD_ENABLE_HELP</Help>
		<bDefault>0</bDefault>
	</PlayerOptionInfo>
4) Add TXT_KEY_PLAYEROPTION_MY_MOD_ENABLES, TXT_KEY_PLAYEROPTION_MY_MOD_ENABLE_HELP
text info to Text XML file in \CustomAssets\xml\text. (like "CIV4GameText_EXTDLL.xml")
5) And recompile the DLL and install it to your CustomAssets folder.
That's it,
Then player can see the new Player option in the Game tab of Option Screen
In C++ SDK, Modder can get/set the value these API. It has python counterpart too.
Code:
bool CvPlayer::isOption(PlayerOptionTypes eIndex) const
void CvPlayer::setOption(PlayerOptionTypes eIndex, bool bEnabled)

getActvePlayer().isOption(PLAYEROPTION_MY_MOD_ENABLE)
getActvePlayer().setOption(PLAYEROPTION_MY_MOD_ENABLE, newValue)
You can access These in Python like this
Code:
UserProfile.getPlayerOption( gc.getInfoTypeForString("PLAYEROPTION_MY_MOD_ENABLE"))
UserProfile.getPlayerOption(gc.getInfoTypeForString("PLAYEROPTION_MY_MOD_ENABLE", newvalue )

If both Game Option and Player Option selction method doesn't meets Your needs,
Then try my run time DLL config and Custom option screen.
 
Thanks that just what I needed, and its infact a lot easier to do then adding a Boolean to the CvGame object which is how I had it set up before. I have redirected all my calls to the GameOption system. Now just needs some final testing and it should be ready.
 
Right.

What is the difference between CvPlayerOptionInfo, and your implementation? It seems to me that both can be changed during runtime. The only difference I can see is where in the options menu they are, and the fact that you can't have a mulitiple choice box in playerInfo.

If there is no difference, then we should put all the options in only one of them. I suggest we use the new CCP tab for this, to prevent the playerInfo section from getting cluttered.
 
I cant get the CustomGame options screen to show new options properly, it always displays the same number of check boxes. I can get my option to display but only by bumping something else off the list. Is almost as if they have the number hardcoded at the UI level. Have you experienced anything similar SimCutie? Anyone know the Python file from which the CustomGame options screen is generated?
 
Impaler[WrG] said:
I cant get the CustomGame options screen to show new options properly, it always displays the same number of check boxes. I can get my option to display but only by bumping something else off the list. Is almost as if they have the number hardcoded at the UI level. Have you experienced anything similar SimCutie? Anyone know the Python file from which the CustomGame options screen is generated?
Yes, it happend same to me.. So I had to remove some less frequently used option and make it as fixed option and put mine to it by comment out the XML entry of old removed otion. This is fault of the CUSTOM GAME OPTION screen that has fixed number of entrie and does not honour changed NUM_GAMEOPTION_TYPES.
 
I dont think this is going to be acceptable to average User if Options that Firaxis created are removed, it also goes against no-change doctorine. The only acceptable solution will be to fix the idiotic Hardcoding of the Custom Game options screen or use the Player Options Screen which I can see is coded to use the NUM_PLAYER_OPTIONS correctly. We would unfortunatly be dependent on the player to set these options imediatly at the games start and not mess with them later which is very risky, I would much prefer the original Game options solution. Can anyone find the code that creates that screen, I haven't been able too, I fear it may be a compiled Python file.

Also not that XML entries only NAME the options, their all defined on the Enum.h and the only thing thats matching them up is the order inwhich they occur (a method that I consider very sloppy and which Firaxis uses way to much and dosn't document), if your XML puts a new Option as the 4th element your new Enum must be 4th as well or the checkbox will activate some other Option.
 
Top Bottom