Banning Weapons Other Than Nukes

JoshW

Chieftain
Joined
Aug 17, 2006
Messages
23
Location
Richmond, VA, US
I believe this question has been asked before BUT for the life of me I can't find that post and I don't think it got a thorough answer when it was asked.

The question is:
"Does anyone know what the mechanism in the game is that bans nukes when the NPT resolution is passed through the UN? I.e., how does the game disallow their production to the players/AI? What I am looking for is some way to create resolutions that ban production of other weapons."

Background info:
Looking through the XML files, it seems rather clear how the game is told to force civics, to ban nukes, etc, since I have seen via one fo the UN mods that the XML file "CIV4VoteInfo.xml" uses the <ForceCivics/> command. Using some additional code, one can tell it which civics to force. The <bNoNukes>1</bNoNukes> command tells the game "this resolution bans nukes," but how the nukes become unavailable to the player/AI is a mystery to me.


UPDATE:
There is a new thread on the Mod Components forum for an initial version of a Disarmament mod. New posts should go there:

http://forums.civfanatics.com/showthread.php?t=183752
 
The games obvoiusly using some SDK code to link that XML tag with Nukes, it might be linked to an atribute of the Nuke, theirs probably a <Nuke> boolean that gives the nuke its ability and causes it to be banned.
 
JoshW said:
The question is:
"Does anyone know what the mechanism in the game is that bans nukes when the NPT resolution is passed through the UN? I.e., how does the game disallow their production to the players/AI? What I am looking for is some way to create resolutions that ban production of other weapons."

Although I'm sure this is not what you meant and you were probably referring to complete bans of other WMDs, I was just suddenly thinking of the Washington Naval Conference and the subsequent Washington Naval Treaty that limited the amount of warships countries could produce... that would be interesting if one were suddenly limited to the number of Battleships, Destroyers, and Carriers.
 
JoshW said:
I believe this question has been asked before BUT for the life of me I can't find that post and I don't think it got a thorough answer when it was asked.

The question is:
"Does anyone know what the mechanism in the game is that bans nukes when the NPT resolution is passed through the UN? I.e., how does the game disallow their production to the players/AI? What I am looking for is some way to create resolutions that ban production of other weapons."

Background info:
Looking through the XML files, it seems rather clear how the game is told to force civics, to ban nukes, etc, since I have seen via one fo the UN mods that the XML file "CIV4VoteInfo.xml" uses the <ForceCivics/> command. Using some additional code, one can tell it which civics to force. The <bNoNukes>1</bNoNukes> command tells the game "this resolution bans nukes," but how the nukes become unavailable to the player/AI is a mystery to me.

It's all done in the SDK.

When Civ4 first starts, all the different votes (from CIV4VoteInfo.xml) are read in. Their values are stored into a data structure (a c++ class called CvVoteInfo). One of the values is a boolean value about whether or not the vote disables nukes.

Whenever a vote is passed (either to enable or disable), this c++ function is called:

Code:
void CvGame::processVote(VoteTypes eVote, int iChange)
{
	int iI;

	changeTradeRoutes(GC.getVoteInfo(eVote).getTradeRoutes() * iChange);
	changeFreeTradeCount((GC.getVoteInfo(eVote).isFreeTrade()) ? iChange : 0);
	[b]changeNoNukesCount((GC.getVoteInfo(eVote).isNoNukes()) ? iChange : 0);[/b]

	for (iI = 0; iI < GC.getNumCivicInfos(); iI++)
	{
		changeForceCivicCount(((CivicTypes)iI), ((GC.getVoteInfo(eVote).isForceCivic(iI)) ? iChange : 0));
	}
}

The arguments are eVote (the vote that passed), and iChange (which will be 1 if the vote was to accept the new treaty, -1 if it was to revoke it). As you can see, "changeNoNukesCount" is a function that gets affected if the vote turns out to be a "no nukes" count. The function simply makes an integer value stored in the CvGame class 1 (or puts it back to zero if nukes were previously banned and then the ban was lifted).

You can check the value of this variable by using the CvGame::isNoNukes(). How nukes are actually allowed or disallowed to be trained is done in CvPlayer::canTrain, which is called to check for every unit if a player can or cannot build it.

Code:
if (GC.getGameINLINE().isNoNukes())
{
	if (GC.getUnitInfo(eUnit).getNukeRange() != -1)
	{
		return false;
	}
}

So, the game uses the definition of a unit with their iNukeRange value not -1 to determine if the unit is considered a "nuke".

Ok, so enough blathering. If you really want to go through with what you're doing, here is what you would have to do:

Using the SDK:
1.) Create your new resolutions in the Civ4VoteInfos.xml.
2.) Modify the SDK to allow for the Civ4VoteInfos.xml to have other tags similar to bNoNukes.
3.) Modify the CvPlayer::canTrain to disallow units in the same way that nukes are disallowed.

Without using the SDK:
1.) Create your new resolutions in the Civ4VoteInfos.xml
2.) Modify the CvGameUtils.py file. Add a dictionary of resolutions, and for each resolution their banned units, to the CvGameUtils class, and initialize it in the init:

Code:
def __init__(self): 
	self.m_dResolutionUnitBans = {
		gc.getInfoTypeForString("MY_RESOLUTION_NAME_1") : ("UNIT_BANNED_1", "UNIT_BANNED_2")
		gc.getInfoTypeForString("MY_RESOLUTION_NAME_2") : ("UNIT_BANNED_1", "UNIT_BANNED_2")
	}

3.) Modify the cannotTrainUnit function in that file to return True (meaning that the unit cannot be built) if the resolution is passed.

Code:
if not bTestVisible:
	for iVote in range(gc.getNumVoteInfos()):
		if gc.getGame().isVotePassed(iVote):
			if self.m_dResolutionUnitBans.has_key(iVote):
				for szBannedUnit in self.m_dResolutionUnitBans[iVote]:
					if gc.getInfoTypeForString(szBannedUnit) == eUnit:
						return True

Obviously, doing it without the SDK is easier, but your data for unit bans won't be stored in the XML files, and not changing the SDK means you can't add "Can't build unit!" entries to the info pane when the unit is hovered over to be trained. However, that's a small enough problem that it may not be worth going through the trouble of doing everything to change the SDK.

Note: I haven't tested any of this code, I just wrote it right in the browser, so it may not work right away, but you can probably tweak it to work correctly.
 
Are there any way to unvote the "nuke ban resolution"?
How could I force UN to revote this resolution? Is there any mod that does revoting?
 
the nuke ban "unvotes" if you put it up again and it fails.

JoshW if you are creating this mod will you create it to disalow submarines
 
Gerikes, you have my grateful thanks. I was surprised someone with such knowledge of the code would respond and so quickly! :goodjob: I will try the Python route first, as I do not believe I have the tools to edit SDK, at least on my Mac.

In regards to IrishDragon's question, if I do create a mod, (and I hope that I will) I was thinking of making several resolutions banning different kinds of weapons. Submarines and other naval vessels will certainly be one of those resolutions. What in particular is it about submarines that you dislike? I have had little experience with them in the game. I think spies will be another unit to ban. Another resolution might ban weapons that serve a solely offensive purpose, such as gunships and tanks, and another for ones which cause collateral damage, such as battleships, artillery, and bombers.
 
I think a more flexible method would be to give each Vote a boolean Array of all UnitClasses, the XML would define which if any are unbuildable for that vote. That data gets rolled up into the Game level Array which is then used for cantrain checking.

This would provide the greatest long term flexibility as each vote could arbitrarily ban any combination or Units by Class without need to refer to any specific characteristic of the Unit.
 
I had some blaring mistakes in my code that I think I've fixed, but once again I haven't really tried it out, so I'm not sure if it works.

Impaler's suggestion would be the best way to go if you want to go the SDK route. it makes more sense than the way Firaxis did it, in my opinion.
 
This could also be used for some scenarios, e.g. a medieval one replacing UN with a Christian Council, and voting to ban crossbows and some such (like the Second Council of Nice did). :)
 
Contrary to what I said in the last post I decided to go the SDK route. I have modded the SDK code in Visual Studio 2003 to the best of my ability. However the program tells me 7 errors remain, (in reality there seem to be 3 causes for the seven), and I can't find their source. Mostly they have to do with "undeclared variables" that I am pretty sure I've declared and the like. :confused:

I am submitting the modified files to whoever would be gracious enough to fix these bugs and compile the DLL and post it here in the forum. :D I have worked on the XML files necessary to make the "first revision" of this mod work.
The C++ / .h files are at:

http://h1.ripway.com/Outopian23/DLL Doing/ChangedFiles08-21.zip

As to the Python route, I cannot get that to work either, for though no errors appear on my screen, when I go into the game there is no HUD, no City Screen, no Interface at all but the terrain and units. I ended up using Gerike's python code almost exactly. If anyone wishes to post some example code which has been tested for how to do this kind of thing I would be grateful. :D
 
I fixed all those errors I spoke of in my last post and compiled the DLL in the appropriate program. I also modded the XML files to implement the changes. When I install the mod on my copy of Civ4 on my Mac however, the game fails to load the GameTextInfos file and the VoteInfos file. This is discouraging, however I also modded the GameInfoSchema, UnitInfo, and UnitSchema files and the game does not complain about these. :confused:

Is this just my Mac? I have placed a link in this post to the mod in its present form as a ZIP file:

http://h1.ripway.com/Outopian23/NoSeigeXMLMod.zip

which contains the new DLL and XML files. This mod is supposed to ban weapons which cause collateral damage.

Try it out! :)
 
Josh, have you tried making changes to your GameTxtMgr files (.cpp and .h)? As this seems a likely cause of the problem.
Beyond this, I would also look in the GameTextInfo.xml and VoteInfos.xml files, and just make sure that you have added in all the new Tags you have created in SDK-as my own personal experience would suggest that this is where you are going wrong. Best of luck :).

Aussie_Lurker.
 
JoshW said:
I fixed all those errors I spoke of in my last post and compiled the DLL in the appropriate program. I also modded the XML files to implement the changes. When I install the mod on my copy of Civ4 on my Mac however, the game fails to load the GameTextInfos file and the VoteInfos file. This is discouraging, however I also modded the GameInfoSchema, UnitInfo, and UnitSchema files and the game does not complain about these. :confused:

Is this just my Mac? I have placed a link in this post to the mod in its present form as a ZIP file:

http://h1.ripway.com/Outopian23/NoSeigeXMLMod.zip

which contains the new DLL and XML files. This mod is supposed to ban weapons which cause collateral damage.

Try it out! :)

Bandwidth exceeded. Also, you're trying this on a mac? I don't believe that mac's work with mods with DLL's, although I'm not sure on this.
 
Sorry guys,

This link to the mod file should work:
http://forums.civfanatics.com/uploads/98311/1156313259.zip

As to Gerike's references of DLLs and Macs, I think I have proved that he is right, that DLL mods do not work with the Mac Version. I removed entirely the CvGameCoreDLL.dll file from the Assets folder of my Mac game and ran the program -- it runs fine without it. I thought there was no such thing as a useless file but..... :mad:

So that leaves me back at square one. I know so very little about Python that I would literally need someone else to write some example code that would fully accomplish some type of weapons ban, which I could then modify to my purposes. If anyone would be that helpful, I would be very grateful. My gratitude might even have some material expression... :mischief:
 
JoshW said:
Sorry guys,

This link to the mod file should work:
http://forums.civfanatics.com/uploads/98311/1156313259.zip

As to Gerike's references of DLLs and Macs, I think I have proved that he is right, that DLL mods do not work with the Mac Version. I removed entirely the CvGameCoreDLL.dll file from the Assets folder of my Mac game and ran the program -- it runs fine without it. I thought there was no such thing as a useless file but..... :mad:

So that leaves me back at square one. I know so very little about Python that I would literally need someone else to write some example code that would fully accomplish some type of weapons ban, which I could then modify to my purposes. If anyone would be that helpful, I would be very grateful. My gratitude might even have some material expression... :mischief:

Check out the code in post 4. Python, IMO, is easier than c++, and if you know c++ it's just a matter of learning the python foibles (indentation, lists, dictionaries, etc.)

In the first code snippet:

Code:
def __init__(self): 
	self.m_dResolutionUnitBans = {
		gc.getInfoTypeForString("MY_RESOLUTION_NAME_1") : ("UNIT_BANNED_1", "UNIT_BANNED_2")
		gc.getInfoTypeForString("MY_RESOLUTION_NAME_2") : ("UNIT_BANNED_1", "UNIT_BANNED_2")
	}

Here, all I've done is made a local variable for the class CvGameUtils (in python, "self" is like "this", except it's used a lot more, such as the first argument in every member function). The function __init__ can be thought of as a constructor.

m_dResolutionUnitBans is a dictionary (think map). It's located in the self object, thus it's a member variable of that class. The keys are simple integers that represent the resolution number, and the data for each key is a tuple (think static array) of strings that are the units that are banned by that resolution. So, if you were to call self.m_dResolutionUnitBans[0], you'd get a tuple of strings that are all the units that should be banned from that vote.

Now, the second, written in the cannotTrainUnit function:

Code:
if not bTestVisible:
	for iVote in range(gc.getNumVoteInfos()):
		if gc.getGame().isVotePassed(iVote):
			if self.m_dResolutionUnitBans.has_key(iVote):
				for szBannedUnit in self.m_dResolutionUnitBans[iVote]:
					if gc.getInfoTypeForString(szBannedUnit) == eUnit:
						return True

The pseudo-code:

Code:
If the bVisible flag is True*
	Loop through all the possible votes:
		If that vote has been passed:
			If the vote has known banned units:
				for each of the strings representing banned units:
					If this unit is one of those banned units:
						return True (meaning we cannot train this unit)

*The bVisible flag is used to differentiate if we're testing to show the button or to enable the button. Normally, when testing, two passes are made. The first is with bVisible as True. If this is successful, than the button for unit training will show up in the city screen. If not, than it will not show up at all.

If the button is determined to be able to show up, than it is also checked a second time, this time with bVisible as false. If this also returns true, than the unit will be trainable. If this returns false, than we'll be able to see the unit, but it will be "greyed out".

The code above means that a unit that is banned can be shown, but will be greyed out, since it only goes through the task of checking for banned units when the bVisible flag is false.
 
Ha, you and your 'pseudo-code' Gerikes ;) :p. To be honest, I have had more success in the month or so that I have been using SDK than in the previous 3 months of using python-so I guess it just goes to show ;)!

Aussie_Lurker.
 
I have just spent the last seven hours trying to implement the python code from Gerikes. :cry: :cry: For some reason if I enter it just the way he put it it causes none of my interface to appear in game or any of the splash videos in the beginning. So I go back to the code and make a few tweaks and run it again. Eventually I got to a point where I could use the No_Nukes resolution to also ban bombers. But then I tried to make it fit with my new resolutions and it didn't work. Now I can't even get it to work with the original No_Nukes resolution. There is no discernable pattern to me as to why it will do this and why it will not. I feel sick. :mad: :cry: :sad:
 
JoshW said:
I have just spent the last seven hours trying to implement the python code from Gerikes. :cry: :cry: For some reason if I enter it just the way he put it it causes none of my interface to appear in game or any of the splash videos in the beginning. So I go back to the code and make a few tweaks and run it again. Eventually I got to a point where I could use the No_Nukes resolution to also ban bombers. But then I tried to make it fit with my new resolutions and it didn't work. Now I can't even get it to work with the original No_Nukes resolution. There is no discernable pattern to me as to why it will do this and why it will not. I feel sick. :mad: :cry: :sad:

The "no interfaces appear" is probably because there's a syntax error in the code. Go into your ini file and make sure that the debugging options are on. Here are my options:

; Set to 1 for no python exception popups
HidePythonExceptions = 0

...

; Enable the logging system
LoggingEnabled = 1

; Enable synchronization logging
SynchLog = 1

; Overwrite old network and message logs
OverwriteLogs = 1

; Enable rand event logging
RandLog = 1

; Enable message logging
MessageLog = 1


-----

Because there's a syntax error somewhere, the python files aren't completely loading, and thus the interface won't be constructed. Fix the errors, and the python files load.

Try posting the file you changed here, I might have time to take a look at it.
 
Back
Top Bottom