ModModder's Guide

Probably. There were problems with PrereqPromotionsNOTOnTile, though they might have been fixed by now. You could try PrereqUnitTypesNOTOnTile and list all Beastmaster units. I know from experience that tag works.

Well, basing it on the Class rather than the Unit Type probably isn't that important, so I could just list one Beastmaster unit (the only issue being that currently the unit is UNIT_BEASTMASTER, but at some point it will be replaced with a UU, so I'll have to remember to fix it, which is obviously not a big deal). Using Unit Class is probably the *right* way of doing it, but I'll try the Unit Type one and see if it works. Thanks.
 
If anyone's wondering, FreePromotions seem to be immune to bMustMaintain. Because I switched the UnitClassNOTOnTile to UnitTypeNOTOnTile and still didn't work until I removed the FreePromotion from the unit. I originally added it just so that the player would be aware that this was a unit that might go Barbarian on you. Since the unit automatically gets the promotion if there's no beastmaster on the square there's no other reason for it to start with it.
 
Three questions...

1) Is there a way to do a PyPerTurn function on a city, leader, civilization, or building level? None of those XML files contains a PyPerTurn tag, but I'm guessing there might be a global function that would accomplish the same thing. What I'm doing is creating a new summonable fallow civ where their city population will depend on the number of particular resources in the BFC. The way I was planning to do it was to loop through their cities each turn, count the resources, set the pop cap, and then tell it to grow one size. Any advice on how to do that, or a better way to do it?

2) How are stackable promotions handled. That is, do they sit on the unit as multiple promotions, or as one promotion with an integer that detemines how many of it there are? The main reason is, if I put a PyPerTurn on a stackable promotion, will it get called once, or one time for each "instance" of the promotion? I think it's just one instance, because stackable promotions with a 100% chance to wear off, don't. Instead of all 10 (or whatever) promotions wearing off, 1 wears off each turn, leading me to believe that it just decrements the counter (using setHasPromotion(PROMO, false)) when the promotion is supposed to wear off. This is actually good for what I'm trying to do, but it requires a little bit of jumping through hoops to have a stackable promotion that is granted by a spell (otherwise n casters could apply it every turn, one would wear off, thus a unit could have (n-1)*t + n applications on at a time, where I'm planning to limit it to n (by disabling casting while the caster maintains it and checking in the PyPerTurn that the instances of the promotion don't exceed the number of maintaining casters in the stack).

3) Maybe I'm still dense, but there's something about modular python that I just can't grasp, which is how functions with a return value can possibly work. Frex, in canBuild, you have
Code:
def canBuild(self,argsList): 
     //a bunch of stuff...
     //i.e.:
     if eCiv == Civ["Malakim"]:
 	pPlot = CyMap().plot(iX, iY)
 	if (iBuild == Improvement["Road"]):
	     if (pPlot.getTerrainType() == Terrain["Desert"]):
 	          return 0 

     //more returns etc...
     //then

        ## *******************
 	## Modular Python: ANW 29-may-2010
 	
 	for module in command['canBuild']:
 	     module.canBuild(self, argsList)
 	
 	## Modular Python End
 	## *******************
 	
	return -1 
     # Returning -1 means ignore; 0 means Build cannot be performed; 1 or greater means it can

How does this manage to do anything but ignore the return value? If I were to set something in a modular canBuild() function, assuming that it gets to that point in the function and doesn't return a 1 or 0 earlier, then no matter what I return, it's just going to ignore it and proceed down to the return -1 statement, isn't it? Am I missing something?
 
Three questions...

1) Is there a way to do a PyPerTurn function on a city, leader, civilization, or building level? None of those XML files contains a PyPerTurn tag, but I'm guessing there might be a global function that would accomplish the same thing. What I'm doing is creating a new summonable fallow civ where their city population will depend on the number of particular resources in the BFC. The way I was planning to do it was to loop through their cities each turn, count the resources, set the pop cap, and then tell it to grow one size. Any advice on how to do that, or a better way to do it?

Not particularly. You can add code into doTurn() which checks for the specific item you want.

2) How are stackable promotions handled. That is, do they sit on the unit as multiple promotions, or as one promotion with an integer that detemines how many of it there are? The main reason is, if I put a PyPerTurn on a stackable promotion, will it get called once, or one time for each "instance" of the promotion? I think it's just one instance, because stackable promotions with a 100% chance to wear off, don't. Instead of all 10 (or whatever) promotions wearing off, 1 wears off each turn, leading me to believe that it just decrements the counter (using setHasPromotion(PROMO, -1)) when the promotion is supposed to wear off. This is actually good for what I'm trying to do, but it requires a little bit of jumping through hoops to have a stackable promotion that is granted by a spell (otherwise n casters could apply it every turn, one would wear off, thus a unit could have (n-1)*t + n applications on at a time, where I'm planning to limit it to n (by disabling casting while the caster maintains it and checking in the PyPerTurn that the instances of the promotion don't exceed the number of maintaining casters in the stack).

One promotion with an integer number, like you thought.

If you need to see how to remove multiple ones each turn, just check the Mechanos or D'tesh affinities. ;)

3) Maybe I'm still dense, but there's something about modular python that I just can't grasp, which is how functions with a return value can possibly work. Frex, in canBuild, you have
Code:
def canBuild(self,argsList): 
     //a bunch of stuff...
     //i.e.:
     if eCiv == Civ["Malakim"]:
 	pPlot = CyMap().plot(iX, iY)
 	if (iBuild == Improvement["Road"]):
	     if (pPlot.getTerrainType() == Terrain["Desert"]):
 	          return 0 

     //more returns etc...
     //then

        ## *******************
 	## Modular Python: ANW 29-may-2010
 	
 	for module in command['canBuild']:
 	     module.canBuild(self, argsList)
 	
 	## Modular Python End
 	## *******************
 	
	return -1 
     # Returning -1 means ignore; 0 means Build cannot be performed; 1 or greater means it can

How does this manage to do anything but ignore the return value? If I were to set something in a modular canBuild() function, assuming that it gets to that point in the function and doesn't return a 1 or 0 earlier, then no matter what I return, it's just going to ignore it and proceed down to the return -1 statement, isn't it? Am I missing something?

Short answer: It doesn't. The only function in CvGameUtils which is properly modular (until I get around to fixing it) is cannotTrain().

The correct code should be:
Code:
		## *******************
		## Modular Python: ANW 29-may-2010
		
		for module in command['cannotTrain']:
			if module.cannotTrain(self, argsList) == True:
				return True
			
		## Modular Python End
		## *******************

Just haven't updated it in all the functions. :p If you'd like to and then submit it to me, be my guest, it will be used. :lol:
 
If anyone's wondering, FreePromotions seem to be immune to bMustMaintain. Because I switched the UnitClassNOTOnTile to UnitTypeNOTOnTile and still didn't work until I removed the FreePromotion from the unit. I originally added it just so that the player would be aware that this was a unit that might go Barbarian on you. Since the unit automatically gets the promotion if there's no beastmaster on the square there's no other reason for it to start with it.

I don't think bMustMaintain works with all of the prereq tags. At least, that's a behavior I noticed a while ago. I'm not sure I can remember which ones didn't work.
 
Short answer: It doesn't. The only function in CvGameUtils which is properly modular (until I get around to fixing it) is cannotTrain().

Just haven't updated it in all the functions. :p If you'd like to and then submit it to me, be my guest, it will be used. :lol:

I'll actually take a look and try to do that. As it turns out, I'm probably not using any of the bool functions in modular python, but I wouldn't mind helping out a bit.


I don't think bMustMaintain works with all of the prereq tags. At least, that's a behavior I noticed a while ago. I'm not sure I can remember which ones didn't work.

Well, it does work with UnitTypeNOTOnTile (I'm assuming also UnitClassNOTOnTile, but I haven't gone back to try that one again yet) - it just doesn't seem to affect FreePromotions. That makes sense in a way, it just wasn't what I was expecting.
 
MustMaintain specifically ignores any promotion in the FreePromotions for a unit, as the mod maker has stated that they get that promotion no matter what.

To have a promotion be free and yet Must Maintain, you have to set up an AutoAcquire that will naturally trigger upon unit creation (and possibly grant a free promotion which does nothing but explain that there will be an AutoAcquire there, if you want the pedia to make things nice on the user)
 
Code:
#Requirement
def reqBlaze2(caster):
	pPlot = caster.plot()
	bValid = False

#Checks if the plot contains mana
	if gc.getBonusInfo(pPlot.getBonusType(-1)).getBonusClassType() == gc.getInfoTypeForString('BONUSCLASS_MANA'):
		if pPlot.getImprovementType() == -1:
			return True
		else:
			if gc.getImprovementInfo(pPlot.getImprovementType()).isPermanent() == False:
				return True

#Checks if the plot contains city ruins
	if pPlot.getImprovementType() == gc.getInfoTypeForString('IMPROVEMENT_CITY_RUINS'):
		return True
	if pPlot.getImprovementType() == gc.getInfoTypeForString('IMPROVEMENT_GRAVEYARD'):
		return True

	iX = pPlot.getX()
	iY = pPlot.getY()

	getPlot	= CyMap().plot
	if gc.getGame().isOption(GameOptionTypes.GAMEOPTION_NO_PLOT_COUNTER):
		iBrokenLands = gc.getInfoTypeForString('TERRAIN_BROKEN_LANDS')
		iBurningSands = gc.getInfoTypeForString('TERRAIN_BURNING_SANDS')
		iFieldsOfPerdition = gc.getInfoTypeForString('TERRAIN_FIELDS_OF_PERDITION')
		iShallows = gc.getInfoTypeForString('TERRAIN_SHALLOWS')
		for iiX,iiY in RANGE1:
			pPlot = getPlot(iX+iiX,iY+iiY)
			if not pPlot.isNone():
				iTerrain = pPlot.getTerrainType()
				if (iTerrain == iBrokenLands or iTerrain == iBurningSands or iTerrain == iFieldsOfPerdition or iTerrain == iShallows):
					bValid = True
	else:
		for iiX,iiY in RANGE1:
			pPlot = getPlot(iX+iiX,iY+iiY)
			if not pPlot.isNone():
				if pPlot.getPlotCounter() > 0:
					bValid = True
	if bValid == False:
		return False
	pPlayer = gc.getPlayer(caster.getOwner())
	if not pPlayer.isHuman():
		if caster.getOwner() != pPlot.getOwner():
			return False
		if pPlayer.getCivilizationType() == gc.getInfoTypeForString('CIVILIZATION_INFERNAL'):
			return False
	return True

This code is supposed to return True if the unit is standing on a plot with mana or if the regular Sanctify conditions are fulfilled.

But it always returns false for some reason.
Any idea what could be causing it?
 
hello!

just 1 little question:

what does the free promotion code look like?
want to port it to another mod.
thanks in advance !!!

:D
 
Please, could somebody guide me to the location of the script that improves the speed of unit movement/selection?.

I wan't to check it out, if possible.
 
er... anyone? anyone?
 
er... anyone? anyone?

I am no python expert. Far from it. Can you print out log info in that routine (ie add print to a log file), or throw up a dialog box with info at various points in the funtion?

For example, it would be helpful to know which False it is returning. (if it is the later part that is an issue)

Of course, If this function is being called, and you are getting False, you know at least the Mana portion is not working.

Which doesn't make sense. It seems to be a modified copy of reqDispelMagic, (does not have a check for pPlot.getBonusType(-1) != -1 and has the extra else statement.)

Maybe try copying the code block from reqDispelMagic, to see if that works on typed nodes, before modifying that part.

I am sure you have already done this, but my first check would be to add "return True" to the first line of the function. If it still returns False -- then there is nothing wrong with the code. The function is not being called, or the caller is overriding its return value.
 
I have tested it again and here is the report.

1. Without a requirement, the spell can be cast on any tile (naturally).
2. It works in changing resources to fire mana as coded
3. It has no effect in removing any of the tiles mentioned in python (TERRAIN_BROKEN_LANDS, TERRAIN_BURNING_SANDS etc.)

However, I have found that the regular sanctify spell does not seem to remove/teraform them either. And that when I place the features using the world builder they just seem to show up like regular terrain.

WTH?

I just tested it again, with a clear ini file and everything.
Sanctify can only be cast if the unit is set to auto cast it, not manually. And the rest of my post still goes.
 
No idea honestly, I did not bother more than to copy the code over from standard sanctify and put my own on the top.

That thing was already there in the original code.

But looking at it, it seems to be a part of the code that calculates the plot to look at based on the X and Y coordinates. There is a loop down on the bottom that modifies said coordinates, since the spell is supposed to check and remove evil terrain from an area around the caster.

I could have copied it over wrong. Let me check.

No, it's there alright. Here is the original code from Sanctify:
Code:
def reqSanctify(caster):
	pPlot = caster.plot()
	bValid = False
	if pPlot.getImprovementType() == gc.getInfoTypeForString('IMPROVEMENT_CITY_RUINS'):
		return True
	if pPlot.getImprovementType() == gc.getInfoTypeForString('IMPROVEMENT_GRAVEYARD'):
		return True
	iX = pPlot.getX()
	iY = pPlot.getY()
	[COLOR="Red"]getPlot	= CyMap().plot[/COLOR]
	if gc.getGame().isOption(GameOptionTypes.GAMEOPTION_NO_PLOT_COUNTER):
		iBrokenLands = gc.getInfoTypeForString('TERRAIN_BROKEN_LANDS')
		iBurningSands = gc.getInfoTypeForString('TERRAIN_BURNING_SANDS')
		iFieldsOfPerdition = gc.getInfoTypeForString('TERRAIN_FIELDS_OF_PERDITION')
		iShallows = gc.getInfoTypeForString('TERRAIN_SHALLOWS')
		for iiX,iiY in RANGE1:
			pPlot = getPlot(iX+iiX,iY+iiY)
			if not pPlot.isNone():
				iTerrain = pPlot.getTerrainType()
				if (iTerrain == iBrokenLands or iTerrain == iBurningSands or iTerrain == iFieldsOfPerdition or iTerrain == iShallows):
					bValid = True
	else:
		for iiX,iiY in RANGE1:
			pPlot = getPlot(iX+iiX,iY+iiY)
			if not pPlot.isNone():
				if pPlot.getPlotCounter() > 0:
					bValid = True
	if bValid == False:
		return False
	pPlayer = gc.getPlayer(caster.getOwner())
	if not pPlayer.isHuman():
		if caster.getOwner() != pPlot.getOwner():
			return False
		if pPlayer.getCivilizationType() == gc.getInfoTypeForString('CIVILIZATION_INFERNAL'):
			return False
	return True
 
Well looking at the FFH code, it's done a little differently.

Code:
		for iiX in range(iX-1, iX+2, 1):
			for iiY in range(iY-1, iY+2, 1):
				pPlot = CyMap().plot(iiX,iiY)

You said that Sanctify wasn't working properly either, so maybe trying to assign the CyMap.plot() check to getPlot is not working correctly. getPlot() is also a function in the DLL, so there might be a conflict occurring. Try commenting out that getPlot assignment and changing the loop to mimic the above code.
 
Hi, I've been a long term viewer of this forum, but haven't the chance of contribute with you yet.
I came across some problems while tring to make a mod for RF Erebus, which I chose for this be the current one I'm playing with.
The First is how I can make a unlimited amounth of contructions of the same building in one city, and how I can limit it to some specific number. For Ex. Unlimited Libreries, or 3 limited forges etc. Before some one tell me it will be unbalanced, I pretend slowering the amouths of bonus from this kind of buildings and making the production price bigger.
By the way how I add a cost (in money) to the building constructions, for ex. the workers it would be necessary to hire to make it, the buying of materials etc. So we may cross around a 30 H 12 Commerce cost of a herbary for exemple.
Others more complicated inssues I will present when maybe I get more used with the modding interfaces, sorry if this questions seam a little stupid, nut I'm beggining in this modding practice.
Btw again, =p I'm having difficults in adding the buildings I made to the mod, It seam to reconize it, however I have to add it to some specific civilization to make it work, There is a way to add some class of buildings to all civs in one one only? I've seen it happens to wonders just couldn't discover how. I think it is a necessary step to make the building of this structures (other ways it can be bloked by then too) by new civs mods.

Thanks for the time, sorry if I written too much, of have made stupid questions =p
 
The First is how I can make a unlimited amounth of contructions of the same building in one city, and how I can limit it to some specific number. For Ex. Unlimited Libreries, or 3 limited forges etc. Before some one tell me it will be unbalanced, I pretend slowering the amouths of bonus from this kind of buildings and making the production price bigger.

I believe the <bNoLimit> tag is what you're looking for. In the building class definition. I don't think you can limit it to, say, 3 of a building in each city. Not via XML. bNoLimit should allow you to build it even if it already exists, but if you want to stop building if there's already 3 of them, then I think you'll need python. Somebody correct me if I'm wrong on either point - I've never used the bNoLimit tag. The only place I see it in use in RifE is for palaces, which are set to 1 per player... the bNoLimit lets you build it if it already exists, but the 1 per player means that each new one destroys the old one.

By the way how I add a cost (in money) to the building constructions, for ex. the workers it would be necessary to hire to make it, the buying of materials etc. So we may cross around a 30 H 12 Commerce cost of a herbary for exemple.
I don't think there's a good way to do that. To be honest, I think you're trying to complicate things too much. Hammers are produced each turn and consumed by production. Commerce is produced each turn and changed into gold/science/culture. It's not set up to be consumable. If you want to make a building cost some money, just add a maintenance cost. AFAIK, the best way to do that is using ObsoleteSafeCommerceChanges. Frex, to give a building a 2G upkeep cost...
Code:
<ObsoleteSafeCommerceChanges>
                <iCommerce>-2</iCommerce>
                <iCommerce>0</iCommerce>
                <iCommerce>0</iCommerce>
            </ObsoleteSafeCommerceChanges>
There might be a way to put a temporary building in the town while the building is being constructed that puts a drain on commerce, but even if it's possible, I don't see how it could possibly be worth it.

Btw again, =p I'm having difficults in adding the buildings I made to the mod, It seam to reconize it, however I have to add it to some specific civilization to make it work, There is a way to add some class of buildings to all civs in one one only? I've seen it happens to wonders just couldn't discover how. I think it is a necessary step to make the building of this structures (other ways it can be bloked by then too) by new civs mods.

Have you added the building class to the BuildingClass xml file? Make sure you set bUnique to 0. If it's 1, then only civs with a unique building of that building class will be able to build it. And make your building the default building for your building class.
 
Has anyone had any luck adding music to a module? I grabbed a 30 second sample of an mp3, saved it in what I think is the proper format, and put it into Mods/NormalModules/Myu/Sounds

Then I created Myu_Audio2DScripts.xml, Myu_AudioDefines.xml, Myu_AudioScriptSchema.xml files, linked the AudioDefine to the mp3 file, linked the Audio2D script to the AudioDefine, and linked the audio script to both leaders' diplomacy music. However, when I make contact with them, I get silence. Is this something that just won't work no matter how hard I try, or is it likely that I just missed something? I can post the xml files if someone is willing to look at them and see what I did wrong...

EDIT: Gah... I found this post: http://forums.civfanatics.com/showpost.php?p=7429111&postcount=3 and a couple of other similar ones which seem to indicate that you can't add audio files modularly. Which sucks. Does anyone know if this is still true for RifE? (I would think it wouldn't necessarily have to be, since RifE uses its own DLL and all...)
 
Dam... I just hit the same problem when adding music as you did.

Would it be possible to modify the DLL to make music modular? Anyone?
 
Back
Top Bottom