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. MagisterCultuum

    MagisterCultuum Great Sage

    Joined:
    Feb 14, 2007
    Messages:
    16,157
    Location:
    Kael's head
    XML changes could certainly have broken the scenarios. The easiest way to break a scenario would be to remove the xml define for something (a unit, promotion, technology, building, improvement, terrain, feature, resource, etc) that is already present at the start of the game.
     
  2. Tasunke

    Tasunke Crazy Horse

    Joined:
    Mar 20, 2009
    Messages:
    2,800
    Location:
    the 1800s
    I think I only modified and added.
     
  3. esvath

    esvath Apprentice of Erebus

    Joined:
    Mar 27, 2008
    Messages:
    1,403
    AFAIK, modifying xml (adding or removing tags) will not cause ctd, but adding or removing entries (adding a new promotion, for example) will cause crash.
     
  4. MagisterCultuum

    MagisterCultuum Great Sage

    Joined:
    Feb 14, 2007
    Messages:
    16,157
    Location:
    Kael's head
    Perhaps it is just a problem with the ModPath? I haven't tried playing a scenario in a long time, but I think that scenarios set to work with a specific mod will not work with another mod even if the two are identical in all but name. Assuming that you are modding a copy of FfH2 in a different folder rather than editing the original, then you should try editing the scenario files in notepad (or your preferred text editor) so that the line "ModPath=Mods\Fall from Heaven 2" uses the proper scenario name.
     
  5. Tasunke

    Tasunke Crazy Horse

    Joined:
    Mar 20, 2009
    Messages:
    2,800
    Location:
    the 1800s
    I was, unfortunately, modding the original >.>

    Hmm, I guess I could try deleting all my new units + new promos to see if that works ;) (even if some XML values will stay different)
     
  6. doktarr

    doktarr Warlord

    Joined:
    Jan 31, 2005
    Messages:
    213
    Quoting myself from another thread, but moving it here since I'm realizing that this is not a bug, just stuff getting done in different places.

    So... I figured out that the "must be alive" requirement for Add to Flesh Golem is in the XML, not the Python. So, a couple general questions based on that:

    1. If I wanted to make it so that angels/demons/undead with Death 3 couldn't become liches, I would just add that same line into the XML block for Lichdom, right?
    2. If I wanted to make it so that flesh golems could merge with other flesh golems (but other non-living figures were still exempt), would I remove that line from the XML, and add code in the reqaddtofleshgolem Python method that checks for the figure to be alive if it's not a Flesh Golem?
     
  7. doktarr

    doktarr Warlord

    Joined:
    Jan 31, 2005
    Messages:
    213
    double post
     
  8. Tholal

    Tholal Emperor

    Joined:
    May 19, 2009
    Messages:
    1,676
    Without looking at the code myself, I would say that the answer to both questions is Yes. It seems like you have a good handle on what to do and how to do it.
     
  9. Samuriman

    Samuriman Chieftain

    Joined:
    May 29, 2012
    Messages:
    32
    Location:
    Toronto
    Bug Fixes are not good. new patches will add content adding bugs.
     
  10. MagisterCultuum

    MagisterCultuum Great Sage

    Joined:
    Feb 14, 2007
    Messages:
    16,157
    Location:
    Kael's head
    I recently decided that I would like to include religion specific art for some more improvements in my modmod.

    How would I go about doing this?

    A while back I successful edited CIV4PlotLSystem.xml to get my new Homestead, Ice Node, Dimensional Node, Creation Node, and Force Node improvements to have religion specific art, but those simply involved copying everything from the normal Farm and Life Node improvements.

    When I just attempted to edit the file to add religion specific art for Citadels (using the Bannor Palace art for ERA_ORDE and the Calabim Palace art for ERA_VEIL and ERA_OCTO), it did not seem to have any effect.
     
  11. Tholal

    Tholal Emperor

    Joined:
    May 19, 2009
    Messages:
    1,676
    How is Blight supposed to work exactly? The code for it is a bit fubared.

    Code:
    if pPlayer.getCivilizationType() != gc.getInfoTypeForString('CIVILIZATION_INFERNAL'):
    	for pyCity in py.getCityList():
    		pCity = pyCity.GetCy()
    		i = CyGame().getSorenRandNum(15, "Blight")
    		i = 10
    		i += pCity.getPopulation()
    		i -= pCity.totalGoodBuildingHealth()
    		if i > 0:
    			pCity.changeEspionageHealthCounter(i)
    
    First it's setting the variable i to a random number, but then it immediately changes i to be 10! Seems like it could work either of two ways.

    1) The random number should be used to set the EspionageHealthCounter. The other calculations are just to determine if a city should be hit with Blight (which would make Blight more random and a lot less crippling to large cities)

    2) The random number should be added to the i value (which would make Blight a bit more nasty than it already is).

    Any ideas or previous posts from Kael that would shed any light on this?
     
  12. kekekeke

    kekekeke Chieftain

    Joined:
    Sep 29, 2010
    Messages:
    70
    I tried to google a bit and all (relevant) I could find was this.
    Spoiler :

    Kael:
    http://forums.civfanatics.com/archive/index.php/t-281972.html

    Balance Changes:
    http://forums.civfanatics.com/archive/index.php/t-285863.html.


    I believe that 10-25 + city pop penalty would be a bit too much :). Imo blight is pretty fine now (balance wise). If you aren't prepared for blight, it can hit you pretty hard. Code is obviously bit broken though.
     
  13. Tholal

    Tholal Emperor

    Joined:
    May 19, 2009
    Messages:
    1,676
    OK. That seems pretty clearcut. Then i=10 line should be removed. That means that instead of a flat 10 base extra unhealth from blight, it will instead be 0-15. Makes it a bit more random with Blight being slightly less painful overall, though potentially more painful if you get some bad rolls. Thanks!
     
  14. MagisterCultuum

    MagisterCultuum Great Sage

    Joined:
    Feb 14, 2007
    Messages:
    16,157
    Location:
    Kael's head
    Spoiler :
    Lately I've been going through the python of my modmod, not only looking for bugs but also trying to rewrite things so that they are more efficient or just better looking and occasionally tweaking the functionality.

    The latest change I made was to the recruit mercenary spell. I decided to base the type of unit on the city's culture rather than its original owner, and to remove the owner's default race rather than just replacing it when the city's owner has a default race. This all seems to be working fine.

    I also switched from using 21 if statements to set the art styles for each civ to using the function getArtStyleType(). This seems to be giving me some problems. Things are fine when the unit being hired is a unique unit or when it has a racial promotion that changes its artstyle, but otherwise units hired from some civs have totally wrong art. The Elohim units always seem to use the default art, the Bannor units keep appearing Dark Elven, and the Amurites are looking like Orcs.


    Spoiler :
    Code:
    def reqRecruitMercenary(pCaster, sUnitClass):
    	pPlot = pCaster.plot()
    	pCity = pPlot.getPlotCity()
    	iTeam = pCaster.getTeam()
    	eTeam = gc.getTeam(iTeam)
    	if eTeam.isAtWar(pCity.getTeam()):
    		return False
    	iPlayer = pCaster.getOwner()
    	pPlayer = gc.getPlayer(iPlayer)
    	iPlayerC = pCity.findHighestCulture()
    	if iPlayerC == -1:
    		iPlayerC = iPlayer
    	iCivC = gc.getPlayer(iPlayerC).getCivilizationType()
    	if iCivC == gc.getInfoTypeForString('CIVILIZATION_INFERNAL'):
    		if pPlayer.getStateReligion() != gc.getInfoTypeForString('RELIGION_THE_ASHEN_VEIL'):
    			return False
    	infoCiv = gc.getCivilizationInfo(iCivC)
    	iUnit = infoCiv.getCivilizationUnits(gc.getInfoTypeForString(sUnitClass))
    	if iUnit == -1:
    		return False
    	if not pPlayer.isHuman():
    		if eTeam.getAtWarCount(True) < 1:
    			return False
    		if pPlayer.getCivilizationType() == gc.getInfoTypeForString('CIVILIZATION_KHAZAD'):
    			if pPlayer.getGold() / pPlayer.getNumCities() < 700:
    				return False
    		iCount = 0
    		for i in range(pPlot.getNumUnits(), 0, -1):
    			pUnit = pPlot.getUnit(i)
    			if iTeam == pUnit.getTeam():
    				iCount += 1
    				if iCount > 7:
    					return False
    	return True
    
    def spellRecruitMercUnit(pCaster, sUnitClass, iCost):
    	iUnitClass = gc.getInfoTypeForString(sUnitClass)
    	iGold = iCost//10
    
    	pPlot = pCaster.plot()
    	pCity = pPlot.getPlotCity()
    
    	iPlayer = pCaster.getOwner()
    	pPlayer = gc.getPlayer(iPlayer)
    	iCiv = pPlayer.getCivilizationType()
    
    	iPlayerC = pCity.findHighestCulture()
    	if iPlayerC == -1:
    		iPlayerC = iPlayer
    	pPlayerC = gc.getPlayer(iPlayerC)
    	iCivC = pPlayerC.getCivilizationType()
    	infoCivC = gc.getCivilizationInfo(iCivC)
    
    	iUnit = infoCivC.getCivilizationUnits(iUnitClass)
    	newUnit = pPlayer.initUnit(iUnit, pCaster.getX(), pCaster.getY(), UnitAITypes.NO_UNITAI, DirectionTypes.DIRECTION_SOUTH)
    	newUnit.finishMoves()
    	newUnit.setHasCasted(True)
    	pCity.applyBuildEffects(newUnit)
    
    
    	if iCivC != iCiv:
    		iArt = infoCivC.getArtStyleType()
    		if iArt != -1:
    			newUnit.setUnitArtStyleType(iArt)
    
    		infoCiv = gc.getCivilizationInfo(iCiv)
    		iRace = infoCiv.getDefaultRace()
    		if iRace != -1:
    			if newUnit.isHasPromotion(iRace):
    				newUnit.setHasPromotion(iRace, False)
    		iRace = infoCivC.getDefaultRace()
    		if iRace != -1:
    			if not newUnit.isHasPromotion(iRace):
    				newUnit.setHasPromotion(iRace, True)
    
    
    		iUnitCombat = newUnit.getUnitCombatType()
    		iTrait = infoCivC.getCivTrait()
    		if iTrait != -1:
    			if iTrait == gc.getInfoTypeForString('TRAIT_ARCANE'):
    				if iUnitCombat == gc.getInfoTypeForString('UNITCOMBAT_ADEPT'):
    					newUnit.setHasPromotion(gc.getInfoTypeForString('PROMOTION_ARCANE'), True)
    			elif iTrait == gc.getInfoTypeForString('TRAIT_GUARDSMAN'):
    				if iUnitCombat == gc.getInfoTypeForString('UNITCOMBAT_ARCHER') or iUnitCombat == gc.getInfoTypeForString('UNITCOMBAT_MELEE'):
    					newUnit.setHasPromotion(gc.getInfoTypeForString('PROMOTION_GUARDSMAN'), True)
    			elif iTrait == gc.getInfoTypeForString('TRAIT_DEXTEROUS'):
    				if iUnitCombat == gc.getInfoTypeForString('UNITCOMBAT_ARCHER'):
    					newUnit.setHasPromotion(gc.getInfoTypeForString('PROMOTION_DEXTEROUS'), True)
    			elif iTrait == gc.getInfoTypeForString('TRAIT_HORSELORD'):
    				if iUnitCombat == gc.getInfoTypeForString('UNITCOMBAT_MOUNTED'):
    					newUnit.setHasPromotion(gc.getInfoTypeForString('PROMOTION_HORSELORD'), True)
    				iGold *= 5
    			elif iTrait == gc.getInfoTypeForString('TRAIT_SEAFARING'):
    				if iUnitCombat == gc.getInfoTypeForString('UNITCOMBAT_NAVAL'):
    					newUnit.setHasPromotion(gc.getInfoTypeForString('PROMOTION_SEAFARING'), True)
    			elif iTrait == gc.getInfoTypeForString('TRAIT_SCAVENGER'):
    				if iUnitCombat == gc.getInfoTypeForString('"UNITCOMBAT_ANIMAL') or iUnitCombat == gc.getInfoTypeForString('UNITCOMBAT_BEAST') or iUnitCombat == gc.getInfoTypeForString('UNITCOMBAT_MELEE') or iUnitCombat == gc.getInfoTypeForString('UNITCOMBAT_RECON'):
    					newUnit.setHasPromotion(gc.getInfoTypeForString('PROMOTION_SCAVENGER'), True)
    			elif iTrait == gc.getInfoTypeForString('TRAIT_SINISTER'):
    				if iUnitCombat == gc.getInfoTypeForString('UNITCOMBAT_RECON'):
    					newUnit.setHasPromotion(gc.getInfoTypeForString('PROMOTION_SINISTER'), True)
    			elif iTrait == gc.getInfoTypeForString('TRAIT_SPIRITUAL'):
    				if iUnitCombat == gc.getInfoTypeForString('UNITCOMBAT_DISCIPLE'):
    					newUnit.setHasPromotion(gc.getInfoTypeForString('PROMOTION_MOBILITY1'), True)
    					newUnit.setHasPromotion(gc.getInfoTypeForString('PROMOTION_ZEAL'), True)
    			elif iTrait == gc.getInfoTypeForString('TRAIT_SUNDERED'):
    				if iUnitCombat == gc.getInfoTypeForString('UNITCOMBAT_ADEPT'):
    					newUnit.setHasPromotion(gc.getInfoTypeForString('PROMOTION_SUNDERED'), True)
    
    
    	if pCaster.getUnitType() == gc.getInfoTypeForString('UNIT_MAGNADINE'):
    		newUnit.setHasPromotion(gc.getInfoTypeForString('PROMOTION_MORALE'), True)
    	elif pPlayer.getCivilizationType() != gc.getInfoTypeForString('CIVILIZATION_HIPPUS'):
    		newUnit.setHasPromotion(gc.getInfoTypeForString('PROMOTION_MERCENARY'), True)
    	pPlayerC.changeGold(iGold)
    
    
    


    I'm pretty sure that that never happened when I assigned the art styles manually though 21 different conditional statements. I guess I could just go back to that if I don't find out what is going wrong.

    edit: ok, going back seems to have fixed the issues with Amurite and Elohim art, but the Bannor art is still dark elven and the Ljosalfar are using default art.

    edit2: I just had to get rid of the if iArt != -1: statement and place the 21 conditionals that check for each civilization type between the code that removes and the code that adds racial promotions in order to make it function properly. I'd rather be able to just use the 1 infoCivC.getArtStyleType() call instead of 21 if statements, but I guess this is fine. I might as well have those same. conditionals handle the promotions from civ traits too.


    Edit: You may ignore this post
     
  15. Tasunke

    Tasunke Crazy Horse

    Joined:
    Mar 20, 2009
    Messages:
    2,800
    Location:
    the 1800s
    Has anyone looked into incorporating the AI modifications in K-mod?

    I know for vanilla BTS these modifications are useful, but as I don't know how they are coded, I do not know if they would be useful for FFH. My gut says yes, but on the other hand we already have Tholal working on FFH-specific AI.

    So my question for Tholal is, have you looked at the AI adjustments in K-mod?
     
  16. Tholal

    Tholal Emperor

    Joined:
    May 19, 2009
    Messages:
    1,676
    Yep, though not recently. And I've pulled and incorporated some code from K-Mod in past releases.
     
  17. Tasunke

    Tasunke Crazy Horse

    Joined:
    Mar 20, 2009
    Messages:
    2,800
    Location:
    the 1800s
    awesome :)
     
  18. MagisterCultuum

    MagisterCultuum Great Sage

    Joined:
    Feb 14, 2007
    Messages:
    16,157
    Location:
    Kael's head
    How do the ImprovementWeightModifiers in CIV4LeadersheadInfos.xml work?


    I assumed that they work much like the religion weight modifiers, and that giving all the Infernal leaders a iWeightModifier of -99 for <ImprovementType>IMPROVEMENT_MANA_LIFE would prevent the AI infernal players from building life nodes.

    Now I'm thinking I may have been wrong about that, however, considering that in my current game Hyborem has built over a dozen life nodes and no mana nodes of any other type. It almost seems as if the negative sign is being ignored.
     
  19. Red Key

    Red Key Modder

    Joined:
    Sep 24, 2011
    Messages:
    408
    Gender:
    Male
    Location:
    USA
    Here is what I found in the SDK (of Tholal's MNAI).
    1st in CvUnitAI::AI_ImproveBonus. In this code the lower iValue is the better.
    Code:
    /*FfH: Added by Chalid AiManaAndBonus 06/10/2006*/
    if (!isHuman())
    {													
    iValue /= 100;
    iValue *= std::max(0, (100-GC.getLeaderHeadInfo(GET_PLAYER(getOwnerINLINE()).getPersonalityType()).getImprovementWeightModifier((ImprovementTypes) GC.getBuildInfo(eBuild).getImprovement())));
    }
    iValue -= GC.getGameINLINE().getSorenRandNum(4000, "AIBonus");
    //FfH: End Add
    
    The other places it shows up are CvCityAI::getImprovementValue, CvCityAI::AI_bestPlotBuild, and CvPlayerAI::AI_techValue. I believe higher values of iValue are better in these functions. In all of them the code goes something like this:

    Code:
    if (!isHuman())
    {
    iValue *= std::max(0, (GC.getLeaderHeadInfo(getPersonalityType()).getImprovementWeightModifier(eFinalImprovement) + 200));
    iValue /= 200;
    }
    
    I don't have time at the moment to interpret the code, but I thought I would throw it up for you to look at.
     
  20. Aurelazza

    Aurelazza Chieftain

    Joined:
    Oct 4, 2012
    Messages:
    58
    As a way to introduce myself to Civ 4 modding, I'm looking to revive / makeover The Frozen. Are they entirely modular? Would I have any forseeable problems importing them into another mod? Where might I find the latest version of them? And who originally designed them, that I might get their OK on using them on anything beyond my personal games?
     

Share This Page