ModModder's Guide

Will have to overwrite it, unfortunately.

What does that mean? Do you mean like you did with modular python where you made the code somehow work some magic beyond my understanding or do you mean something else?
 
Oh well.
The list keeps mounting anyway.


BTW, could someone look at the code of Sanctify and tell me how to hell it works.
I mean, I tried understanding it, but I have newer cast the spell in RIFE at all, and I may have even broken something with it since I can't get the spell to work for me at all, even with my module detached. (hence my idea for a spell that would be sanctify + other effects is down for now)


Edit: It appears that the sound XML files also don't support comments.
 
Hey Eugene, Sorry for taking a time to reply. Any way thank you for the answer, I understood that I should probably have to make a adtional tag "<imaxbuildingspercity>" kind of in python or SDK, I just still don't know how to do that. I ll search for some tutorials to do that.
Err... I know I made a complication, but my planned mod is much more complicated then that. I just made that question here for I wanted to have some help with a first test. It ended up with needing to do a lot of new tags and some more complicated workings in code. But with the time I'm sure it will be all done.
Yeah, I made a mistake with the tag of limit I think, the others buildings were going fine.

Really thanks. I will try to make better questions in time.
 
Faladh - I really think what you're trying to do is more trouble than it's worth, but feel free to give it a go. One of the beauties of modding Civ IV is that sometimes people find a way to do things that looked impossible. If you're going to try and add a max number per city of a building, you may be able to do it with python. It wouldn't be in the xml, so it wouldn't normally be visible to the player, but you can add a Help tag to the building that says something like "You may build 3 of these in each city". Then the question is counting the building in python... I don't know know if that's possible, but it's worth a look.

PPQ - When you add your lines to the audio xml files, send them to me and I'll send you my audio xml lines and we can merge them in. That way, when either mod is installed, the audio xml files will have to overwrite RifE's audio xml, but both will be the same so we won't overwrite each other's changes. From what I've read, it doesn't cause a problem if the files don't exist (you can put the files in your own mods directory like normal). Unfortunately, I don't remember if it's possible to unzip files to a parent directory (like, unzip this file to "RifE\Assets\Modules\NormalModules\", but store the path to the audio xml as "..\..\Audio\"). If so, that's easy enough, but if not, I think it might require an installer for the mod, which seems like overkill.
 
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:

This is done. I'll be sending it to you in a PM. Most of the functions are pretty straightforward - keep calling modular functions until you get one that isn't the same as the default return for the function. A few of them are additive, and one or two I wasn't sure if they should add or replace the default value. The sticky ones were AI_chooseTech and the similar function for production - I feel like the modular python calls should go higher up in the function (probably right after the civ specific stuff and before the function is just grasping at "hey, maybe we should get Gunpowder?"), but without knowing the functions too well, I didn't want to mess with them too much.

Doing a little more testing to make sure I didn't leave out a colon or something while I also test out another project I'm working on (modular flavour start), which is almost done.

Edit: Silly me. Doesn't look like you can send a file via PM. Attaching it here, since it's not like it's secret or anything.
 
oh plz dont tell me CvEventManager.py isnt complely modular...
it took me a lot of time to find out that some functions like:

def onUnitPillage(self, argsList):

aren't modular... :(

a few functions i need for my module(s) are missing some magic lines at the end (for module in command['stuff']: ... )

for my modules i additionaly need:

onLoadGame
onGameStart
onCityAcquiredAndKept
onImprovementDestroyed
onUnitPillage

is there something that can be done about this?
 
edit2:
Well, ignore this post. I found my mistake... lol
Spoiler :
It seems I found a little climate related compatibility bug in one of my modules. In a few cases I used pPlot.setTempTerrainType(i_Terrain, CyGame().getSorenRandNum(10, "timer") + 10) to change some plots temporaly but now if I use it that way it will give me a python exception when mouse-over the plot:
Traceback (most recent call last):
File "CvScreensInterface", line 754, in forceScreenRedraw
File "CvMainInterface", line 1347, in redraw
File "CvMainInterface", line 4569, in updateHelpString
RuntimeError: unidentifiable C++ exception
The new way seems to be: pPlot.setTempTerrainTypeFM( i_Terrain, CyGame().getSorenRandNum(10, "timer") + 10, False, False)

Question:
For what are the two boolean values?


edit:
Ok, I guess it's the same like it is with setTerrainType:
VOID setTerrainType(TerrainType eNewValue, BOOL bRecalculate, BOOL bRebuildGraphics)
void (TerrainTypes eNewValue, bool bRecalculate, bool bRebuildGraphics)

Alos I found in the Blizzards.py file that setTempTerrainType is still in use:
( e.g. line 189: targetPlot.setTempTerrainType(iSnow, CyGame().getSorenRandNum(5, "Bob") + 10) )

So:
What's the different between setTempTerrainTypeFM and setTempTerrainType?
Why I get the python exception when I use setTempTerrainType?
Also, everything works when I use setTempTerrainTypeFM (no mouse-over error and terrain changes) but I don't see a timer when I mouse-over the plot - the plot is permanent. Any idea?
 
def onUnitPillage(self, argsList):

aren't modular... :(

onUnitPillage isn't modular? Strange, I could have sworn that I used it in a modular fashion in the Mekara module. ;)
 
onUnitPillage isn't modular? Strange, I could have sworn that I used it in a modular fashion in the Mekara module. ;)

Well, maybe something is wrong with my install.
I made a new install of Rife with:
1.30.exe -> 1.31.176 -> 2011_01_03_RifE_1.31_Religious_Soundtracks.exe -> 1.31.195

I ended up with this files in \Rise from Erebus\Assets\Modules\NormalModules\Mekara\python :

eventInterfaceMekara.py
MekaraSpecialistList.py
spellMekara.py
utilsMekara.py

The content of the eventInterfaceMekara.py file in my install is this:

Spoiler eventInterfaceMekara.py :
Code:
## MODULAR PYTHON FOR THE MEKARA ORDER MODULE
## Eric 'Jheral' Lindroth
## Last Edited: 28-August-2010
## ericl87@hotmail.com

from CvPythonExtensions import *
from BasicFunctions import *
import PyHelpers

# globals
gc = CyGlobalContext()
PyInfo = PyHelpers.PyInfo
getInfoType = gc.getInfoTypeForString

def onUnitPillage(self, argsList):
	pUnit, iImprovement, iRoute, iOwner = argsList
	iPlotX = pUnit.getX()
	iPlotY = pUnit.getY()
	map 	= CyMap()
	pPlot 	= map.plot(iPlotX, iPlotY)
	pPlayer = gc.getPlayer(iOwner)
	eCiv    = pPlayer.getCivilizationType()
	pVictim =gc.getPlayer( pPlot.getOwner())
	eVictimCiv = pVictim.getCivilizationType()
	iRace = (gc.getCivilizationInfo(pVictim.getCivilizationType())).getDefaultRace()
	if pUnit.getUnitType() == getInfoType('UNIT_BOUNTY_HUNTER') or pUnit.getUnitType() == getInfoType('UNIT_SLAVE_HUNTER') or pUnit.getUnitType() == getInfoType('UNIT_RAIDER'):
		sValidImprovements = ['IMPROVEMENT_PASTURE','IMPROVEMENT_FARM','IMPROVEMENT_HOMESTEAD','IMPROVEMENT_COTTAGE','IMPROVEMENT_HAMLET','IMPROVEMENT_VILLAGE','IMPROVEMENT_TOWN','IMPROVEMENT_ENCLAVE','IMPROVEMENT_PLANTATION' ,'IMPROVEMENT_DWARVEN_SETTLEMENT','IMPROVEMENT_DWARVEN_HALL','IMPROVEMENT_DWARVEN_FORTRESS','IMPROVEMENT_DWARVEN_MINE','IMPROVEMENT_BEDOUIN_CAMP','IMPROVEMENT_BEDOUIN_GATHERING','IMPROVEMENT_BEDOUIN_VILLAGE','IMPROVEMENT_BEDOUIN_SIT']
		iRnd = CyGame().getSorenRandNum(100, "Capture Chance")
		if (pUnit.getUnitType() == getInfoType('UNIT_BOUNTY_HUNTER') and iRnd < 30) or (pUnit.getUnitType() == getInfoType('UNIT_SLAVE_HUNTER') and iRnd < 40) or (pUnit.getUnitType() == getInfoType('UNIT_RAIDER') and iRnd < 60):
			for i in xrange (0, len(sValidImprovements)) :
				iImprovement2 =  getInfoType (sValidImprovements[i])
				if iImprovement == iImprovement2 :
					CvUtil.pyPrint("While pillaging, Player %d's %s captured a slave" %(iOwner, PyInfo.UnitInfo(pUnit.getUnitType()).getDescription()))
					iUnit = getInfoType("UNIT_SLAVE")
					if getInfoType('CIVILIZATION_JOTNAR') != -1:
						if gc.getCivilizationInfo(pVictim.getCivilizationType()) == getInfoType('CIVILIZATION_JOTNAR'):
							iUnit = getInfoType("UNIT_JOT_SLAVE")
						newUnit = pPlayer.initUnit(iUnit,iPlotX, iPlotY, UnitAITypes.NO_UNITAI, DirectionTypes.DIRECTION_SOUTH)
					if iRace != -1:
						newUnit.setHasPromotion(iRace, True)

def onCityAcquired(self, argsList):
	'City Acquired'
	iPreviousOwner,iNewOwner,pCity,bConquest,bTrade = argsList
	gc 			= CyGlobalContext()
	cf			= self.cf
	game 		= CyGame()
	iPlotX = pCity.getX()
	iPlotY = pCity.getY()
	getPlayer 	= gc.getPlayer
	pPlayer 	= getPlayer(iNewOwner)
	hasTrait 	= pPlayer.hasTrait
	pPlot 		= pCity.plot()
	setBuilding = pCity.setNumRealBuilding
	changePop	= pCity.changePopulation
	iCiv		= pPlayer.getCivilizationType()
	iCityOwner 	= pCity.getOwner()
	pCityOwner	= getPlayer(iCityOwner)
	Civ	 		= self.Civilizations
	Trait 		= self.Traits
	Leader 		= self.Leaders
	Civic 		= self.Civics
	Rel	 		= self.Religions
	Building 	= self.Buildings
	Unit		= self.Units
	iPop		= pCity.getPopulation()
	pPrevious	= getPlayer(iPreviousOwner)
	iNoAI 		= UnitAITypes.NO_UNITAI
	iSouth		= DirectionTypes.DIRECTION_SOUTH
	iPrevCiv 	= pPrevious.getCivilizationType()
	
	if iPrevCiv == gc.getInfoTypeForString('CIVILIZATION_MEKARA'):
		iCount = pCity.getFreeSpecialistCount(gc.getInfoTypeForString('SPECIALIST_SLAVE'))
		#iUnit = getInfoType("UNIT_SLAVE")
		for i in xrange(iCount):
			#newUnit = pPlayer.initUnit(iUnit,iPlotX, iPlotY, UnitAITypes.NO_UNITAI, DirectionTypes.DIRECTION_SOUTH)
			pCity.changeFreeSpecialistCount(gc.getInfoTypeForString('SPECIALIST_CITIZEN'), 1)
			pCity.changeFreeSpecialistCount(gc.getInfoTypeForString('SPECIALIST_SLAVE'), -1)
			
def onUnitPromoted(self, argsList):
	pUnit = argsList[1]
	pPlayer = gc.getPlayer( pUnit.getOwner())
	if pPlayer.getCivilizationType() == gc.getInfoTypeForString('CIVILIZATION_MEKARA'):
		if pUnit.getUnitType() == getInfoType('UNIT_SLAVE_HUNTER') or pUnit.getUnitType() == getInfoType('UNIT_COMBAT_OVERSEER') or pUnit.getUnitType() == getInfoType('UNIT_ASSASSIN'):
			iRnd = CyGame().getSorenRandNum(100, "Vampirism Results")
			if iRnd < 20:
				pUnit.setHasPromotion( getInfoType('PROMOTION_VAMPIRE') , True )
		if pUnit.getUnitType() == getInfoType('UNIT_SLUGA') or pUnit.getUnitType() == getInfoType('UNIT_BATTLE_SLUGA'):
			newUnit = pPlayer.initUnit(pUnit.getUnitType(), caster.getX(), caster.getY(), UnitAITypes.NO_UNITAI, DirectionTypes.DIRECTION_SOUTH)
			pUnit.kill(True, 0)

def onUnitBuilt(self, argsList):
	pUnit = argsList[1]
	pPlayer = gc.getPlayer( pUnit.getOwner())
	if pPlayer.getCivilizationType() == gc.getInfoTypeForString('CIVILIZATION_MEKARA'):
		if pUnit.getUnitType() == getInfoType('UNIT_SLAVE_HUNTER') or pUnit.getUnitType() == getInfoType('UNIT_COMBAT_OVERSEER') or pUnit.getUnitType() == getInfoType('UNIT_ASSASSIN'):
			iRnd = CyGame().getSorenRandNum(100, "Vampirism Results")
			if iRnd < 20:
				pUnit.setHasPromotion( getInfoType('PROMOTION_VAMPIRE') , True )
		if pUnit.getUnitType() == getInfoType('UNIT_SLUGA') or pUnit.getUnitType() == getInfoType('UNIT_BATTLE_SLUGA'):
			newUnit = pPlayer.initUnit(pUnit.getUnitType(), caster.getX(), caster.getY(), UnitAITypes.NO_UNITAI, DirectionTypes.DIRECTION_SOUTH)
			pUnit.kill(True, 0)

The first thing is that as far as I know this file should be renamed to Mekara.py or something without the event in front of the file name because the event....py refers to the CvRandomEventInterface.py file and not to the CvEventManager.py file (so it will not trigger).

But I tried it the way it was. (I tried onUnitPillage and onUnitBuilt, but didn't worked).
Then I renamed the file from eventInterfaceMekara.py to Mekara.py and I tried it again. (I tried onUnitPillage and onUnitBuilt again, and this time onUnitBuilt worked but I was not able to get onUnitPillage to work).

So plz can someone help me. What made I wrong?

edit:
Also at the end of the onUnitBuilt function in the CvEventManager.py file are these "magic" lines:
Code:
		## *******************
		## Modular Python: ANW 29-may-2010

		for module in command['onUnitBuilt']:
			module.onUnitBuilt(self, argsList)

		## Modular Python End
		## *******************

And no such lines in the onUnitPillage function so i was guessing it's not working anyway...
 
Back
Top Bottom