RFC Modding Central

I'd like "def onCombatResult" in CvEventManager, which has two arguements, pWinner and pLoser, to also distinguish attacker and defender. is this possible?

You can extend the event to provide more data, not sure if there won't be any compatibility issues, but there shouldn't be. This may look bad but it's also a set of simple copy & paste one-liners ;)

In CvEventReporter.cpp/.h and CvDllPythonEvents.cpp/.h find combatResult method and add another argument there (int iAttacker). In CvDllPytonEvents.cpp you'll need to add line like this: eventData.add(iAttacker);

Same with CvDLLEventReporterIFaceBase.h (that's where the compat issues may come up).

In CvUnit find all lines with CvEventReporter::getInstance().combatResult ... and add another the attacker's ID ( basically getID() ).

You'll also need to override the onCombatResults of the default CvEventManager.py so that it reads the third argument.

---

Depends on what you are doing, but you may also consider just doing it in C++ instead.
 
I want the chance to enslave a unit to vary depending on whether you are attacking or defending. all the code for enslaving is in python.

would I override the regular CvEventManager by including my own modded version of the file in the mod folder or some other way?
 
would I override the regular CvEventManager by including my own modded version of the file in the mod folder

Yeah.
 
I asked this question in the main modding questions thread, but no one had an answer:

the map doesn't appear in the replay screen in my mod. the rest of the screen is there, the power graph and event log and the play and pause controls and they all work, but no map. I've searched all the python in my mod, BTS and vanilla and all I can find is:

def showReplay(argsList): in CvScreensInterface.py

but it seems to never get called. I searched every file for "showReplay" and got nothing.

can anyone help me?
 
trying to understand stability better.

is it true that the various stability parameters are used only to display information to the player and aren't involved in the calculation of actual stability?
 
Yes, they're only used for the numbers in the Financial Advisor.
 
in your CivilizationIV.ini file set HidePythonExceptions = 0 and LoggingEnabled = 1
 
The link still works for me by the way ...
 
I'm working on making barbarians hireable as mercenaries.

I'm doing this by creating alternative versions of the "getEraAppropriateRandomMercenary" definition and the "hire" definition called "getSpecificMercenary" and "spothire", passing a name and grid coordinates.

everything works for the 1st unit: the unit appears on the map, it also appears as hired in the mercenary screen, the hire cost and the maintenance costs are properly calculated and deducted. for the next and subsequent units the unit appears on the map but the rest doesn't happen.

Spoiler :
Code:
	def getSpecificMercenary(self, iPlayer, iUnitType, strName, iX, iY):
		' Mercenary - the mercenary'
		# returns a specific mercenary with a name but no promotions
		# Setup the mercenary data structure if it hasn't been setup yet.		
		# if(sdEntityExists("Mercenaries Mod","MercenaryData") == False): # edead
			# self.setupMercenaryData() # edead

		# return immediately if the iEra doesn't contain a valid value for an era
		#if(gc.getEraInfo(iEra) == None):
			#return

		# Initialize the prereqTechEra so it doesn't equal the iEra
		#prereqTechEra = iEra * -1

		# If iEra is set to 0 then the game just began and set the prereqTechEra 
		# to -1
		#if(prereqTechEra == iEra):
			#prereqTechEra = -1

		# Get the current active player, this use to get the barbarian player but
		# it had to be changed since barbarians will not always exist in games.
		# Yes, I know I should change the variable name, but alas I am lazy ...
		# well maybe not so lazy since I at least took the time to document this
		# and I could have used the time instead to change the variable name but
		# I did not ... so live with it.
		barbarianPlayer = gc.getPlayer(gc.getGame().getActivePlayer())

		mercenary = None

		promotionList = []
		
		# Loop until we get a unit with at least some promotions
		#while(len(promotionList) < g_iMinimumStartingMercenaryPromotionCount):

			#bLoop = True #Rhye
			#iLoopCounter = 0 #Rhye
			# Loop until we get a unit that matches the required era
			#while(prereqTechEra != iEra): #Rhye
			#while(bLoop): #Rhye
				#promotionList = []

				#Rhye - start loopfix (infinite loop happens if renaissance+ techs that offer no units are enabled by WB while in the ancient age)
				#iLoopCounter += 1
				#if (iLoopCounter > 5000):
					#return None
				#Rhye - end

				# The random type of unit that will be created
				#iUnitType = gc.getGame().getMapRand().get(gc.getNumUnitInfos(), "Random Unit Info")
				#iUnitType = con.lMercenaries[gc.getGame().getSorenRandNum(len(con.lMercenaries), "Random Unit Info")] # edead: merc whitelist
				
				# Get the PyUnitInfo for the iUnitType
		pUnitInfo = PyInfo.UnitInfo(iUnitType)
		

		# Create the mercenary unit if we have a valid iUnitType value
		if(iUnitType != -1):
				
			#Rhye - start bugfix
			# Create the mercenary unit
			#tmpUnit = barbarianPlayer.initUnit(iUnitType, 0, 0, UnitAITypes.NO_UNITAI, DirectionTypes.DIRECTION_SOUTH)
			tmpUnit = barbarianPlayer.initUnit(iUnitType, con.iMercX, con.iMercY, UnitAITypes.NO_UNITAI, DirectionTypes.DIRECTION_SOUTH) # edead
								
			# Create the actual mercenary object, we do not pass in the tmpUnit object itself 
			# because we do not want to accidentally set it as the CyUnit in the Mercenary class
			#Rhye - start
			#mercenary = Mercenary(MercenaryNameUtils.getRandomMercenaryName(), gc.getUnitInfo(iUnitType), promotionList, tmpUnit.getExperience(), tmpUnit.experienceNeeded())
			mercenary = Mercenary(strName, gc.getUnitInfo(iUnitType), promotionList, tmpUnit.getExperience(), tmpUnit.experienceNeeded())
			#Rhye - end

			# Kill off the tmpUnit since it does not need to exist in the game until someone hires the 
			# mercenary
			tmpUnit.kill(false,PlayerTypes.NO_PLAYER)

		#edead - start
		for x in range(con.iMercX-1, con.iMercX+2):
			for y in range(con.iMercY-1, con.iMercY+2):
				gc.getMap().plot(x, y).setRevealed(gc.getGame().getActivePlayer(), False, True, -1);
		#edead - end
				
		# Debug code - start		
		if(g_bDebug):
			self.printMercenaryDataToLog(mercenary)
		# Debug code - end
		
		
		
		# Get the starting location for the mercenary if we are not delaying their
		# placement	
		#city = None
		#if(not g_bDelayMercenaryPlacement):
			# edead: start naval mercenaries
		#if mercenary.getUnitInfo().getDomainType() == gc.getInfoTypeForString("DOMAIN_LAND"):
			#city = self.getMercenaryStartingLocation(iPlayer)
		#else:
			#city = self.getCoastalStartingLocation(iPlayer) 
				
		mercenary.spothire(iPlayer, iX, iY)
		
		# Saves the mercenary in the global mercenary pool
		self.saveMercenary(mercenary)

		# Finally return the mercenary
		#return mercenary


Spoiler :
Code:
	def spothire(self, iPlayer, iX, iY):
		' CyUnit - the instance of the mercenary in the game '

		# get the player instance
		player = gc.getPlayer(iPlayer)
		
		# return nothing if the iPlayer is an invalid value
		if(player == None):
			return
			
		# return nothing if the player is dead
		if(player.isAlive() == false):
			return

		# Set the player as the owner of the mercenary.	
		self.iOwner = iPlayer
		
		# Set the mercenary as hired
		self.bHired = true
		
		unitType = gc.getInfoTypeForString(self.objUnitInfo.getType())

		
		# Create the unit and place it in the game		
		self.objUnit = player.initUnit(unitType, iX, iY, UnitAITypes.NO_UNITAI, DirectionTypes.DIRECTION_SOUTH)

		# If g_bConsumeMercenaryMovesOnHire is set to true then use up all of the 
		# mercenaries moves, otherwise just select the mercenary.
		if(g_bConsumeMercenaryMovesOnHire):
			self.objUnit.finishMoves()
		elif(CyGame().isNetworkMultiPlayer()):
			self.objUnit.finishMoves()
		else:
			CyInterface().selectUnit(self.objUnit, true, false, false)

		if(g_bDisplayMercenaryMessages):
			strMessage = rstrip(self.getName()) + " has been retained as a mercenary"
			# Inform the player that the mercenary has arrived.
			CyInterface().addMessage(self.iOwner, False, 20, strMessage, "", 0, self.objUnitInfo.getButton(), ColorTypes(0), iX, iY, True, True) 
				
		# Apply of the promotions to the mercenary in the game
		self.applyPromotions()

		# Set the mercenaries experience
		self.setExperience()		

		# Set the mercenaries unique name
		self.objUnit.setName(self.strMercenaryName)

		self.iPlacementTurn = -1

		if(g_bDisplayMercenaryMessages and self.iBuilder != -1):
			strMessage = rstrip(self.getName()) + " has been hired by " + gc.getPlayer(self.iOwner).getName()
			# Inform the player that the mercenary has been hired.
			CyInterface().addMessage(self.iBuilder, True, 20, strMessage, "", 0, "", ColorTypes(0), -1, -1, True, True) 
	
		# Subtract cost to hire from player current cash
		#if(self.iOwner != self.iBuilder):
			#Rhye - start Carthaginian UP
			#player.setGold(player.getGold()-self.getHireCost())
		player.setGold(player.getGold()-self.getHireCostXPlayer(iPlayer))
			#Rhye - end Carthaginian UP
		
		# if(self.iBuilder != -1 and self.iOwner != self.iBuilder):
			#Rhye - start Carthaginian UP
			#gc.getPlayer(self.iBuilder).setGold(gc.getPlayer(self.iBuilder).getGold() + self.getHireCost())
			# gc.getPlayer(self.iBuilder).setGold(gc.getPlayer(self.iBuilder).getGold() + self.getHireCostXPlayer(iPlayer))
			#Rhye - end Carthaginian UP
 
I have this completely working now except for the fact that every mercenary must have a unique name to properly become part of the mercenary pool. for now I just have it naming them Seleucid Scythian Horseman 1, Seleucid Scythian Horseman 2 etc and it works but it looks awkward.
 
is it possible to not have the StoredData reset when reloading python modules?
 
is it possible to not have the StoredData reset when reloading python modules?

Yes. This is the line that does it in SoI, in CvRFCEventHandler.py:
Code:
if gc.getMap().getMapScriptName(): # Baldyr: loads stored data on module reload
	sd.load()

But you already have it. Is it not working?
 
how to apply better graphics to RFC :dawn of mankind?
Resently I am playing RFC&#65306;dawn of mankind with Varietas Delectat.
I want to play it with the graphics of Realism Invictus.
I copied the graphics file to the assets of RFC&#65306;dawn of mankind, but it didn't seem compatible. I really don't know how to solve it.
thank you!
 
Could you tell me how to enable more instances of dynamic names for different circumstances? I have just about zero experience in modding, so any help would be appreciated.
 
everything is in DynamicCivs.py. the file basically consists of 2 things: 1.lists of names and the civs and circumstances they apply to and 2. methods to check for a name change under certain circumstances. have a look at it. you should be able to figure out how to make changes. you also need to enable python exceptions (error reporting) in your civ.ini file so you will know if you've made a mistake.
 
I should mention that DynamicCivs.py is only part of Sword of Islam and any RFC mod based on it. You won't find that file in the original RFC, which unfortunately handles dynamic civ names in the DLL, and for that you'd need to set up the SDK and learn the basics of C++ first. Specifically, Rhye put them in CvPlayer:: processCivNames() function, and that's where you'd add anything.
 
Top Bottom