Python Wonders and their effects

seasnake

Conquistador
Joined
Apr 21, 2006
Messages
2,003
Location
California, United States
Hi, question:

There are several python wonders by Tsentom1 and others that make use of the "onBuildingBuilt" tag in the EventManager in python. Thus you build a wonder and you get some goodies.

I want something that would work for just having the building, not necessarily building it. I'm making a mod where each civ starts with it's own unique palace, and my hope is to make it so that having the building from the start, with the Settler automatically building it, results in you getting the effect. My goal is for effects like the Djenne Mosque wonder by Tsentom1, namely as long as you have the palace you get better production from desert tiles (this is for the Arabs).

Any ideas on how to make these effects tie into ownership of a building rather than building the building?
 
Yeah, Jarlaxe Baenre is absolutely right. There is no reason to tie the effect to a building/wonder/whatever. That sort of thing is what you do when you try to create effects with XML modding.

What you plan to do is basically Unique Powers like those in RFC. Nothing is prohibiting you from giving each Civ their own Palace though...

Also, what you do in onBuildingBuilt() is to "activate" whatever power the wonder is granting. The actual effect would be triggered by some other game event, like a new game turn, a unit killed, a city conquered, or whatever. Again, look at Rhye's code in UniquePowers.py (RFC) - but note that you can skip the class (and the self references) entirely... Give a holler if you need help setting this up.
 
Thanks for the advice. My point is each civ has in this mod already has their own palace. The problem is when you found your first city, say as America it founds Washington, it will put the palace in the city but it will not trigger the OnBuildingBuilt Python Tag, nor if it is moved to another city (i.e. Washington is taken, goes to New York). If you actually build the palace in a new city, it will trigger the effect. I was just wondering if there was a way to building ownership to an effect, like something where at the beginning of each turn the game says "if X owns the Palace_America, then plains tiles have 1 extra hammer" because I've tried to implement that through "if X builds the Palace_America" but I don't get the effect that way unless I choose to build my palace in a different city.

I'll look at the code in RFC Baldyr, and I'll let you know what happens.
 
Yeah, but I still don't see any good reason to add these effects to the Palace. They are individual and unique powers, always active (once the first city is built).
 
Yeah, but I still don't see any good reason to add these effects to the Palace. They are individual and unique powers, always active (once the first city is built).

Well, mostly because I've had some experience anchoring things to buildings, taking wonders like School of Confucius and applying the code to other things. But I see your point, if you just anchor it to the trait (every civ has a unique trait, like TRAIT_ENGLAND) then it should be okay.
 
Since your leaving the confines of the XML modding you don't need to "anchor" anything to anything else. You use the player ID instead. This is actually the point of learning programming - you get to do whatever you want. (Even if you really need to know C++ :rolleyes:)
 
Okay, so in Rise and Fall i've found the unique powers tags.

def arabianUP(self, city):
pArabia = gc.getPlayer(iArabia)

So what if I went into the CvEventManager and put that tag underneath and tabbed below this one

def onGameStart(self, argsList):

Does that mean that one game start, it will check and see if a person is arabia? And if that person is arabia, then it will activate that special ability. So it looks like this?

def onGameStart(self, argsList):
'Called at the start of the game'
if (gc.getGame().getGameTurnYear() == gc.getDefineINT("START_YEAR") and not gc.getGame().isOption(GameOptionTypes.GAMEOPTION_ADVANCED_START)):
for iPlayer in range(gc.getMAX_PLAYERS()):
player = gc.getPlayer(iPlayer)
if (player.isAlive() and player.isHuman()):
popupInfo = CyPopupInfo()
popupInfo.setButtonPopupType(ButtonPopupTypes.BUTTONPOPUP_PYTHON_SCREEN)
popupInfo.setText(u"showDawnOfMan")
popupInfo.addPopup(iPlayer)
else:
CyInterface().setSoundSelectionReady(true)

if gc.getGame().isPbem():
for iPlayer in range(gc.getMAX_PLAYERS()):
player = gc.getPlayer(iPlayer)
if (player.isAlive() and player.isHuman()):
popupInfo = CyPopupInfo()
popupInfo.setButtonPopupType(ButtonPopupTypes.BUTTONPOPUP_DETAILS)
popupInfo.setOption1(true)
popupInfo.addPopup(iPlayer)

def arabianUP(self, city):
pArabia = gc.getPlayer(iArabia)
tt_desert = gc.getInfoTypeForString( 'TERRAIN_DESERT' )

for iXLoop in range(iX - 2, iX + 3, 1):
for iYLoop in range(iY - 2, iY + 3, 1):
pPlot = CyMap().plot(iXLoop, iYLoop)
if ( pPlot.isPlayerCityRadius(pPID)==true ):
if ( pPlot.getTeam()==pTID ):
if ( pPlot.getTerrainType()==tt_desert ):
CyGame().setPlotExtraYield(iXLoop, iYLoop, YieldTypes.YIELD_COMMERCE, 2)



CvAdvisorUtils.resetNoLiberateCities()
 
If you're gonna do programming you should probably start with learning programming. Just trying random thing out will get you nowhere.

edit: So you could either ask for help getting started with programming - or you could just ask for the actual code you need. I'd be glad to help with either, and so would others. But to debug some code you copy-pasted from some other mod is just a waste of everyone's time.
 
Another advice:
Instead of binding the effect to a building being built, you can also attach it to a city being found, and check if it's the first city, that works too ;).

Does then look for example somehow like that:
PHP:
	def onCityBuilt(self, argsList):
                print 'onCityBuilt'
		'City Built'
		city = argsList[0]
###new code		
		icurplayer = city.getOwner ()
		curplayer = gc.getPlayer(icurplayer)
		if curplayer.getNumCities ()==1:                        
                        myName = curplayer.getCivilizationType ()
                        america = gc.getInfoTypeForString("CIVILIZATION_AMERICA")                                    
                        if myName == america:
                                curplayer.foundReligion(1,1,True)
 
The Code I need is a pretty tall order, too tall I think to merely ask for.

If you are interested in helping with the python would you like to get a co-author credit for my new mod, Glory and Greatness? What it does is it adds six civs, merges in Next War, Chuggi's better graphics, Cultural Citystyles, Rise of Empires, and Bluemarble to the RevolutionsDCM base. Then each civ is reduced to one leader, given either 2 extra UUs or one UU and UB, and then given unique powers.

So you have an idea, here's some screenshots of what's been done. First is the main menu, second is America, which is completely done. I've given each civ their own version of the Palace and a Unique Tech so I could modify things through XML. Third is the new Washington and America's Powers, which work very well. Fourth is the Mech from Nextwar, which is now in. Last is an example of the South/Native American artstyle standing on Blue Marble.

Not all civs need Python changes, but some do. My goal was to simply copy the code from some of Tsentom's Python Wonders and replace the building with the appropriate palace to make sure that Civ enjoys those bonuses. However, if you have a better way and our interested I'd appreciate the help. I could send a wish list of what I was trying to do and how I was hoping to get it done, and we could go from there.
 

Attachments

  • Civ4ScreenShot0020.JPG
    Civ4ScreenShot0020.JPG
    116.9 KB · Views: 57
  • Civ4ScreenShot0016.JPG
    Civ4ScreenShot0016.JPG
    192.9 KB · Views: 62
  • Civ4ScreenShot0017.JPG
    Civ4ScreenShot0017.JPG
    156.2 KB · Views: 53
  • Civ4ScreenShot0018.JPG
    Civ4ScreenShot0018.JPG
    161.9 KB · Views: 53
  • Civ4ScreenShot0019.JPG
    Civ4ScreenShot0019.JPG
    258.7 KB · Views: 63
Another advice:
Instead of binding the effect to a building being built, you can also attach it to a city being found, and check if it's the first city, that works too ;).

Does then look for example somehow like that:
PHP:
	def onCityBuilt(self, argsList):
                print 'onCityBuilt'
		'City Built'
		city = argsList[0]
###new code		
		icurplayer = city.getOwner ()
		curplayer = gc.getPlayer(icurplayer)
		if curplayer.getNumCities ()==1:                        
                        myName = curplayer.getCivilizationType ()
                        america = gc.getInfoTypeForString("CIVILIZATION_AMERICA")                                    
                        if myName == america:
                                curplayer.foundReligion(1,1,True)

Thanks for that, I'll try a few things with it and see how they work.
 
Sure, we could start with discussing the powers you need scripted. I think this thread is as good a place as any - and others could join in with their insights as well. But if you wanna keep your design between four eyes you can just PM me.

The main thing would probably be to figure out what is doable with Python, XML and C++ respectively. If you can find a XML solution then you should probably explore that further. If I can contribute with some Python code, then I'm up for it. (Heck, programming is fun!) But if you need to edit the SDK you probably wanna rethink your approach - unless you can get someone else to do all of that for you. (And you might.)
 
With Python you're actually quite limited as to what effects you can have for your powers. The things that are available include granting free commerce yields (:gold::science::culture::espionage:) to all cities belonging to a player, adding bonuses to buildings in cities, and adding bonuses to the cities themselves. Among other things.

What you tried to do with adding bonuses to map tiles is actually not that efficient, because the change is both inexact (some tiles outside of the BFC are added with the code you copy-pasted) and will remain even if some other player controls those tiles. So this is really an example of a power that really should be done in the SDK in order to work as intended. (The alternative would be to create a Python script that looks up all tiles every single turn and adjust the tile yields accordingly. This would cause some serious lag however.)

You could actually look up the CivIV Python API yourself as to what methods are available.
 
Okay Baldyr, let's do this. These are the civs whose powers I don't know how to accomplish with XML or Python.

Arabs: Bonus food and commerce from Desert Tiles
China: Start game with 2 sources of Silk.
Gran Colombia: No Revolting in Captured cities
Germany: 50 percent chance to capture barbs and earn gold
Japan: 20 percent chance for a unit to heal fully after combat victory (but I think I've got a good idea for this based on Tsentom's Jaguar Temple).
Maya: 25 percent chance to enslave unit (turns land units into workers).
Netherlands: 3 percent interest on gold reserves
Ottomans:O Chance to capture enemy ships and earn gold, spread culture quickly to conquered city.
Russia: Units in Russia with whom Russia is at war take damage.
Sumeria: Each city is a source of freshwater for farming purposes.
Zulu: Extra movement for melee units.

Included is the complete list as a Word attachment, but I think everything else can be done with XML OR I can figure it out with what limited Python I know.
 

Attachments

Arabs: Bonus food and commerce from Desert Tiles
As stated before, this is not a very good candidate for a Python mod. You either get lag or something that really doesn't do what it advertises... The problem is that once you add the bonuses to the tiles they won't disappear by themselves when the changes owners.

You could alternatively redefine the effect for this particular power. Like that all desert tiles adjacent to any city founded by the Arabs, or something...
China: Start game with 2 sources of Silk.
What do you mean by this? Does the original city site get the resources within its BFC or does the player always have access to 2 free Silk resources? :confused:
Gran Colombia: No Revolting in Captured cities
This has been done before, right? Then it should be possible to replicate.
Germany: 50 percent chance to capture barbs and earn gold
You mean get a similar unit when defeating a barbarian unit? What is the gold for? :confused:
Japan: 20 percent chance for a unit to heal fully after combat victory (but I think I've got a good idea for this based on Tsentom's Jaguar Temple).
This should be relatively easy to achieve.
Maya: 25 percent chance to enslave unit (turns land units into workers).
Basically same as Germany, then.
Netherlands: 3 percent interest on gold reserves
How will this income be declared? Is it simply added in between turns or does it show in the domestic advisor, or something?
Ottomans:O Chance to capture enemy ships and earn gold, spread culture quickly to conquered city.
Sounds like a Python job to me.
Russia: Units in Russia with whom Russia is at war take damage.
Is suggest we do something along these lines.
Sumeria: Each city is a source of freshwater for farming purposes.
Hmm... I can't really tell whether or not this is a good idea (with Python in mind). I'm guessing you add the fresh water thing to the city tile, but then it should be removed if the city is lost, right?
Zulu: Extra movement for melee units.
This would have to be done every time a unit is created, but should basically be doable.

If you know pre-existing code for any of the above, I would like to look at it. Even if I probably will rewrite the code there still is no reason to reinvent the wheel, so to speak. A good implementation is still a good implementation, even if the specifics of variables, helper functions and such will differ.

Included is the complete list as a Word attachment, but I think everything else can be done with XML OR I can figure it out with what limited Python I know.
What powers do you think that you can do yourself - with Python? If you have some functioning code I could add that to the powers module right away. Otherwise I could make room by making empty functions for them. (That you can fill with code later.)
 
As stated before, this is not a very good candidate for a Python mod. You either get lag or something that really doesn't do what it advertises... The problem is that once you add the bonuses to the tiles they won't disappear by themselves when the changes owners. You could alternatively redefine the effect for this particular power. Like that all desert tiles adjacent to any city founded by the Arabs, or something...

I actually have a wonder that does this already in the game, trans-siberian railroad, and it improves tundra tiles and camp resources and ocean resources. It's all Python from Tsentom's Ice Hotel wonder. I've played a game with this wonder and it hasn't caused any significant lag that I've experienced.

What do you mean by this? Does the original city site get the resources within its BFC or does the player always have access to 2 free Silk resources? :confused:

Now that I'm reading your quote of course you're confused. This can be completely done in XML, I'll just have the China palace give a source of silk at two of them. Don't know why I posted it.

This has been done before, right? Then it should be possible to replicate.

I think so. I've got it set in my other mod so that if you have the civic Vassalage there is no revolt when the city is taken over. I think I know enough to edit that to rely on a Trait instead, like Trait_Colombia. But I've never tried it.

You mean get a similar unit when defeating a barbarian unit? What is the gold for? :confused:

What I'm looking for is something where if you kill a barbarian unit, you have a chance of the unit joining your side and earning and immediate 10 gold to your treasury. So if I kill a barbarian warrior I have a 20 percent chance of getting a warrior unit. Applies to land units only.

This should be relatively easy to achieve.

Actually, I think it is.

Basically same as Germany, then.

With two significant differences: First it doesn't work against barbarians, but civs you're at war with. The Germany one ONLY works against barbs. Second, you don't get that unit type, you get a worker. So if I kill a Khmer warrior, I have a 25 percent chance of getting a worker.

How will this income be declared? Is it simply added in between turns or does it show in the domestic advisor, or something?

I figured it would simply be added on, so if you have 100 dollars on one turn you get an additional 3 gold showing up the next turn. It sees how much money you have banked in your treasury when you click end turn and it adds the appropriate amount.

Sounds like a Python job to me.

Yup, we talked about it a little at one point.

Is suggest we do something along these lines.

Looks good to me. Seems that tying the damage to trying to move through Russia is pretty much how Russian Winter worked.

Hmm... I can't really tell whether or not this is a good idea (with Python in mind). I'm guessing you add the fresh water thing to the city tile, but then it should be removed if the city is lost, right?

Right. Something like "If owner is Sumeria, then City creates source of Fresh Water."

This would have to be done every time a unit is created, but should basically be doable.

Cool, I've got the python in place to make Ships move one farther per turn thanks to Tsentom's Seafaring trait (Englands UP), but I'm having trouble applying to other types of units (like Melee, etc.).

If you know pre-existing code for any of the above, I would like to look at it. Even if I probably will rewrite the code there still is no reason to reinvent the wheel, so to speak. A good implementation is still a good implementation, even if the specifics of variables, helper functions and such will differ.

I have several modcomps downloaded off the site, but almost all of them deal with EventManager.

What powers do you think that you can do yourself - with Python? If you have some functioning code I could add that to the powers module right away. Otherwise I could make room by making empty functions for them. (That you can fill with code later.)

I don't think I am capable of making any of these things as unique powers, rather I can use EventManager to tie these abilities to having a trait, building, etc. I can do Japan's UP not by creating a player-specific code, but by say using existing work done by other modders. In the Spoiler is an example of how I intend to create Japan's Units 20 percent chance to heal fully:

Spoiler :
def onCombatResult(self, argsList):
'Combat Result'
pWinner,pLoser = argsList
playerX = PyPlayer(pWinner.getOwner())
unitX = PyInfo.UnitInfo(pWinner.getUnitType())
playerY = PyPlayer(pLoser.getOwner())
unitY = PyInfo.UnitInfo(pLoser.getUnitType())

## JAPAN Start ##

pPlayer = gc.getPlayer(pWinner.getOwner())

b_Jaguar = gc.getInfoTypeForString("BUILDING_PALACE_JAPAN")
obsoleteTech = gc.getBuildingInfo(b_Jaguar).getObsoleteTech()

if ( gc.getTeam(pPlayer.getTeam()).isHasTech(obsoleteTech) == false or obsoleteTech == -1 ):
for iCity in range(pPlayer.getNumCities()):
ppCity = pPlayer.getCity(iCity)
if ppCity.getNumActiveBuilding(b_Jaguar) == true:

self.iHealChance = self.getRandomNumber( 4 )

if self.iHealChance == 0:

pWinner.setDamage(0, False)

## JAPAN End ##


Everything I think I can do in Python will be like this in the EventManager. Other than that I know of no other code to do things like the Ottoman Culture or Russian Winter..
 
Back
Top Bottom