Enable disabled techs

Mark_T

Chieftain
Joined
Feb 6, 2008
Messages
28
Hi

Does anybody know, if there is anyway in python to enable a tech, that has been disabled in the xml?

Cheers
 
AFAIK, everything in XML is read-only in the game. The Python API doesn't have any setXXX() methods on the CvXXXInfo objects.
 
Ok, thanks for your reply. So I suppose, I would have to edit the SDK to add some kind of function somewhere or something.
 
Yes, but I'm not sure how much the game counts on those fields being read-only.

For example, in my mod BUG I build an internal representation of the tech in order to show the next tech each GP type will lightbulb as well as the tech they'll lightbulb once you've researched all the techs you have selected. If you enable/disable a tech, BUG won't know about it and may show you incorrect results.

The game may be doing something similar, but I don't know. Probably not since all the Firaxis code I've seen recalculates everything every time it's needed, even in the same function where it's completely unnecessary.
 
Yay, it worked. I made a setDisable() function, and I could enable a tech, disabled in the XML file, via event.

Thanks for your help.
 
What happens if that event occurs while the player is already researching the tech? Is that even possible?
 
It's not possible to research a disabled tech. It's red in the Tech screen, and you cannot click it.

I found it is not possible to disable it, while it is being researched actively. But it was possible to do some research on the tech, then switch to another tech, then disable the former tech. So for the function to be foolproof, it should stop research on the tech (if it is being actively researched), and then disable it. Dunno how to do that though.

EDIT: The popResearch function can remove the tech from the research queue, and then it can be disabled. Another problem I found though is, that when I disable a tech, and go to Main Menu to start a new game, it is still disabled in the new game. That's odd to me, but I guess I can do some kind of tech cleanup (set the techs to their proper disable-mode) at gamestart. Or perhaps there's some other way to get around this problem, that you know of?
 
Civ loads all the XML when it launches--not each time a game starts or loads. You'll need to reset the disabled status of techs in the GameStart and GameLoad events. Also need to save the state of the tech when saving the game.
 
You can store information in what's called Script Data--a single Python string--in several types of objects: CyGame, CyPlayer, CyCity, CyUnit, CyPlot, CyMap (I think). Each gets their own string to be used however you want. Civ4 will read and write it to the saved game, but it won't interpret what it means.

I highly recommend using an existing toolkit like Stone-D's Toolkit for easing the process. Someone also made an advanced version of his toolkit, and I think Jeckel has his own.
 
Yeah, I actually found that. Haven't tried it out yet, though. I also found that the disable-tech value was global, so it would affect techs for all civilizations in the game, so I have to think of something else.
 
Instead of exposing the CvInfos field (that loaded from XML) you would be a lot better off to create your own function (in CvPlayer or CvTeam) which exists just to block the tech access. Then in the check for if a player/team canResearch you have it query your boolean array before it is allowed to read the XML, and if your array says no, then the tech is blocked. Alternatively you could use an INT array which blocks the tech on a negative number, force allows the tech on a positive (even if the XML says you cannot research it) and obeys the XML on a zero.

This would allow you to avoid the issue of things persisting across savegames. The reason that one happens is that the game only reads the XML when you load BtS from the desktop and then never again till next time you load from the desktop. Thus it can never change the value back to what XML claims is proper (and you can never query the XML yourself either)
 
How can I declare the array? I copied an existing array, but they were all defined with a constant, f.ex:

m_aiCommerceFlexibleCount = new int[NUM_COMMERCE_TYPES];

but there's no NUM_TECH_TYPES constant to use?
 
Take a look at CyTeam.cpp's use of m_pabHasTech for tracking which techs the team has acquired. Here's how it gets created in CyTeam.reset():

Code:
m_pabHasTech = new bool[GC.getNumTechInfos()];

You don't need to specify the size of a single-dimensional array when declaring it--only when creating space to hold its values.

Edit: You might also want to take a step back and describe why you need to disable a tech for a player/team here. Maybe someone can provide a more complete method for achieving your actual game goal.
 
Thanks. Now I ran into another problem:

CyPlayer.cpp error C2556: 'int CyPlayer::isTechDisabled(int)' : overloaded function differs only by return type from 'bool CyPlayer::isTechDisabled(int)'
CyPlayer.cpp error C2371: 'CyPlayer::isTechDisabled' : redefinition; different basic types

I don't understand this. I have no other definition of the function, and not with a boolean return type.

I want to disable all techs and only enable them by events, according to how the player plays the game. But you are right. I haven't actually thought it all out yet.

EDIT: Strange. It compiles if I change the return type in CyPlayer.cpp to bool. It crashes on gamestart though.
EDIT 2: I think I have it.
EDIT 3: Ugh. I think I found all typing errors, but now it crashes on gamestart. I think I'll have to start over.
 
You shouldn't be able to create any function in CyPlayer.cpp without declaring it in CyPlayer.h so if you didn't do anything in CyPlayer.h at all, I would suspect that the code you are working on already had such a function created and declared, but I think it would yell at you for having 2 functions of the same name and input, so that makes no sense either.

You generated content in CvPlayer as well right? The Cy____ files are just an interface between the DLL and Python, they don't really do anything on their own.
 
Yeah, I have changes in the following files:

CvPlayer.cpp
CvPlayer.h
CyPlayer.cpp
CyPlayer.h
CyPlayerInterface1.cpp

I started over, and now I get this error:
CyPlayer.cpp error C5211: 'void CyPlayer::changeTechDisabled(int,int)' : overloaded member function not found in 'CyPlayer'

But it should be there.

EDIT: Ah, I found the error. Sorry for bugging you guys with all this.
EDIT 2: So now it has compiled, and there seems to be no errors, yet when I start a game in the Main Menu, it crashes to desktop after clicking Launch.
 
Turn on asserts when you compile your DLL. This way you'll see if an assertion is failing instead of a CTD with no information. Check how you initialize the array; that's a common pain point.

You might consider changing the array to a bool array since it is holding a boolean value, assuming that's the case. Also, you probably want this array attached to CyTeam. I don't know if you are enabling the research of a tech or the ability to acquire it at all.
 
Is there any way to stop the compiler from starting over each time I edit CvPlayer.cpp and CvPlayer.h? It's really slowing me down to have to wait about 15 minutes for each change. I use Codeblocks and MS Visual C++ Toolkit 2003.

EDIT: Hurray. It's working now, including saving and restarting.
 
Hopefully that meant you were able to turn off auto-compilation. You should be able to make as many changes as you like without your compiler doing anything and then tell it to compile all those changes at once at will.
 
Top Bottom