Hidden GameOptions and the Civ4 Config

phungus420

Deity
Joined
Mar 1, 2003
Messages
6,296
So I've hidden some useless options in LoR that either come from RevDCM or BtS itself (such as lock modified assets). I figured everything was dandy with this, makes the Gameoptions list less cluttered, and keeps users from enabling options that can cause issues. However I have just discovered that even though I have the options set to false in the XML and have them invisible, the stupid game loads up the hidden options from the ini file. Now if the user has played a different mod and selected a different gameoptions it will set the invisible game options to what is in the Civ4 config file, and not by the XML, this has the effect of locking some game options into settings exactly the opposite of what I'd like them to be in, and the user has no way to toggle them, since they are hidden.

So anyone know where these options are loaded from, specifically where it's set to load them from the ini file? I'd like to add a simple function that if the XML sets the gameoption to be invisible, that the game ignores the config setting and loads directly from the XML. Anyone have any idea where such a function could be set, and where the function that loads the gameoptions from the config is located?
 
Is that done in the .exe file? ForceGameOptions is located in the .ini file and is used to force all game options to be loaded from XML. This is pure speculation on my part - so I may be wrong.
 
Yeah, I'm aware of being able to force game options with the mod's ini file, but that's a bad way to do it. That means the user will need to reset the game to their preferences every time they start a game. It's just poor implementation. All I want to do is force them for options that are set to be hidden in the XML.
 
I agree this is a problem. Whenever people switch from one mod to another, unexpected game options may turn on. If you are able to find any solution, I would love to know.
 
Any ideas of where to look? I'm totally shooting in the dark here, but really want to tackle this; would help immensely if someone could point in a probable direction and what to look for.
 
CvInitCore::resetGame() loops over all game options, setting them to false. I recommend searching for other places where m_abOptions elements are set.
 
That seems like a good place to look. Looking at the code though I'm not seeing where they are loaded from. Here is the relevant code:

CvInitCore.cpp
Code:
CvInitCore::CvInitCore()
{
	m_abOptions = new bool[NUM_GAMEOPTION_TYPES];
	m_abMPOptions = new bool[NUM_MPOPTION_TYPES];
	m_abForceControls = new bool[NUM_FORCECONTROL_TYPES];
...
void CvInitCore::setDefaults()
{
	for (int i = 0; i < NUM_GAMEOPTION_TYPES; ++i)
	{
		m_abOptions[i] = GC.getGameOptionInfo((GameOptionTypes)i).getDefault();
	}
	for (int i = 0; i < NUM_MPOPTION_TYPES; ++i)
	{
		m_abMPOptions[i] = GC.getMPOptionInfo((MultiplayerOptionTypes)i).getDefault();
	}
}
...
		// Standard game options
		int i;
		for (i = 0; i < NUM_GAMEOPTION_TYPES; ++i)
		{
			setOption((GameOptionTypes)i, pSource->getOption((GameOptionTypes)i));
		}

		for (i = 0; i < NUM_MPOPTION_TYPES; ++i)
		{
			setMPOption((MultiplayerOptionTypes)i, pSource->getMPOption((MultiplayerOptionTypes)i));
		}
		setStatReporting(pSource->getStatReporting());
...
bool CvInitCore::getOption(GameOptionTypes eIndex) const
{
	FASSERT_BOUNDS(0, NUM_GAMEOPTION_TYPES, eIndex, "CvInitCore::getOption");
	if ( checkBounds(eIndex, 0, NUM_GAMEOPTION_TYPES) )
	{
		return m_abOptions[eIndex];
	}
	else
	{
		return false;
	}
}

void CvInitCore::setOption(GameOptionTypes eIndex, bool bOption)
{
	FASSERT_BOUNDS(0, NUM_GAMEOPTION_TYPES, eIndex, "CvInitCore::setOption");
	if ( checkBounds(eIndex, 0, NUM_GAMEOPTION_TYPES) )
	{
		m_abOptions[eIndex] = bOption;
	}
}

bool CvInitCore::getMPOption(MultiplayerOptionTypes eIndex) const
{
	FASSERT_BOUNDS(0, NUM_MPOPTION_TYPES, eIndex, "CvInitCore::getMPOption");
	if ( checkBounds(eIndex, 0, NUM_MPOPTION_TYPES) )
	{
		return m_abMPOptions[eIndex];
	}
	else
	{
		return false;
	}
}

void CvInitCore::setMPOption(MultiplayerOptionTypes eIndex, bool bOption)
{
	FASSERT_BOUNDS(0, NUM_MPOPTION_TYPES, eIndex, "CvInitCore::setMPOption");
	if ( checkBounds(eIndex, 0, NUM_MPOPTION_TYPES) )
	{
		m_abMPOptions[eIndex] = bOption;
	}
}

bool CvInitCore::getForceControl(ForceControlTypes eIndex) const
{
	FASSERT_BOUNDS(0, NUM_FORCECONTROL_TYPES, eIndex, "CvInitCore::getForceControl");
	if ( checkBounds(eIndex, 0, NUM_FORCECONTROL_TYPES) )
	{
		return m_abForceControls[eIndex];
	}
	else
	{
		return false;
	}
}

void CvInitCore::setForceControl(ForceControlTypes eIndex, bool bOption)
{
	FASSERT_BOUNDS(0, NUM_FORCECONTROL_TYPES, eIndex, "CvInitCore::setForceControl");
	if ( checkBounds(eIndex, 0, NUM_FORCECONTROL_TYPES) )
	{
		m_abForceControls[eIndex] = bOption;
	}
}
After that it's just the read and write stuff. Pretty straightforward.

In CvPlayer this variable is called a couple more times, but it's just used to set things, not to set the variable itself.

In CvInitCore.cpp with the code I can see I can't figure out a way to force loading from the XML if !bVisible. Of course I can't figure out where it's deciding to read from the Civ4 Config rather then the XML.

@davidlallen if you can figure anything out, this will go into the RevDCM core, so would be very helpful, and will directly benifit DuneWars.
 
That seems like a good place to look. Looking at the code though I'm not seeing where they are loaded from. Here is the relevant code:

CvInitCore.cpp
Code:
CvInitCore::CvInitCore()
{
    m_abOptions = new bool[NUM_GAMEOPTION_TYPES];
    m_abMPOptions = new bool[NUM_MPOPTION_TYPES];
    m_abForceControls = new bool[NUM_FORCECONTROL_TYPES];
...
void CvInitCore::setDefaults()
{
    for (int i = 0; i < NUM_GAMEOPTION_TYPES; ++i)
    {
        m_abOptions[i] = GC.getGameOptionInfo((GameOptionTypes)i).getDefault();
    }
    for (int i = 0; i < NUM_MPOPTION_TYPES; ++i)
    {
        m_abMPOptions[i] = GC.getMPOptionInfo((MultiplayerOptionTypes)i).getDefault();
    }
}
...
        // Standard game options
        int i;
        for (i = 0; i < NUM_GAMEOPTION_TYPES; ++i)
        {
            setOption((GameOptionTypes)i, pSource->getOption((GameOptionTypes)i));
        }

        for (i = 0; i < NUM_MPOPTION_TYPES; ++i)
        {
            setMPOption((MultiplayerOptionTypes)i, pSource->getMPOption((MultiplayerOptionTypes)i));
        }
        setStatReporting(pSource->getStatReporting());
...
bool CvInitCore::getOption(GameOptionTypes eIndex) const
{
    FASSERT_BOUNDS(0, NUM_GAMEOPTION_TYPES, eIndex, "CvInitCore::getOption");
    if ( checkBounds(eIndex, 0, NUM_GAMEOPTION_TYPES) )
    {
        return m_abOptions[eIndex];
    }
    else
    {
        return false;
    }
}

void CvInitCore::setOption(GameOptionTypes eIndex, bool bOption)
{
    FASSERT_BOUNDS(0, NUM_GAMEOPTION_TYPES, eIndex, "CvInitCore::setOption");
    if ( checkBounds(eIndex, 0, NUM_GAMEOPTION_TYPES) )
    {
        m_abOptions[eIndex] = bOption;
    }
}

bool CvInitCore::getMPOption(MultiplayerOptionTypes eIndex) const
{
    FASSERT_BOUNDS(0, NUM_MPOPTION_TYPES, eIndex, "CvInitCore::getMPOption");
    if ( checkBounds(eIndex, 0, NUM_MPOPTION_TYPES) )
    {
        return m_abMPOptions[eIndex];
    }
    else
    {
        return false;
    }
}

void CvInitCore::setMPOption(MultiplayerOptionTypes eIndex, bool bOption)
{
    FASSERT_BOUNDS(0, NUM_MPOPTION_TYPES, eIndex, "CvInitCore::setMPOption");
    if ( checkBounds(eIndex, 0, NUM_MPOPTION_TYPES) )
    {
        m_abMPOptions[eIndex] = bOption;
    }
}

bool CvInitCore::getForceControl(ForceControlTypes eIndex) const
{
    FASSERT_BOUNDS(0, NUM_FORCECONTROL_TYPES, eIndex, "CvInitCore::getForceControl");
    if ( checkBounds(eIndex, 0, NUM_FORCECONTROL_TYPES) )
    {
        return m_abForceControls[eIndex];
    }
    else
    {
        return false;
    }
}

void CvInitCore::setForceControl(ForceControlTypes eIndex, bool bOption)
{
    FASSERT_BOUNDS(0, NUM_FORCECONTROL_TYPES, eIndex, "CvInitCore::setForceControl");
    if ( checkBounds(eIndex, 0, NUM_FORCECONTROL_TYPES) )
    {
        m_abForceControls[eIndex] = bOption;
    }
}
After that it's just the read and write stuff. Pretty straightforward.

In CvPlayer this variable is called a couple more times, but it's just used to set things, not to set the variable itself.

In CvInitCore.cpp with the code I can see I can't figure out a way to force loading from the XML if !bVisible. Of course I can't figure out where it's deciding to read from the Civ4 Config rather then the XML.

@davidlallen if you can figure anything out, this will go into the RevDCM core, so would be very helpful, and will directly benifit DuneWars.

Try this,

Code:
void CvInitCore::setDefaults()
{
    for (int i = 0; i < NUM_GAMEOPTION_TYPES; ++i)
    {
        m_abOptions[i] =  GC.getGameOptionInfo((GameOptionTypes)i).getDefault();
    }
    for (int i = 0; i < NUM_MPOPTION_TYPES; ++i)
    {
        m_abMPOptions[i] =  GC.getMPOptionInfo((MultiplayerOptionTypes)i).getDefault();
    }
}
...
        // Standard game options
        int i;
        for (i = 0; i < NUM_GAMEOPTION_TYPES; ++i)
        {
[COLOR=Navy]            setOption((GameOptionTypes)i, false );
            setOption((GameOptionTypes)i, [/COLOR][COLOR=Navy]GC.getGameOptionInfo((GameOptionTypes)i).getDefault() );[/COLOR]
        }

        for (i = 0; i < NUM_MPOPTION_TYPES; ++i)
        {
            setMPOption((MultiplayerOptionTypes)i,  pSource->getMPOption((MultiplayerOptionTypes)i));
        }
        setStatReporting(pSource->getStatReporting());
...

This should first turn off all the options, then get the default option from the XML and turn those marked on, on. IDK if the exe over rides this somewhere though, so it may not help.
 
I suspect that the evil unmoddable Custom Game screen loads the options from the INI. You could set the options directly in the INI in resetOptions() I suppose.
 
Yeah, I'm aware of being able to force game options with the mod's ini file, but that's a bad way to do it. That means the user will need to reset the game to their preferences every time they start a game. It's just poor implementation. All I want to do is force them for options that are set to be hidden in the XML.

keep in mind that this can cause problems with scenarios/maps that depend on a Gameoption which you hide for whatever reason.

what you can do is move all options you want to hide to the end of the gameoptionlist (Options 1, 8 and 19 are hardcoded in the exe somewhere so you don't want to move them) You can also add some 30 dummy gameoptions in between so if someone played a mod with more gameoptions before, then plays yours the worst that can happen is that he has some hidden gameoptions enabled which do absolutly nothing.
 
OK, so it doesn't seem like we have access to how it's read. Is there someway then to set up another program, similar to BUG's ini system to read civ4's config, then alter it if it finds anything wrong?
 
Hi thanks for answering my question, not the answer I was hoping for of course but I was
being optimistic asking it. However I need some advice. Earlier this year I started on this idea for a mod and it centres around giving players as many options as possible. So that means working closely with the EVIL Custom Games Screen (ECGS) then...

I read on the forum that the ECGS wasn't moddable so I decided to open a new window with the dll and then write a text file and put some code into the map files to read it. I had just worked out how to open a window from the dll when I found the God of War mod. Hello I thought there's an extra checkbox in the victory options.

After playing around I've got it to the point where a checkbox in the options section if selected and with the correct map file will open a new screen (where there will be many new options). So good so far but then the options problem raises its ugly head. If I have the xml option turned on it works to a point but if I have the NO BARBARIONS option selected what do I get... RAGING BARBARIONS, the opposite of what I want.

Right... so now I've started to write some code, currently when the mod starts it reads the civ ini. Once finished it'll change the options if necessary and change them back when the mod closes. But now it appears the ini file may not be that important and the order of the options may be hard coded into the exe. Therefore I can't place my checkbox at the top where it will be easily seen. So I might be back to my original idea. Any suggestions?
 
Thanks for that. I might leave the Evil CGS for now concentrate on the rest and then look at Civ 5 when it comes out. It may be setup differently.
 
Well it may be a bit late in the day with the release of Civ 5 imminent. But nevertheless I've found that CyGame() appears to fix the options problem ie.

for i in range(24):
if CyGame().isOption(i):
if i == 0 :
CyGame().setOption(i , false)
else:
CyGame().setOption(i , false)
CyGame().setOption(i - 1 , true)

As I've created an extra checkbox there are 24 options to check. I placed the loop in a map file (Highlander.py) in the addFeatures() function (probably not too important where you place it). I've tested it a couple of times with BTS and it seems to work. :)
 
Top Bottom