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

Modders Guide to FfH2

Discussion in 'Civ4 - Fall from Heaven' started by Kael, Aug 14, 2007.

  1. Tholal

    Tholal Emperor

    Joined:
    May 19, 2009
    Messages:
    1,676


    Is this typo in your code or just this post? It should be just getHealRateChange(), without the I.
     
  2. stolenrays

    stolenrays Deity

    Joined:
    Aug 2, 2009
    Messages:
    2,061
  3. stolenrays

    stolenrays Deity

    Joined:
    Aug 2, 2009
    Messages:
    2,061
  4. stolenrays

    stolenrays Deity

    Joined:
    Aug 2, 2009
    Messages:
    2,061
    Game loads properly, but I have no idea if it works since they new tag does not show up in the civilopedia screen or when you roll over the plot in game. There is probabaly a way to do that, but I have no idea how.
     
  5. arcticnightwolf

    arcticnightwolf Emperor

    Joined:
    Jun 8, 2008
    Messages:
    1,301
    Location:
    Prague, Czech Republic
    you need to edit CvGameTextMgr.cpp file
     
  6. xienwolf

    xienwolf Deity

    Joined:
    Oct 4, 2007
    Messages:
    10,589
    Location:
    Location! Location!
    If you look through my "An Idiot's Guide to Editing the DLL" tutorial, it walks you through the steps needed to add a tag to the XML. There are quite a few little things you need to do for ANY tag you add. The code listed in here so far was just the details to get the tag to do what you want. Right now, the tag doesn't exist for you yet.

    I only ever got around to writing the boolean tag bits, but you can use that for integer with few modifications.
     
  7. MagisterCultuum

    MagisterCultuum Great Sage

    Joined:
    Feb 14, 2007
    Messages:
    16,157
    Location:
    Kael's head
    I've been trying to play around with reintroducing espionage (and linking it closely with the Council of Esus), but have reached an early impasse; I have been unable to turn off the No Espionage game option. I edited CIV4GameOptionInfos.xml so that GAMEOPTION_NO_ESPIONAGE is visible and should no longer be active by default, but whenever I start a custom game I find that the option is on regardless of whether I selected it or not. Is this hardcoded in the DLL or something? How do I get around this?
     
  8. Valkrionn

    Valkrionn The Hamster King

    Joined:
    May 23, 2008
    Messages:
    14,450
    Location:
    Crestview FL
    I believe Kael hardcoded that option in the DLL, yes.
     
  9. MagisterCultuum

    MagisterCultuum Great Sage

    Joined:
    Feb 14, 2007
    Messages:
    16,157
    Location:
    Kael's head
    Is there a way to use python to determine whether a vote has passed?

    (I currently am using python to make it so that Radiant Guards/Nightwatches require either the Empyrean/Council of Esus religion or Overcouncil/Undercouncil membership. I would much rather make it so that those who are on the proper council but do not have the proper state religion can only train the units after the votes to recruit them have passed. It would also be nice to allow votes that reduce the cost of these and other unique units under various circumstances, like is done with gambling houses but without needing to implement new tags in the sdk.)
     
  10. Azhral

    Azhral Let's get Tactical!

    Joined:
    Jul 9, 2008
    Messages:
    622
    Location:
    Dunedin, New Zealand
    Should be able to MC, just need a bunch of booleans declared someplace.

    Is there any way to weight a spell so much that the AI will cast it immediately if they are able to. Specifically 'Add to City' so the Infenals don't sit around with 50+ manes just sitting in Dis, or 'Promote to City' for the Kuroutaites, as in my current game they have just 3 settlements left after their core was conquered, and have had them for quite a while now.
     
  11. Tholal

    Tholal Emperor

    Joined:
    May 19, 2009
    Messages:
    1,676
    Yep. Just bump the AIweight up to 300 or something along those lines

    For some reason this spell isn't enabled for the AI. You have to add <bAllowAI>1</bAllowAI> to it in spellinfos.xml
     
  12. Tholal

    Tholal Emperor

    Joined:
    May 19, 2009
    Messages:
    1,676
    There's some stuff in CVvictoryscreen.py regarding vote results. You can probably look there for examples as to how to access that info. Might require some DLL changes if you're adding in a new vote.
     
  13. MagisterCultuum

    MagisterCultuum Great Sage

    Joined:
    Feb 14, 2007
    Messages:
    16,157
    Location:
    Kael's head
    You could increase the value of <iAIWeight> (or maybe <iAIWeightCity>, although I'm less sure what that does) dramatically to make the AI casting it more likely. I vaguely recall it not working when I put the value too high, but at 1000 casting it within a turn or two is almost guaranteed.


    I actually figured out my last question within about an hour of posting it. I probably should have edited it so others wouldn't work too hard to give unneeded help.
    Spoiler in CvGameUtils.py :
    Code:
    	def cannotTrain(self,argsList):
    		pCity = argsList[0]
    		eUnit = argsList[1]
    		bContinue = argsList[2]
    		bTestVisible = argsList[3]
    		bIgnoreCost = argsList[4]
    		bIgnoreUpgrades = argsList[5]
    		ePlayer = pCity.getOwner()
    		pPlayer = gc.getPlayer(ePlayer)
    		eUnitClass = gc.getUnitInfo(eUnit).getUnitClassType()
    		eTeam = gc.getTeam(pPlayer.getTeam())
    
    
    
    
    		if eUnitClass == gc.getInfoTypeForString('UNITCLASS_NIGHTWATCH'):
    			if pPlayer.getStateReligion() == gc.getInfoTypeForString('RELIGION_COUNCIL_OF_ESUS'):
    				return False
    			if pPlayer.getCivics(gc.getInfoTypeForString('CIVICOPTION_MEMBERSHIP')) == gc.getInfoTypeForString('CIVIC_UNDERCOUNCIL'):
    				if CyGame().isVotePassed(gc.getInfoTypeForString('VOTE_ENLIST_THE_NIGHTWATCH')):
    					return False
    			return True
    			
    		if eUnitClass == gc.getInfoTypeForString('UNITCLASS_RADIANT_GUARD'):
    			if pPlayer.getStateReligion() == gc.getInfoTypeForString('RELIGION_THE_EMPYREAN'):
    				return False
    			if pPlayer.getCivics(gc.getInfoTypeForString('CIVICOPTION_MEMBERSHIP')) == gc.getInfoTypeForString('CIVIC_OVERCOUNCIL'):
    				if CyGame().isVotePassed(gc.getInfoTypeForString('VOTE_ENLIST_THE_GUARD')):
    					return False
    			return True


    I also edited the file so that AI civs actually uses the Infernal Pact Ritual (in my version the tech is exchanged for a project that can be used 7 times to bring it all 7 demon lords, with a maximum of 3 summoned by the same team), and in the process must have accidentally messed something up to make them spam warriors like crazy.



    Would it be possible to make it so that a Smuggler's Port rendered ships unable to blockade a city? I imagine that blocking the action in the first place or ignoring it would almost certainly require DLL changes, but maybe python could be used to cancel the blockade action?
     
  14. MagisterCultuum

    MagisterCultuum Great Sage

    Joined:
    Feb 14, 2007
    Messages:
    16,157
    Location:
    Kael's head
    Could someone help me figure out what is wrong with this code? It seemed to be working juts fine during two test games this afternoon, but in the past few hours it has caused a CtD every time I complete the ritual even though I'm pretty sure that the code has not changed.

    Code:
    		if iProjectType == gc.getInfoTypeForString('PROJECT_INFERNAL_PACT'):
    			demonList = []
    			if not CyGame().isLeaderEverActive(gc.getInfoTypeForString('LEADER_HYBOREM')):
    				demonList.append(gc.getInfoTypeForString('LEADER_HYBOREM'))
    			if not CyGame().isLeaderEverActive(gc.getInfoTypeForString('LEADER_JUDECCA')):
    				demonList.append(gc.getInfoTypeForString('LEADER_JUDECCA'))
    			if not CyGame().isLeaderEverActive(gc.getInfoTypeForString('LEADER_SALLOS')):
    				demonList.append(gc.getInfoTypeForString('LEADER_SALLOS'))
    			if not CyGame().isLeaderEverActive(gc.getInfoTypeForString('LEADER_OUZZA')):
    				demonList.append(gc.getInfoTypeForString('LEADER_OUZZA'))
    			if not CyGame().isLeaderEverActive(gc.getInfoTypeForString('LEADER_MERESIN')):
    				demonList.append(gc.getInfoTypeForString('LEADER_MERESIN'))
    			if not CyGame().isLeaderEverActive(gc.getInfoTypeForString('LEADER_STATIUS')):
    				demonList.append(gc.getInfoTypeForString('LEADER_STATIUS'))
    			if not CyGame().isLeaderEverActive(gc.getInfoTypeForString('LEADER_LETHE')):
    				demonList.append(gc.getInfoTypeForString('LEADER_LETHE'))
    			if len(demonList)>0:
    				iDemonLord = demonList[CyGame().getSorenRandNum(len(demonList), "Infernal Pact")]
    				
    				
    				iInfernalPlayer = cf.getOpenPlayer()
    				pBestPlot = -1
    				iBestPlot = -1
    				for i in range (CyMap().numPlots()):
    					pPlot = CyMap().plotByIndex(i)
    					iPlot = -1
    					if pPlot.isWater() == False:
    						if pPlot.getNumUnits() == 0:
    							if pPlot.isCity() == False:
    								if pPlot.isImpassable() == False:
    									iPlot = CyGame().getSorenRandNum(500, "Place Hyborem")
    									iPlot = iPlot + (pPlot.area().getNumTiles() * 2)
    									iPlot = iPlot + (pPlot.area().getNumUnownedTiles() * 10)
    									if pPlot.isOwned() == False:
    										iPlot = iPlot + 500
    									if pPlot.getOwner() == iPlayer:
    										iPlot = iPlot + 200
    					if iPlot > iBestPlot:
    						iBestPlot = iPlot
    						pBestPlot = pPlot
    				if (iInfernalPlayer != -1 and pBestPlot != -1):
    					CyGame().addPlayerAdvanced(iInfernalPlayer, -1, iDemonLord, gc.getInfoTypeForString('CIVILIZATION_INFERNAL'))
    					iFounderTeam = gc.getPlayer(iPlayer).getTeam()
    					eFounderTeam = gc.getTeam(gc.getPlayer(iPlayer).getTeam())
    					iInfernalTeam = gc.getPlayer(iInfernalPlayer).getTeam()
    					eInfernalTeam = gc.getTeam(iInfernalTeam)
    					for iTech in range(gc.getNumTechInfos()):
    						if eFounderTeam.isHasTech(iTech):
    							eInfernalTeam.setHasTech(iTech, true, iInfernalPlayer, true, false)
    
    					
    					iBarbTeam = gc.getPlayer(gc.getBARBARIAN_PLAYER()).getTeam()
    					eFounderTeam.makePeace(iBarbTeam)
    					eInfernalTeam.makePeace(iBarbTeam)
    					for iTeam in range(gc.getMAX_TEAMS()):
    						if iTeam != iBarbTeam:
    							eTeam = gc.getTeam(iTeam)
    							if eTeam.isAlive():
    								if eFounderTeam.isAtWar(iTeam):
    									eInfernalTeam.declareWar(iTeam, false, WarPlanTypes.WARPLAN_LIMITED)
    					pInfernalPlayer = gc.getPlayer(iInfernalPlayer)
    					pInfernalPlayer.AI_changeAttitudeExtra(iPlayer,4)
    					eFounderTeam.signOpenBorders(iInfernalTeam)
    					eInfernalTeam.signOpenBorders(iFounderTeam)
    
    					eFounderTeam.signDefensivePact(iInfernalTeam)
    					eInfernalTeam.signDefensivePact(iFounderTeam)
    
    					pAshCity = cf.getAshenVeilCity(1)
    					if pAshCity != -1 and not gc.getGame().isNetworkMultiPlayer():
    						pInfernalPlayer.acquireCity(pAshCity,false,false)
    						pBestPlot = pAshCity.plot()
    					else:
    						newUnit0 = pInfernalPlayer.initUnit(gc.getInfoTypeForString('UNIT_SETTLER'), pBestPlot.getX(), pBestPlot.getY(), UnitAITypes.NO_UNITAI, DirectionTypes.DIRECTION_NORTH)
    						newUnit0.setHasPromotion(gc.getInfoTypeForString('PROMOTION_STARTING_SETTLER'), true)
    						pBestPlot.setImprovementType(gc.getInfoTypeForString('IMPROVEMENT_HELLFIRE'))
    
    					if iDemonLord ==gc.getInfoTypeForString('LEADER_HYBOREM'):
    						newUnit1 = pInfernalPlayer.initUnit(gc.getInfoTypeForString('UNIT_HYBOREM'), pBestPlot.getX(), pBestPlot.getY(), UnitAITypes.NO_UNITAI, DirectionTypes.DIRECTION_NORTH)
    						newUnit1.setHasPromotion(gc.getInfoTypeForString('PROMOTION_IMMORTAL'), true)
    						sInfernal = "TXT_KEY_POPUP_CONTROL_INFERNAL"
    						
    					if iDemonLord ==gc.getInfoTypeForString('LEADER_JUDECCA'):
    						newUnit1 = pInfernalPlayer.initUnit(gc.getInfoTypeForString('UNIT_JUDECCA'), pBestPlot.getX(), pBestPlot.getY(), UnitAITypes.NO_UNITAI, DirectionTypes.DIRECTION_NORTH)
    
    						
    						sInfernal = "TXT_KEY_POPUP_CONTROL_INFERNAL_JUDECCA"
    					if iDemonLord ==gc.getInfoTypeForString('LEADER_SALLOS'):
    						newUnit1 = pInfernalPlayer.initUnit(gc.getInfoTypeForString('UNIT_SALLOS'), pBestPlot.getX(), pBestPlot.getY(), UnitAITypes.NO_UNITAI, DirectionTypes.DIRECTION_NORTH)
    						sInfernal = "TXT_KEY_POPUP_CONTROL_INFERNAL_SALLOS"
    					if iDemonLord ==gc.getInfoTypeForString('LEADER_OUZZA'):
    						newUnit1 = pInfernalPlayer.initUnit(gc.getInfoTypeForString('UNIT_OUZZA'), pBestPlot.getX(), pBestPlot.getY(), UnitAITypes.NO_UNITAI, DirectionTypes.DIRECTION_NORTH)
    						sInfernal = "TXT_KEY_POPUP_CONTROL_INFERNAL_OUZZA"
    					if iDemonLord ==gc.getInfoTypeForString('LEADER_MERESIN'):
    						newUnit1 = pInfernalPlayer.initUnit(gc.getInfoTypeForString('UNIT_MERESIN'), pBestPlot.getX(), pBestPlot.getY(), UnitAITypes.NO_UNITAI, DirectionTypes.DIRECTION_NORTH)
    						sInfernal = "TXT_KEY_POPUP_CONTROL_INFERNAL_MERESIN"
    					if iDemonLord ==gc.getInfoTypeForString('LEADER_STATIUS'):
    						newUnit1 = pInfernalPlayer.initUnit(gc.getInfoTypeForString('UNIT_STATIUS'), pBestPlot.getX(), pBestPlot.getY(), UnitAITypes.NO_UNITAI, DirectionTypes.DIRECTION_NORTH)
    						sInfernal = "TXT_KEY_POPUP_CONTROL_INFERNAL_STATIUS"
    					if iDemonLord ==gc.getInfoTypeForString('LEADER_LETHE'):
    						newUnit1 = pInfernalPlayer.initUnit(gc.getInfoTypeForString('UNIT_LETHE'), pBestPlot.getX(), pBestPlot.getY(), UnitAITypes.NO_UNITAI, DirectionTypes.DIRECTION_NORTH)
    						sInfernal = "TXT_KEY_POPUP_CONTROL_INFERNAL_LETHE"
    					
    					newUnit2 = pInfernalPlayer.initUnit(gc.getInfoTypeForString('UNIT_LONGBOWMAN'), pBestPlot.getX(), pBestPlot.getY(), UnitAITypes.NO_UNITAI, DirectionTypes.DIRECTION_NORTH)
    					newUnit2.setHasPromotion(gc.getInfoTypeForString('PROMOTION_MOBILITY1'), true)
    					newUnit3 = pInfernalPlayer.initUnit(gc.getInfoTypeForString('UNIT_LONGBOWMAN'), pBestPlot.getX(), pBestPlot.getY(), UnitAITypes.NO_UNITAI, DirectionTypes.DIRECTION_NORTH)
    					newUnit3.setHasPromotion(gc.getInfoTypeForString('PROMOTION_MOBILITY1'), true)
    					newUnit4 = pInfernalPlayer.initUnit(gc.getInfoTypeForString('UNIT_CHAMPION'), pBestPlot.getX(), pBestPlot.getY(), UnitAITypes.NO_UNITAI, DirectionTypes.DIRECTION_NORTH)
    					newUnit4.setHasPromotion(gc.getInfoTypeForString('PROMOTION_IRON_WEAPONS'), true)
    					newUnit4.setHasPromotion(gc.getInfoTypeForString('PROMOTION_MOBILITY1'), true)
    					newUnit5 = pInfernalPlayer.initUnit(gc.getInfoTypeForString('UNIT_CHAMPION'), pBestPlot.getX(), pBestPlot.getY(), UnitAITypes.NO_UNITAI, DirectionTypes.DIRECTION_NORTH)
    					newUnit5.setHasPromotion(gc.getInfoTypeForString('PROMOTION_IRON_WEAPONS'), true)
    					newUnit5.setHasPromotion(gc.getInfoTypeForString('PROMOTION_MOBILITY1'), true)
    					newUnit6 = pInfernalPlayer.initUnit(gc.getInfoTypeForString('UNIT_WORKER'), pBestPlot.getX(), pBestPlot.getY(), UnitAITypes.NO_UNITAI, DirectionTypes.DIRECTION_NORTH)
    					newUnit6.setHasPromotion(gc.getInfoTypeForString('PROMOTION_DEMON'), true)
    					newUnit7 = pInfernalPlayer.initUnit(gc.getInfoTypeForString('UNIT_IMP'), pBestPlot.getX(), pBestPlot.getY(), UnitAITypes.NO_UNITAI, DirectionTypes.DIRECTION_NORTH)
    					newUnit7.setHasPromotion(gc.getInfoTypeForString('PROMOTION_MOBILITY1'), true)
    					newUnit8 = pInfernalPlayer.initUnit(gc.getInfoTypeForString('UNIT_MANES'), pBestPlot.getX(), pBestPlot.getY(), UnitAITypes.NO_UNITAI, DirectionTypes.DIRECTION_NORTH)
    					newUnit9 = pInfernalPlayer.initUnit(gc.getInfoTypeForString('UNIT_MANES'), pBestPlot.getX(), pBestPlot.getY(), UnitAITypes.NO_UNITAI, DirectionTypes.DIRECTION_NORTH)
    					newUnit10 = pInfernalPlayer.initUnit(gc.getInfoTypeForString('UNIT_MANES'), pBestPlot.getX(), pBestPlot.getY(), UnitAITypes.NO_UNITAI, DirectionTypes.DIRECTION_NORTH)
    
    					
    					if gc.getPlayer(iPlayer).isHuman():
    						popupInfo = CyPopupInfo()
    						popupInfo.setButtonPopupType(ButtonPopupTypes.BUTTONPOPUP_PYTHON)
    						popupInfo.setText(CyTranslator().getText(sInfernal,()))
    						popupInfo.setData1(iPlayer)
    						popupInfo.setData2(iInfernalPlayer)
    						popupInfo.addPythonButton(CyTranslator().getText("TXT_KEY_POPUP_YES", ()), "")
    						popupInfo.addPythonButton(CyTranslator().getText("TXT_KEY_POPUP_NO", ()), "")
    						popupInfo.setOnClickedPythonCallback("reassignPlayer")
    						popupInfo.addPopup(iPlayer)
    
    
    							
    					if pPlayer.getStateReligion() != gc.getInfoTypeForString('RELIGION_THE_ASHEN_VEIL'):
    						pPlayer.setAlignment(gc.getInfoTypeForString('ALIGNMENT_EVIL'))
    
    						for pUnit in (iPlayer).getUnitList():
    							if pUnit.getReligion() ==-1:
    								pUnit.setReligion(gc.getInfoTypeForString('RELIGION_THE_ASHEN_VEIL'))
    
    
    
    
     
  15. Tholal

    Tholal Emperor

    Joined:
    May 19, 2009
    Messages:
    1,676
    You probably need to make sure that pPlot doesn't equal NULL before doing the isWater() check.
     
  16. MagisterCultuum

    MagisterCultuum Great Sage

    Joined:
    Feb 14, 2007
    Messages:
    16,157
    Location:
    Kael's head
    I doubt that's the issue, as that portion of code is unaltered from vanilla FfH.


    Edit: I just realized the difference between the games where it worked fine and those where it caused a crashed. The crash seems to occur only when the city that completes the ritual is the same as the city returned by getAshenVeilCity(1) and given to the Infernals. When I complete the ritual in my capital city, which getAshenVeilCity() can never return, then it works perfectly fine. I think I need to make it so that it moves on to the second best ashen veil city if the ritual is completed in the best one.

    It seems I can't just check to see if one city equals another. I decided it was best to make it so that the ritual will never steal a city belonging to the player that performs it, and to add an extra parameter to getAshenVeilCity() indicating this player so that the function will never return such a city.
     
  17. Azhral

    Azhral Let's get Tactical!

    Joined:
    Jul 9, 2008
    Messages:
    622
    Location:
    Dunedin, New Zealand
    Quick Question: Where is the code that governs map creation?

    More specifically: Where is the bit of code that handles the adding of unique features (at least with the 'All Unique Features' option tagged)?

    Even more specifically: Am running a slightly modified vanilla version of Jean Elcards FlavourMod for patch M (or whatever we are up to). On map creation Yggdrasil isn't created properly, it instead just adds a single copy of the Fruit on the map (which I'm not sure you can access without the improvement.)
     
  18. MagisterCultuum

    MagisterCultuum Great Sage

    Joined:
    Feb 14, 2007
    Messages:
    16,157
    Location:
    Kael's head
    It is handled in the dll. The relevant code is at the end of CvMapGenerator.cpp in the SDK.

    The Yggdrasil is the only improvement that gives access to the Fruit of the Yggdrasil, but building a city on top of it would give you access too.
    --------

    How would I go about forcing two players to trade maps?
     
  19. PsiCorps

    PsiCorps FF: Babylon 5 mod team

    Joined:
    Dec 30, 2007
    Messages:
    1,425
    Location:
    Britain
    Hi all, been a while since I played FfH2 as I've been very busy with the Babylon 5 mod I'm working on. But, there was one thing I distinctly remember about the mod which was to do with Promotions. IIRC there are two types of promotions, one for equipment if you have access to certain resources, Bronze weapons if you have access to bronze, iron weapons if you have iron etc etc. Then you have all of the normal promotions available to the units ala standard Civ IV.
    I would love to see this change to the promotions as a separate Modcomp it would be perfect for the B5 mod as I would be able to have Promotions for Ships that needed to be paid for (Equipment promotions) and Crew Promotions that reflect the experience earned by the units in combat. Would it be possible for someone to extract the code (C++, Python &/or XML) and post this as a standalone ModComp, if it hasn't already been done?
     
  20. Tasunke

    Tasunke Crazy Horse

    Joined:
    Mar 20, 2009
    Messages:
    2,800
    Location:
    the 1800s
    I've only modded XML files ... and yet several of the Scenarios are giving me CTDs :(

    to name a few -> The Wall and Splintered Court.

    Is this possible? or is the only way if I had accidentally modified some of the Python code I was looking at? I modified quite a lot of XML, so if its possible with pure XML change I think I achieved it >.>
     

Share This Page