Questions about modding UN/AP eligibility

Munch

Benevolent Despot
Joined
May 25, 2006
Messages
2,081
EDIT: Solution in post 11 below

Hi, I am interested in modding the UN and AP voting system, so that you can't be elected to secretary general twice consecutively. In some games it seems like the same civ is elected continuously, so I am looking to avoid this and make the secretary general election a bit more variable.

Of course as it stands the two candidates are the civ who built the thing, and the distinct civ that holds the most votes. The idea is that if one of these wins the election then they cannot win the next time, so for each election candidates would have to be chosen with a memory of who the incumbent is, so they can be excluded. Of course, this would remove the idea of the builder of the UN being immediately and forever eligible for election, but then again that's the whole point.

I ran a search to see if anyone had made a thread about anything similar to this, but all I could find was this thread, about increasing the number of candidates in an election. This is something I want to do as well; since the builder of the UN/AP wouldn't have guaranteed eligibility anymore, I think it would make sense to consider several, possibly all civs for election to secretary general (in the case of the AP, it would presumably have to be all civs provided they have the correct state religion).

However in that short thread the only suggestion to increase the number of election candidates is to change the TEAM_VOTE_MIN_CANDIDATES to some larger number, such as 6. I haven't tried this but based on the variable name, wouldn't that stop elections from even happening if there weren't at least 6 civs remaining?

If anyone is familiar with how civs becoming eligible for election is coded, I would very much appreciate any pointers regarding these ideas.

Thanks
 
Well your at it, it would be awesome if you could still use the UN/AP without a Diplomatic Victory, and just remove the "Win" vote option.
 
However in that short thread the only suggestion to increase the number of election candidates is to change the TEAM_VOTE_MIN_CANDIDATES to some larger number, such as 6. I haven't tried this but based on the variable name, wouldn't that stop elections from even happening if there weren't at least 6 civs remaining?

I don't know the answer to your actual question about preventing the incumbent from being re-elected. But changing the T_V_M_C variable and trying what happens on a tiny game would only take you a few minutes.

afforess said:
Well your at it, it would be awesome if you could still use the UN/AP without a Diplomatic Victory, and just remove the "Win" vote option.

That is easy to change in xml. See file gameinfo/civ4voteinfo.xml. Each VoteInfo section describes one possible UN or AP vote. One of them is called "VOTE_VICTORY". Remove it. Voila!
 
I don't know the answer to your actual question about preventing the incumbent from being re-elected. But changing the T_V_M_C variable and trying what happens on a tiny game would only take you a few minutes.

Yes I'll try that, was just curious if anyone knew off-hand what the effect of that change would be.

That is easy to change in xml. See file gameinfo/civ4voteinfo.xml. Each VoteInfo section describes one possible UN or AP vote. One of them is called "VOTE_VICTORY". Remove it. Voila!

That's true, I have done the same thing previously to remove the ability of the UN to vote on banning nuclear weapons.
 
That is easy to change in xml. See file gameinfo/civ4voteinfo.xml. Each VoteInfo section describes one possible UN or AP vote. One of them is called "VOTE_VICTORY". Remove it. Voila!

That's not what I want...

I want it so that even if the game option Diplomatic Victory is off, players can still build and use the AP/UN exactly the same, except there is no victory vote option.

Sorry for hijacking this thread...
 
That's not what I want...

I want it so that even if the game option Diplomatic Victory is off, players can still build and use the AP/UN exactly the same, except there is no victory vote option.

Try it. Take out the victory vote from the voteinfo file, and you will see that there is no possible vote for diplomatic victory.

Perhaps you thought I was suggesting to remove the victory condition from the victory condition file. I am not sure what would happen if you left the vote in voteinfo but removed the victory condition -- I guess you could win the vote, but nothing would happen. But anyway, that is not what I am suggesting.
 
Try it. Take out the victory vote from the voteinfo file, and you will see that there is no possible vote for diplomatic victory.

Perhaps you thought I was suggesting to remove the victory condition from the victory condition file. I am not sure what would happen if you left the vote in voteinfo but removed the victory condition -- I guess you could win the vote, but nothing would happen. But anyway, that is not what I am suggesting.

But I don't want to get rid of the Diplo victory option, just add a feature to non-diplo games...

Anyways, I think I may have found what I wanted, from your advice though. The <bvictory> tag looks promising.
 
I've been looking through the code today and it seems like a lot of the stuff to do with handling elections goes on in CvGame.cpp. Still, there are a lot of methods and very few things which look like they are related to deciding who the candidates are for secretary general.

A possible lead:

1) There is a method TeamTypes CvGame::findHighestVoteTeam(const VoteTriggeredData& kData) const in CvGame.cpp which (obviously) returns the team with the most votes. This seems to only ever be called in the method void CvGame::doVoteResults(), in this context:

Code:
			if (isTeamVote(eVote))
			{
				TeamTypes eTeam = findHighestVoteTeam(*pVoteTriggered);

				if (NO_TEAM != eTeam)
				{
					bPassed = countVote(*pVoteTriggered, (PlayerVoteTypes)eTeam) >= getVoteRequired(eVote, eVoteSource);
				}

				szBuffer = GC.getVoteInfo(eVote).getDescription();

				if (eTeam != NO_TEAM)
				{
					szBuffer += NEWLINE + gDLL->getText("TXT_KEY_POPUP_DIPLOMATIC_VOTING_VICTORY", GET_TEAM(eTeam).getName().GetCString(), countVote(*pVoteTriggered, (PlayerVoteTypes)eTeam), getVoteRequired(eVote, eVoteSource), countPossibleVote(eVote, eVoteSource));
				}

The only time I can imagine that the identity of the civ with the most votes would be required is in the case of choosing the candidate (other than the UN/AP builder) who is eligible for election to secretary general. But then, the findHighestVoteTeam method doesn't appear to consider whether or not the resultant team is also the UN builder (perhaps it is handled in countVote(), but I don't know):

Code:
TeamTypes CvGame::findHighestVoteTeam(const VoteTriggeredData& kData) const
{
	TeamTypes eBestTeam = NO_TEAM;
	int iBestCount = 0;

	if (isTeamVote(kData.kVoteOption.eVote))
	{
		for (int iI = 0; iI < MAX_CIV_TEAMS; ++iI)
		{
			if (GET_TEAM((TeamTypes)iI).isAlive())
			{
				int iCount = countVote(kData, (PlayerVoteTypes)iI);

				if (iCount > iBestCount)
				{
					iBestCount = iCount;
					eBestTeam = (TeamTypes)iI;
				}
			}
		}
	}

	return eBestTeam;
}

Very confusing.

Also with respect to if (isTeamVote(eVote)), what is a "teamvote", and how does it differ from a regular vote, if at all?
 
TeamVote is for electing a new Secretary General as opposed to a vote for a particular policy or course of action.

Thanks for the information. Does that also include voting for the Apostolic Palace resident, or is that done somewhere else (if so I haven't found it yet)?
 
To answer my own question, a teamvote is a vote for secretary general (UN or AP) or it is also a vote for victory. This is set in CvGame.cpp:

Code:
bool CvGame::isTeamVote(VoteTypes eVote) const
{
	return (GC.getVoteInfo(eVote).isSecretaryGeneral() || GC.getVoteInfo(eVote).isVictory());
}

So thanks very much for the tips guys, I am pretty sure I have got this working now. For anyone who is interested in modding this or something similar themselves, read on:

Successful changes:

1) You cannot be elected to secretary general if you are currently secretary general.
2) Building the UN/AP does not ascribe permanent voting eligibility.

Spoiler :
This can be done by editing three .cpp files like so:

In CvGame.cpp there is a crucial method bool CvGame::isTeamVoteEligible(TeamTypes eTeam, VoteSourceTypes eVoteSource) const, which decides who the candidates should be for a teamvote (i.e., who the candidates are for secretary general or for victory).

The first edit here ensures that when the method is called on the incumbent team, they are not deemed eligible for the teamvote election if it is for secretary general (they are still eligible if it is for victory of course).

The second edit here involves the latter part of the method, which counts up the votes of everyone and decides whether you should be involved in the election or whether there are other players with more votes than you who should be 'reserved' a place. The edit ensures that a place is not reserved for the incumbent if it is a secretary general election.

The new method in full:

Code:
bool CvGame::isTeamVoteEligible(TeamTypes eTeam, VoteSourceTypes eVoteSource) const
{
	CvTeam& kTeam = GET_TEAM(eTeam);

/* Munch edit 06/10/09 */
/* so that the incumbent resident is forbidden from being reelected, but not forbidden from being elected to total victory */
/* to revert, delete all */
	int bSecretaryElection = 0;
	for (int iI = 0; iI < GC.getNumVoteInfos(); iI++)
	{
		if (GC.getVoteInfo((VoteTypes)iI).isVoteSourceType(eVoteSource))
		{
			if (!GC.getVoteInfo((VoteTypes)iI).isVictory())
			{
				bSecretaryElection = 1;
			}
		}
	}

	int incumbentTeam = getSecretaryGeneral(eVoteSource);
	if (eTeam == incumbentTeam)
	{
		if (bSecretaryElection == 1) return false;
	}
/* end Munch edit */

	if (kTeam.isForceTeamVoteEligible(eVoteSource))
	{
		return true;
	}

	if (!kTeam.isFullMember(eVoteSource))
	{
		return false;
	}

	int iCount = 0;
	for (int iI = 0; iI < MAX_CIV_TEAMS; iI++)
	{
		CvTeam& kLoopTeam = GET_TEAM((TeamTypes)iI);
		if (kLoopTeam.isAlive())
		{
			if (kLoopTeam.isForceTeamVoteEligible(eVoteSource))
			{
				++iCount; /* Munch comment 06/10/09 - iCount represents how many teams in total are forced to be vote eligible, in my mod this should always be zero */
			}
		}
	}

	int iExtraEligible = GC.getDefineINT("TEAM_VOTE_MIN_CANDIDATES") - iCount; /* Munch comment 06/10/09 - this new int then declares how many eligibility spaces remain to be filled */
	if (iExtraEligible <= 0)
	{
		return false;
	}

	for (int iI = 0; iI < MAX_CIV_TEAMS; iI++)
	{
		if (iI != eTeam)
		{
			CvTeam& kLoopTeam = GET_TEAM((TeamTypes)iI);
			if (kLoopTeam.isAlive())
			{
				if (!kLoopTeam.isForceTeamVoteEligible(eVoteSource))
				{
					if (kLoopTeam.isFullMember(eVoteSource))
					{
						int iLoopVotes = kLoopTeam.getVotes(NO_VOTE, eVoteSource);
						int iVotes = kTeam.getVotes(NO_VOTE, eVoteSource);
						if (iLoopVotes > iVotes || (iLoopVotes == iVotes && iI < eTeam))
						{
/* Munch edit 22/10/09 */
							iExtraEligible--;
							if (bSecretaryElection == 1 && iI == incumbentTeam) iExtraEligible++;
/* the purpose of this is to not 'reserve' an election space due to higher vote count for the incumbent, who is supposed to be now ineligible */
/* exception being if the teamvote is actually a victory vote rather than a secretary general vote */
/* to revert, delete all except iExtraEligible--; */
						}
					}
				}
			}
		}
	}

	return (iExtraEligible > 0); /* Munch comment 06/10/09 - i.e. return true if all available eligibility slots are not to be taken by civs with more voting power */
}

In CvTeam.cpp, commenting out the contents of the method changeForceTeamVoteEligibilityCount ensures that when the method is called, the builder of the vote building does not actually become forever eligible for election.

The fourth change is in CvGameTextMgr.cpp, and is just commenting out the contents of the statement which begins if (kBuilding.isForceTeamVoteEligible()), the effect of which is to prevent the civilopedia claiming that the UN/AP guarantee eligibility when in reality that function has been removed as described above.


As I mentioned in the original post, changing the number of election candidates can also be achieved by editing GlobalDefines.xml.

:)

EDIT: Pretty sure the bug has been removed, it seems to work properly now at re-election times.
 
Top Bottom