1. We have added a Gift Upgrades feature that allows you to gift an account upgrade to another member, just in time for the holiday season. You can see the gift option when going to the Account Upgrades screen, or on any user profile screen.
    Dismiss Notice

changing unique power

Discussion in 'Rhye's and Fall Modmods' started by gui13, Jul 17, 2010.

  1. gui13

    gui13 Chieftain

    Joined:
    Jul 17, 2010
    Messages:
    2
    In Rhye´s and fall of civilization, how can i change the unique power of a civilization?
     
  2. The_J

    The_J Say No 2 Net Validations Retired Moderator Supporter

    Joined:
    Oct 22, 2008
    Messages:
    31,149
    Location:
    Germany / Netherlands
    Moderator Action: Thread moved.
    Questions belong either into the main section of the creation forum or into the appropriate subsections of the mods forum ;).
    But in the tutorial section only finished tutorials should go, no questions ;).


    And welcome to CFC :).
     
  3. Baldyr

    Baldyr "Hit It"

    Joined:
    Dec 5, 2009
    Messages:
    5,530
    Location:
    Sweden
    It depends. Most UPs are coded in the \Assets\Python\UniquePowers.py but some others are done in C++ and would have to be coded in the SDK (Software Developer's Kit) and recompiled into a custom DLL file.

    It won't be easy to change UPs if you don't know programming. Turning the Russian UP into a global effect ("Universal Winter") was my first ever programming project, by the way. :D I think I got it right on the fourth try, but I was learning Python by doing it at that point. I will have to do it all over again some day though, as I'm still not entirely satisfied with the results.

    A good start would be to learn Python, then. It can be done in a matter of weeks if you really wanna. You could probably learn the basics in a matter of days.
     
  4. gui13

    gui13 Chieftain

    Joined:
    Jul 17, 2010
    Messages:
    2
    Thanks Baldyr, i appreciate your help.
     
  5. Baldyr

    Baldyr "Hit It"

    Joined:
    Dec 5, 2009
    Messages:
    5,530
    Location:
    Sweden
    Sure, just holler if I can offer any actual help. Like point you to where you can learn this stuff.

    What exactly are you proposing to achieve, by the way? It might be easier to do than you'd imagine...
     
  6. CHEESE!

    CHEESE! On a long nostalgia trip

    Joined:
    Aug 11, 2007
    Messages:
    2,219
    Gender:
    Male
    Hey Baldyr, I just want a quick assessment of my UP idea for my Iroquois (ie how hard it would be).

    Unique Power: The Power of the Warpath
    Improvements can be built in forests, jungles.

    How hard would that be to make? And is it overpowered?
     
  7. Baldyr

    Baldyr "Hit It"

    Joined:
    Dec 5, 2009
    Messages:
    5,530
    Location:
    Sweden
    Actually, I have no idea. Improvements are defined in the XML but how to change them for just one Civ...? You'd have to dig into this and figure it out, I guess...

    By the way, do you mean that the improvements would be the same as if the terrain feature was cleared? Like building a Farm on a Grassland Jungle tile or on a Plains Forest tile? And that would give +1 Food to the forest/jungle?

    I guess its an interesting idea, here is what can be done with map tiles with Python, at least:
    http://civ4bug.sourceforge.net/PythonAPI/Classes/CyPlot.html

    If you can't find what you need there, then it would pretty much be a C++ thing that would have to be done in the SDK. (Well, I don't see anything useful at least. Its the entries that start with "VOID" that can be used to manipulate CyPlot instances. The other ones just lets you get information about them.) But (almost) anything is possible if you know how to achieve it. :king:
     
  8. TC01

    TC01 Deity

    Joined:
    Jun 28, 2009
    Messages:
    2,216
    Location:
    Irregularly Online
    It's possible to do in Python. It would be pretty complex, though... This feature is part of Fall from Heaven 2 and is much cleaner- FFH 2 adds a new array to CIV4CivilizationInfos.xml, and then does it all in the DLL.

    However, to do it in Python, you'd need to in onBeginPlayerTurn, loop through all of a player's units, check the ones that are building something, and if they are, save both the unit's owner and the feature to the plot's script data.

    Then, in onImprovementBuilt, you would need to check the previous feature, and if it's no longer on the plot, and if it's one of the features you want (Forest or Jungle), and if the player who had just built the improvement has unique power, you add back the feature.

    This is not perfect. In addition to other possible issues, if a feature is destroyed between the beginning of a player's turn and the completion of the improvement (depending on what happens between the beginning of a player's turn and checks for build progress in the DLL), it won't register, but it's the best you can do in Python only.

    EDIT: Plenty of things are possible in Python only, but it's often not necessarily a good idea to do it in Python only. Take Final Frontier as an example. That mod has no custom DLL (until FF+, of course), John Shafer did everything using Python. As a result, it's really slow and has some bugs, but is impressive nonetheless.
     
  9. Baldyr

    Baldyr "Hit It"

    Joined:
    Dec 5, 2009
    Messages:
    5,530
    Location:
    Sweden
    Yeah, Python is good for some thing and less so for other things. This is why Rhye did some UP in Python and some in C++.

    Regarding FF - isn't there supposed to be like a Fort replacement (a space station or something) that has its own cultural boundaries independent from any nearby cities/planets/whatever? Because this is something I'd wanna do with Forts myself. And since you say it was all done with Python...
     
  10. TC01

    TC01 Deity

    Joined:
    Jun 28, 2009
    Messages:
    2,216
    Location:
    Irregularly Online
    There is, and yes, it's all done with Python (until Final Frontier Plus anyway).

    The trouble is that the method requires you to either:

    a. Have a Fort unit built when the Fort improvement is, so the updateStarbaseCulture() function knows who owns the Fort. This is how Final Frontier's Starbase works- it's a unit.

    b. Alternatively, have a method of storing the Fort's builder (script data, obviously) and a way of claiming the fort from other players. This might be easier, but you'd have to decide- does an enemy unit moving onto the Fort tile claim it? Do units have a custom Python action button letting them seize a tile? Or do Forts have to be razed and then rebuilt by another player?
     
  11. Baldyr

    Baldyr "Hit It"

    Joined:
    Dec 5, 2009
    Messages:
    5,530
    Location:
    Sweden
    What exactly would be the problem with this setup, then? I would probably prefer it if Forts could be taken, I guess... At least when outside of any city's cultural influence.

    AFAIK the problem is having Fort tiles, or any tiles for that matter, that aren't part of a city's cultural radius register as owned. Period. Can this be achieved with Python? Like a tile containing a Fort being part of a Civ's cultural borders (just that one tile, unconnected to any other owned tiles). And the Fort would still function as a city in regard for using it as a port/channel/airport, to claim resources and so on. Just like any fort inside cultural borders.

    How exactly?
     
  12. TC01

    TC01 Deity

    Joined:
    Jun 28, 2009
    Messages:
    2,216
    Location:
    Irregularly Online
    Yes, it can be done.

    Here is the original Final Frontier starbase code. updateAllStarbases() is called by onBeginEndGameTurn(), and canBuildStarbase() is called by canBuild(). Everything else is either called by one of those or is a callback.

    There is only one change- a bugfix by me that makes it work properly on flat maps when the starbase is at the edge of the map (otherwise, the culture would spill over).

    Spoiler :
    Code:
    #############################################################################################
    #		Starbase Stuff
    #############################################################################################
    	
    	def onUnitBuildImprovement(self, argsList):
    		'Unit begins enacting a Build (building an Improvement or Route)'
    		pUnit, iBuild, bFinished = argsList
    		
    		iBuildStarbaseID = CvUtil.findInfoTypeNum(gc.getBuildInfo,gc.getNumBuildInfos(),'BUILD_STARBASE')
    		
    		# Starbase WAS built
    		if (iBuild == iBuildStarbaseID):
    			pUnit.setScriptData("BuildingStarbase")
    
    	def onImprovementBuilt(self, argsList):
    		'Improvement Built'
    		iImprovement, iX, iY = argsList
    		
    		iImprovementStarbaseID = CvUtil.findInfoTypeNum(gc.getImprovementInfo,gc.getNumImprovementInfos(),'IMPROVEMENT_STARBASE')
    		iUnitConstructShipID = CvUtil.findInfoTypeNum(gc.getUnitInfo,gc.getNumUnitInfos(),'UNIT_CONSTRUCT_SHIP')
    		
    		# Starbase finished
    		if (iImprovement == iImprovementStarbaseID):
    			
    			pPlot = CyMap().plot(iX, iY)
    			pPlot.setImprovementType(-1)
    			
    			# Look for Construction Ship on this plot
    			for iUnitLoop in range(pPlot.getNumUnits()):
    				pUnit = pPlot.getUnit(iUnitLoop)
    				
    				if (pUnit.getScriptData() == "BuildingStarbase"):
    					self.doMakeStarbase(pUnit.getOwner(), iX, iY)
    					self.aiKillTimerData = [3, pUnit.getOwner(), pUnit.getID()]
    #					pUnit.kill(true, -1)
    	
    	def doMakeStarbase(self, iPlayer, iX, iY):
    		
    		pPlayer = gc.getPlayer(iPlayer)
    		pPlot = CyMap().plot(iX, iY)
    		
    		# Create Starbase Unit
    		iUnitStarbaseID = CvUtil.findInfoTypeNum(gc.getUnitInfo,gc.getNumUnitInfos(),'UNIT_STARBASE_I')
    		pPlayer.initUnit(iUnitStarbaseID, iX, iY, UnitAITypes.UNITAI_ATTACK, DirectionTypes.NO_DIRECTION)
    		
    		self.updateStarbaseCulture(iPlayer, iX, iY)
    		
    	def updateStarbaseCulture(self, iPlayer, iX, iY):
    		
    		# Create culture around unit
    		for iXLoop in range(iX-2, iX+3):
    			for iYLoop in range(iY-2, iY+3):
    				iActiveX = iXLoop
    				iActiveY = iYLoop
    				if CyMap().isWrapX():
    					if (iActiveX < 0):
    						iActiveX = CyMap().getGridWidth() + iActiveX
    				if CyMap().isWrapY():
    					if (iActiveY < 0):
    						iActiveY = CyMap().getGridHeight() + iActiveY
    				pLoopPlot = CyMap().plot(iActiveX, iActiveY)
    #				printd("Setting Player %d as the owner of %d, %d" %(iPlayer, iXLoop, iYLoop))
    				# Don't override culture that's already here
    				if not pLoopPlot.isNone():
    					if (pLoopPlot.getOwner() == -1):
    						pLoopPlot.setOwnerNoUnitCheck(iPlayer)
    		
    	def updateAllStarbases(self):
    		
    		# Update Starbase culture
    		iUnitStarbaseID = CvUtil.findInfoTypeNum(gc.getUnitInfo,gc.getNumUnitInfos(),'UNIT_STARBASE_I')
    		iUnitStarbaseIID = CvUtil.findInfoTypeNum(gc.getUnitInfo,gc.getNumUnitInfos(),'UNIT_STARBASE_II')
    		iUnitStarbaseIIID = CvUtil.findInfoTypeNum(gc.getUnitInfo,gc.getNumUnitInfos(),'UNIT_STARBASE_III')
    		iUnitMissileI = CvUtil.findInfoTypeNum(gc.getUnitInfo,gc.getNumUnitInfos(),'UNIT_MISSILE_I')
    		iUnitMissileII = CvUtil.findInfoTypeNum(gc.getUnitInfo,gc.getNumUnitInfos(),'UNIT_MISSILE_II')
    		iUnitMissileIII = CvUtil.findInfoTypeNum(gc.getUnitInfo,gc.getNumUnitInfos(),'UNIT_MISSILE_III')
    		
    		# List made to preserve culture of units built first
    		aaiStarbaseList = []
    		
    		for iPlayerLoop in range(gc.getMAX_CIV_PLAYERS()):
    			pPlayer = gc.getPlayer(iPlayerLoop)
    			pTeam = gc.getTeam(pPlayer.getTeam())
    			pyPlayer = PyPlayer(iPlayerLoop)
    			
    			iUnitToCreate = -1
    			aiPossibleUnitList = [iUnitMissileI, iUnitMissileII, iUnitMissileIII]
    			
    			for iUnitLoop in aiPossibleUnitList:
    				
    				pUnitInfo = gc.getUnitInfo(iUnitLoop)
    				iNeededTech = pUnitInfo.getPrereqAndTech()
    				
    				if (pTeam.isHasTech(iNeededTech)):
    					iUnitToCreate = iUnitLoop
    			
    			apUnitList = pyPlayer.getUnitList()
    			for pUnitLoop in apUnitList:
    				if (pUnitLoop.getUnitType() == iUnitStarbaseID or pUnitLoop.getUnitType() == iUnitStarbaseIID or pUnitLoop.getUnitType() == iUnitStarbaseIIID):
    					aaiStarbaseList.append([pUnitLoop.getGameTurnCreated(), iPlayerLoop, pUnitLoop.getX(), pUnitLoop.getY()])
    					
    					# Need appropriate tech to create Missile
    					if (iUnitToCreate != -1):
    						# Need appropriate turn to create
    						iTurnCreated = pUnitLoop.getGameTurnCreated()
    						iCurrentTurn = CyGame().getGameTurn()
    						
    						if (iTurnCreated != iCurrentTurn):
    							iTurnsSinceCreation = iCurrentTurn - iTurnCreated
    							# Produce Missile every 15 turns
    							if (iTurnsSinceCreation % 15 == 0):
    								print "UnitID: %d, X: %d, Y: %d" %(iUnitToCreate, pUnitLoop.getX(), pUnitLoop.getY())
    								pUnit = pPlayer.initUnit(iUnitToCreate, pUnitLoop.getX(), pUnitLoop.getY(), UnitAITypes.NO_UNITAI, DirectionTypes.NO_DIRECTION)
    								# Load Missile onto Starbase... the C++ doesn't like this but it can deal :)
    								pUnit.setTransportUnit(pUnitLoop)
    		
    #		printd("\n\nXXX: There are %d Starbases on the map" %(len(aaiStarbaseList)))
    #		printd(aaiStarbaseList)
    			
    		if (len(aaiStarbaseList) > 0):
    			
    			# Make order such that units built first get culture preference
    			aaiStarbaseList.sort()
    #			aaiStarbaseList.reverse()
    			
    			for iStarbaseLoop in range(len(aaiStarbaseList)):
    				self.updateStarbaseCulture(aaiStarbaseList[iStarbaseLoop][1], aaiStarbaseList[iStarbaseLoop][2], aaiStarbaseList[iStarbaseLoop][3])
    		
    	def canBuildStarbase(self, pPlot, iOffset=0):
    		
    		# Starbase restriction
    		iBuildStarbase = CvUtil.findInfoTypeNum(gc.getBuildInfo,gc.getNumBuildInfos(),'BUILD_STARBASE')
    		
    		# Can't build on a Solar System
    		iFeatureIDSolarSystem = CvUtil.findInfoTypeNum(gc.getFeatureInfo,gc.getNumFeatureInfos(),'FEATURE_SOLAR_SYSTEM')
    		if (pPlot.getFeatureType() == iFeatureIDSolarSystem):
    			return 0
    		
    		# Can't build on top of another Starbase
    		iUnitStarbaseI = CvUtil.findInfoTypeNum(gc.getUnitInfo,gc.getNumUnitInfos(),'UNIT_STARBASE_I')
    		iUnitStarbaseII = CvUtil.findInfoTypeNum(gc.getUnitInfo,gc.getNumUnitInfos(),'UNIT_STARBASE_II')
    		iUnitStarbaseIII = CvUtil.findInfoTypeNum(gc.getUnitInfo,gc.getNumUnitInfos(),'UNIT_STARBASE_III')
    		
    		iNumUnits = iOffset # Offset so that Interface can disable button
    		
    		# Loop through all units on the plot
    		for iUnitLoop in range(pPlot.getNumUnits()):
    			pUnit = pPlot.getUnit(iUnitLoop)
    			
    			# Can't build on top of another Starbase
    			if (pUnit.getUnitType() == iUnitStarbaseI or pUnit.getUnitType() == iUnitStarbaseII or pUnit.getUnitType() == iUnitStarbaseIII):
    				return 0
    			
    			# if there are any Construction Ships already building a Starbase then disallow more	
    			if (pUnit.getBuildType() == iBuildStarbase):
    				iNumUnits += 1
    				if (iNumUnits > 1):	# Account for the one unit actually performing the mission
    					return 0
    		
    		return 1


    Several things are handled poorly, especially the onUnitBuildImprovement() code. It initializes a timer, and on the end of the timer (after the actual starbase unit is created and its culture is generated) the unit is killed. This probably wouldn't be necessary if you don't use a Fort unit- and in any case, should be done by writing the owner of the build unit to script data each turn, since it makes no allowances

    You also probably won't need the code to create missiles on each starbase.
     
  13. Baldyr

    Baldyr "Hit It"

    Joined:
    Dec 5, 2009
    Messages:
    5,530
    Location:
    Sweden
    What exactly does CyPlot.setOwnerNoUnitCheck() achieve? Is the "unit check" perhaps to see whether or not foreign units are present and need to be relocated?
     
  14. embryodead

    embryodead Caliph

    Joined:
    Jan 1, 2003
    Messages:
    5,179
    Location:
    basement
    For forts, can't you use the jculture? It makes fort improvements spread cultural borders of the owner by 1 tile (with 50% strength iirc), meaning that you can extend the borders with forts, until they are taken or destroyed - I believe it's part SDK, so that the AI also builds forts in contested locations to steal tiles.

    EDIT: this: http://forums.civfanatics.com/showthread.php?t=283686
     
  15. TC01

    TC01 Deity

    Joined:
    Jun 28, 2009
    Messages:
    2,216
    Location:
    Irregularly Online
    It's entirely DLL, and that's the point- Baldyr is looking for a Python-only solution (at least, I think).

    Well, there actually is some Python, but it looks like it's mostly AI Auto Play and various other (unnecessary) stuff. Kailric and I used it for our wild west Colonization mod, Westward Ho, and when he created the Forts modcomp for Colonization there
     
  16. TC01

    TC01 Deity

    Joined:
    Jun 28, 2009
    Messages:
    2,216
    Location:
    Irregularly Online
    I think that's what it does, but I'm not sure.

    The setOwner() function in the DLL has three arguments that aren't available to the Python version, so setOwnerNoUnitCheck() simply sets one of those arguments to true.

    It's entirely DLL, and that's the point- Baldyr is looking for a Python-only solution (at least, I think).

    Well, there actually is some Python, but it looks like it's mostly AI Auto Play and various other (unnecessary) stuff. Kailric and I used it for our wild west Colonization mod, Westward Ho, and when he created the Forts modcomp for Colonization there was no Python involved.
     
  17. usi

    usi Shogun

    Joined:
    Jun 20, 2007
    Messages:
    239
    Location:
    Connecticut, USA
    How about adding a worker UU to Iroquois and edit "Builds" (so, modify CIV4UnitInfos.xml and CIV4BuildInfos.xml)?
    Of course, there might be some RFC specific issues with modding, and I am not sure if that works though.
     
  18. CHEESE!

    CHEESE! On a long nostalgia trip

    Joined:
    Aug 11, 2007
    Messages:
    2,219
    Gender:
    Male
    That's a very interesting idea. Would it say:

    Unique Unit: Mohawk Warrior (current unit)

    or

    Unique Unit: Mohawk Warrior, iWorker?
     

Share This Page