How to make mods without copying files.

clinton

Warlord
Joined
Apr 24, 2004
Messages
133
I was looking at the python files, and thinking about modifying a few things. However, from what I read the procedure is to copy the python file you want to edit to custom assets or the mod directory, and change it there. However, I just want to change or extend a few methods, and copying the whole file seems to make maintainence difficult in the future. I've noticed the built in mods don't copy the whole file, but instead create a different named file and extend the base classes in the original files, without copying everything. I was wondering what mechanism the built in mods used to do this, because I would of thought that the game wouldn't see these new classes and instead see the old ones. Or is there any other way to mod the game without copying entire files? An example of a simple mod that does this would be great.
 
Or is there a python modding tutorial anywhere. I see a lot of python tutorials, but I can learn python from any tutorial. Anything civ specific so I can learn how to solve the above problem?
 
Its general oop(object-oriented programming), they inherit from the base class and then extend it. let me give an example straight out of the scenerios:

From CvDesertWarGameUtils.py:
import CvUtil
from CvPythonExtensions import *
import CvGameUtils
import CvDesertWar

# globals
gc = CyGlobalContext()
dw = CvDesertWar.CvDesertWar()

class CvDesertWarGameUtils(CvGameUtils.CvGameUtils):
def __init__(self):
self.parent = CvGameUtils.CvGameUtils
self.parent.__init__(self)

That is the first bit of code from that file. Blah blah blah we got our imports and everything, here is the important part:

class CvDesertWarGameUtils(CvGameUtils.CvGameUtils):
Here, the CvDesertWarGameUtils inherits from CvGameUtils.CvGameUtils, thus it literally is a copy of the object, except we can override and modify at our will, without ever touching the base object. Inside the file, you can see certian methods *are* overwritten like you said (cannotTrain, cannotDoCivic, etc), and perform different things. *But* keep in mind, you should be wise to copy the base copy of this method for the override, less it stops working because they must return the same types of values and take the same types of arguements (duh).

The above reference is initialized in EntryPoints\CvGameInterface.py, which loads the CvGameUtils object (which we change to *ours*, CvWhateverICalledIt).

Does that all make sense?

EDIT: Oh, sorry. Heres an example of a 2-file mod that does exactly that:

(NOTE: CvGameInterface.py *has* to have all the methods in there, but you only have to change 1 line)
EntryPoints\CvGameInterface.py:
Code:
####################################
#### Civilizations 4 Realism Mod ###
#### by jaynus                   ###
####################################
#
# Ovewrite of game interfacing routines
#



import CvUtil
import CvRealismGameUtils
import CvGameUtils
import CvEventInterface
from CvPythonExtensions import *

# globals
gc = CyGlobalContext()
normalGameUtils = CvRealismGameUtils.CvRealismGameUtils()

def gameUtils():
	#' replace normalGameUtils with your mod version'
	return normalGameUtils
		
def isVictoryTest():
	#CvUtil.pyPrint( "CvGameInterface.isVictoryTest" )
	return gameUtils().isVictoryTest()

def isPlayerResearch(argsList):
	#CvUtil.pyPrint( "CvGameInterface.isPlayerResearch" )
	return gameUtils().isPlayerResearch(argsList)

def createBarbarianCities():
	#CvUtil.pyPrint( "CvGameInterface.createBarbarianCities" )
	return gameUtils().createBarbarianCities()

def createBarbarianUnits():
	#CvUtil.pyPrint( "CvGameInterface.createBarbarianUnits" )
	return gameUtils().createBarbarianUnits()

def skipResearchPopup(argsList):
	#CvUtil.pyPrint( "CvGameInterface.skipResearchPopup" )
	return gameUtils().skipResearchPopup(argsList)

def showTechChooserButton(argsList):
	#CvUtil.pyPrint( "CvGameInterface.showTechChooserButton" )
	return gameUtils().showTechChooserButton(argsList)

def getFirstRecommendedTech(argsList):
	#CvUtil.pyPrint( "CvGameInterface.getFirstRecommendedTech" )
	return gameUtils().getFirstRecommendedTech(argsList)

def getSecondRecommendedTech(argsList):
	#CvUtil.pyPrint( "CvGameInterface.getSecondRecommendedTech" )
	return gameUtils().getSecondRecommendedTech(argsList)

def skipProductionPopup(argsList):
	#CvUtil.pyPrint( "CvGameInterface.skipProductionPopup" )
	return gameUtils().skipProductionPopup(argsList)

def showExamineCityButton(argsList):
	#CvUtil.pyPrint( "CvGameInterface.showExamineCityButton" )
	return gameUtils().showExamineCityButton(argsList)

def getRecommendedUnit(argsList):
	#CvUtil.pyPrint( "CvGameInterface.getRecommendedUnit" )
	return gameUtils().getRecommendedUnit(argsList)

def getRecommendedBuilding(argsList):
	#CvUtil.pyPrint( "CvGameInterface.getRecommendedBuilding" )
	return gameUtils().getRecommendedBuilding(argsList)

def updateColoredPlots():
	#CvUtil.pyPrint( "CvGameInterface.updateColoredPlots" )
	return gameUtils().updateColoredPlots()

def isActionRecommended(argsList):
	#CvUtil.pyPrint( "CvGameInterface.isActionRecommended" )
	return gameUtils().isActionRecommended(argsList)

def cannotHandleAction(argsList):
	#CvUtil.pyPrint( "CvGameInterface.cannotHandleAction" )
	return gameUtils().cannotHandleAction(argsList)

def cannotSelectionListMove(argsList):
	#CvUtil.pyPrint( "CvGameInterface.cannotSelectionListMove" )
	return gameUtils().cannotSelectionListMove(argsList)

def cannotSelectionListGameNetMessage(argsList):
	#CvUtil.pyPrint( "CvGameInterface.cannotSelectionListGameNetMessage" )
	return gameUtils().cannotSelectionListGameNetMessage(argsList)

def cannotDoControl(argsList):
	#CvUtil.pyPrint( "CvGameInterface.cannotDoControl" )
	return gameUtils().cannotDoControl(argsList)

def canResearch(argsList):
	#CvUtil.pyPrint( "CvGameInterface.canResearch" )
	return gameUtils().canResearch(argsList)

def cannotResearch(argsList):
	#CvUtil.pyPrint( "CvGameInterface.cannotResearch" )
	return gameUtils().cannotResearch(argsList)

def canDoCivic(argsList):
	#CvUtil.pyPrint( "CvGameInterface.canDoCivic" )
	return gameUtils().canDoCivic(argsList)

def cannotDoCivic(argsList):
	#CvUtil.pyPrint( "CvGameInterface.cannotDoCivic" )
	return gameUtils().cannotDoCivic(argsList)

def canTrain(argsList):
	#CvUtil.pyPrint( "CvGameInterface.canTrain" )
	return gameUtils().canTrain(argsList)

def cannotTrain(argsList):
	#CvUtil.pyPrint( "CvGameInterface.cannotTrain" )
	return gameUtils().cannotTrain(argsList)

def canConstruct(argsList):
	#CvUtil.pyPrint( "CvGameInterface.canConstruct" )
	return gameUtils().canConstruct(argsList)

def cannotConstruct(argsList):
	#CvUtil.pyPrint( "CvGameInterface.cannotConstruct" )
	return gameUtils().cannotConstruct(argsList)

def canCreate(argsList):
	#CvUtil.pyPrint( "CvGameInterface.canCreate" )
	return gameUtils().canCreate(argsList)

def cannotCreate(argsList):
	#CvUtil.pyPrint( "CvGameInterface.cannotCreate" )
	return gameUtils().cannotCreate(argsList)

def canMaintain(argsList):
	#CvUtil.pyPrint( "CvGameInterface.canMaintain" )
	return gameUtils().canMaintain(argsList)

def cannotMaintain(argsList):
	#CvUtil.pyPrint( "CvGameInterface.cannotMaintain" )
	return gameUtils().cannotMaintain(argsList)

def AI_chooseTech(argsList):
	'AI chooses what to research'
	#CvUtil.pyPrint( "CvGameInterface.AI_chooseTech" )
	return gameUtils().AI_chooseTech(argsList)

def AI_chooseProduction(argsList):
	'AI chooses city production'
	#CvUtil.pyPrint( "CvGameInterface.AI_chooseProduction" )
	return gameUtils().AI_chooseProduction(argsList)

def AI_unitUpdate(argsList):
	'AI moves units - return 0 to let AI handle it, return 1 to say that the move is handled in python '
	#CvUtil.pyPrint( "CvGameInterface.AI_unitUpdate" )
	return gameUtils().AI_unitUpdate(argsList)

def AI_doWar(argsList):
	'AI decides whether to make war or peace - return 0 to let AI handle it, return 1 to say that the move is handled in python '
	#CvUtil.pyPrint( "CvGameInterface.AI_doWar" )
	return gameUtils().AI_doWar(argsList)

def AI_doDiplo(argsList):
	'AI decides does diplomacy for the turn - return 0 to let AI handle it, return 1 to say that the move is handled in python '
	#CvUtil.pyPrint( "CvGameInterface.AI_doDiplo" )
	return gameUtils().AI_doDiplo(argsList)

def calculateScore(argsList):
	#CvUtil.pyPrint( "CvGameInterface.calculateScore" )
	return gameUtils().calculateScore(argsList)

def doHolyCity():
	#CvUtil.pyPrint( "CvGameInterface.doHolyCity" )
	return gameUtils().doHolyCity()

def doHolyCityTech(argsList):
	#CvUtil.pyPrint( "CvGameInterface.doHolyCityTech" )
	return gameUtils().doHolyCityTech(argsList)

def doGold(argsList):
	#CvUtil.pyPrint( "CvGameInterface.doGold" )
	return gameUtils().doGold(argsList)

def doResearch(argsList):
	#CvUtil.pyPrint( "CvGameInterface.doResearch" )
	return gameUtils().doResearch(argsList)

def doGoody(argsList):
	#CvUtil.pyPrint( "CvGameInterface.doGoody" )
	return gameUtils().doGoody(argsList)

def doGrowth(argsList):
	#CvUtil.pyPrint( "CvGameInterface.doGrowth" )
	return gameUtils().doGrowth(argsList)

def doProduction(argsList):
	#CvUtil.pyPrint( "CvGameInterface.doProduction" )
	return gameUtils().doProduction(argsList)

def doCulture(argsList):
	#CvUtil.pyPrint( "CvGameInterface.doCulture" )
	return gameUtils().doCulture(argsList)

def doPlotCulture(argsList):
	#CvUtil.pyPrint( "CvGameInterface.doPlotCulture" )
	return gameUtils().doPlotCulture(argsList)

def doReligion(argsList):
	#CvUtil.pyPrint( "CvGameInterface.doReligion" )
	return gameUtils().doReligion(argsList)

def doGreatPeople(argsList):
	#CvUtil.pyPrint( "CvGameInterface.doGreatPeople" )
	return gameUtils().doGreatPeople(argsList)

def doMeltdown(argsList):
	#CvUtil.pyPrint( "CvGameInterface.doMeltdown" )
	return gameUtils().doMeltdown(argsList)

Above, notice 2 things:
#1. I import my object, CvRealismGameUtils
#2. I change the normalGameUtils variable to reference an instantiation of my object, CvRealismGameUtils

Next file is CvRealismGameUtils.py:
Code:
####################################
#### Civilizations 4 Realism Mod ###
#### by jaynus                   ###
####################################
#
# GameUtils Overwrite file 
#

import CvUtil
import CvRealism
import CvGameUtils
from CvPythonExtensions import *

# globals
gc = CyGlobalContext()
realismObject = CvRealism.CvRealism()

class CvRealismGameUtils(CvGameUtils.CvGameUtils):
	"Miscellaneous game functions"
	def __init__(self): 
		self.parent = CvGameUtils.CvGameUtils()
		pass

	def canTrain(self,argsList):
		pCity = argsList[0]
		eUnit = argsList[1]
		bContinue = argsList[2]
		bTestVisible = argsList[3]
		
		try:
			requiredBonus =  realismObject.getUnitRequiredBonus(eUnit)
			if requiredBonus < 0:
				return False
        	
			if realismObject.getAvialableBonusCount(requiredBonus) < realismObject.getUnitBonusUsage(eUnit):
				# Give a popup
				popup = PyPopup.PyPopup()
				popup.setBodyString( 'You are out of the resource for this unit.' )
				popup.launch()
				return True
			else:
				return False	
		except EOFError:
			pass	
		return False

	def cannotTrain(self,argsList):
		pCity = argsList[0]
		eUnit = argsList[1]
		bContinue = argsList[2]
		bVisibleTest = argsList[3]

		try:
			requiredBonus =  realismObject.getUnitRequiredBonus(eUnit)
			if requiredBonus < 0:
				return False
        	
			if realismObject.getAvialableBonusCount(requiredBonus) < realismObject.getUnitBonusUsage(eUnit):
				# Give a popup
				popup = PyPopup.PyPopup()
				popup.setBodyString( 'You are out of the resource for this unit.' )
				popup.launch()
				return True
			else:
				return False	
		except EOFError:
			pass	
		return False
 
Back
Top Bottom