Questions about using fake wonders for trait abilities

Xyth

History Rewritten
Joined
Jul 14, 2004
Messages
4,106
Location
Aotearoa
In my mod I currently use a number of fake buildings to provide leader trait effects that I'm unable to achieve via xml or directly in Python. This works well via onCityBuilt and onCityAcquired. However, there are some civilization-wide building effects (extra commerce from specialists, reduced hurry costs, etc) that I'd like to use but obviously having one of these 'fake wonders' in every city would cause these effects to stack undesirably. So I need to adapt my python code to handle just one instance of such a building.

I figure the most straightforward method is to leave the fake wonder in the starting city and should the player lose the starting city, place a new version of the fake wonder in another city (capital?). I don't want to replace the Palace itself as that leads to a lot of misleading information in tooltips and the pedia. Anyway, this has lead to a few questions:

• Firstly, is there a more appropriate way of doing this?
• To detect the loss of a fake wonder could I use onCityLost instead of onCityAcquired
and onCityRazed?
• Is one of the those events triggered early enough to allow a check to see whether a certain building was present?
• Are xml tags like <iMaxPlayerInstances> obeyed when placing a building via setNumRealBuilding?
• Is there some method of finding out where the former capital was when the Palace is moved to a new city?
• Is there some method of identifying a player's capital without looping through all cities?
• Is there anything else I need to consider?
 
My advice would probably be to use the capital for the wonder, and you can always find the capital with CyPlayer.getCapitalCity(). If you store the current capital in some variable or attribute (perhaps an array that holds the capitals of all players, indexed by Player ID) you can check whether or not the capital has changed at beginPlayerTurn - and if it has, just use CyCity.setNumRealBuilding() to set the number of instances to exactly one.
 
My advice would probably be to use the capital for the wonder, and you can always find the capital with CyPlayer.getCapitalCity(). If you store the current capital in some variable or attribute (perhaps an array that holds the capitals of all players, indexed by Player ID) you can check whether or not the capital has changed at beginPlayerTurn - and if it has, just use CyCity.setNumRealBuilding() to set the number of instances to exactly one.

Hmm that makes sense. I don't know how to store variables/attributes in a way that could survive a save/load process but it occurs to me that instead I could simply do a check at beginPlayerTurn that sees if the current capital has the fake wonder present, and if not, place it there.

Does using CyCity.setNumRealBuilding() also remove any previous instance of the wonder if <iMaxPlayerInstances> is set to 1? Or does that have to be handled separately?
 
Hmm that makes sense. I don't know how to store variables/attributes in a way that could survive a save/load process but it occurs to me that instead I could simply do a check at beginPlayerTurn that sees if the current capital has the fake wonder present, and if not, place it there.
You don't need to carry this information over from a save game - simply set it up at game initialization.

Your approach should also work.

Does using CyCity.setNumRealBuilding() also remove any previous instance of the wonder if <iMaxPlayerInstances> is set to 1? Or does that have to be handled separately?
I don't think this is even an issue, so I wouldn't worry about it unless you actually run into troubles. Because if the number of buildings is 1 and you change it to the same value, then nothing really happens. As long as you use the number 1 there will never be more than... 1. So no multiple buildings and no conflicts anywhere.
 
I don't think this is even an issue, so I wouldn't worry about it unless you actually run into troubles. Because if the number of buildings is 1 and you change it to the same value, then nothing really happens. As long as you use the number 1 there will never be more than... 1. So no multiple buildings and no conflicts anywhere.

What I'm meaning is that, say the Nubian capital is Kerma and the fake wonder is initially placed there. The Nubian leader later builds a new palace in Napata making that the capital and the onBeginTurn script places a new fake wonder there via setNumRealBuilding?. What happens to the one in Kerma?

Sorry for my confusion ><
 
After some testing I can confirm that CyCity.setNumRealBuilding() doesn't pay any attention to the <iMaxPlayerInstances> tags, previous instances of the fake wonder are not removed. So I'd need some way of detecting where the old capital was if I use this method.

I think I'll try out onCityLost first, seems more intuitive to me.
 
I don't want to replace the Palace itself as that leads to a lot of misleading information in tooltips and the pedia.

Then add a new palace like building :D.
That you get a single free instance of the building is controlled in CivilizationInfos, take a look there at the palace ;).
 
Ok, now I see the problem.

You pretty much need to have the data on the current capital for each player in order for this to work properly. So you set up an array of None capital sites at startup, and then check this against each player's current capital on each beginPlayerTurn callup. If the previous value is None, then replace it with the return value of CyPlayer.getCapitalCity(). If the value instead is another CyCity instance, then you have a hit and need to move the wonder and replace the old value with the new capital CyCity object.

There is no need to store this data with saved games, as far as I can see. Otherwise you can simply populate the array of capital CyCity objects at onGameStart.

Is this for a scenario or a mod, by the way? Because if there is a WBS, then you already know what players are eligible for the wonder/effect. Then it becomes that much easier.
 
Then add a new palace like building :D.
That you get a single free instance of the building is controlled in CivilizationInfos, take a look there at the palace ;).

That works for assigning such buildings to civilizations but I'm trying to assign them only to leaders with a specific trait. Thanks though :)

You pretty much need to have the data on the current capital for each player in order for this to work properly. So you set up an array of None capital sites at startup, and then check this against each player's current capital on each beginPlayerTurn callup. If the previous value is None, then replace it with the return value of CyPlayer.getCapitalCity(). If the value instead is another CyCity instance, then you have a hit and need to move the wonder and replace the old value with the new capital CyCity object..

While I understand roughly what you're saying I'm unsure how to actually code this. Any chance you could give an example in code?

Is this for a scenario or a mod, by the way? Because if there is a WBS, then you already know what players are eligible for the wonder/effect. Then it becomes that much easier.

It's for a mod. What's a WBS?
 
While I understand roughly what you're saying I'm unsure how to actually code this. Any chance you could give an example in code?
Either read up on Python (the bare basics) or have someone else do it for you. It would take more time to explain what the documentation at Python.org or any textbook teaches, than to simply do the code and be done with it.

If you can hold off a week or two I will be able to do any Python scripting you might need for you. It'd be my pleasure, actually, since I'm having coding withdrawals like you wouldn't believe right now. :p
It's for a mod. What's a WBS?
Ok, then the players with this trait would change with every game.

WBS stands of World Builder Save file. Basically a map - also known as a scenario, with present land/terrain and possibly cities/units. Its different from a save game though, even if you can save any gave as a scenario by launching the World Builder in mid-game.
 
Either read up on Python (the bare basics) or have someone else do it for you. It would take more time to explain what the documentation at Python.org or any textbook teaches, than to simply do the code and be done with it.

If you can hold off a week or two I will be able to do any Python scripting you might need for you. It'd be my pleasure, actually, since I'm having coding withdrawals like you wouldn't believe right now. :p

No worries, I'm doing some reading and having a go at writing it myself. If I'm still struggling in a week or two I'll come back and take you up on that offer :)
 
Read up on data structures (lists, tuples, dictinaries, that sort of thing) and Object-Oriented Programming (classes and methods) in particular. Because then the whole thing will make all that much more sense.
 
I've done something similar to this working around a palace UB in the XML - it was a bit awkward but did the job for what I wanted. The main issue was as you point out using a UB makes it civ-targeted and not leader-targeted. I had to swap one trait of about half the leaders, so e.g. all the Americans were expansive, French industrious, English financial etc. I thought that wasn't too much of a problem though because the abilities were getting altered so much the old traits were pretty much irrelevant anyway!
 
Back
Top Bottom