Modders Guide to FfH2

Code:
def spellEnterPortal(caster):
	pPlot = caster.plot()
	iX = pPlot.getPortalExitX()
	iY = pPlot.getPortalExitY()
	pExitPlot = CyMap().plot(iX,iY)
	if not pPlot.isNone():
		caster.setXY(iX, iY, false, true, true)

Why does the enter portal spell bother to find pExitPlot when it never uses it, how would it ever be possible for the tile on which the caster started not to exit, and why should that matter?

I think you meant to use if not pExitPlot.isNone(): instead of if not pPlot.isNone():. I first I thought that wouldn't matter anyway since every tile where you haven't set the portal exit seems to have (0,0) as default, but then I realized that you could make it so that it would send the caster to a plot with an index higher than possible on that map, like if you played a duel size map with the The Cult game option on.




Also, what would you think of making the Portal a unique feature to be generated along with the other upon map creation, and changing the code to something like this:

Code:
def spellEnterPortal(caster):
	pPlotCaster = caster.plot()
	iX = pPlotCaster.getPortalExitX()
	iY = pPlotCaster.getPortalExitY()
	
	if iY < 1 and iX < 1:
		iBestValue = 0
		pBestPlot = -1
		iArea1 = pPlotCaster.area().getNumTiles()
		for i in range (CyMap().numPlots()):
			iValue = 0
			pPlot = CyMap().plotByIndex(i)
			if not pPlot.isWater():
				if not pPlot.isPeak():
					if not pPlot.isCity():
						if pPlot.getImprovementType() == -1:
							if pPlot.getBonusType(-1) == -1:
								iValue = CyGame().getSorenRandNum(1000, "Portal")
								if not pPlot.isOwned():
									iValue += 300
								iArea2 = pPlot.area().getNumTiles()
								if iArea1 != iArea2:
									iValue += 200
									
								if iValue > iBestValue:
									iBestValue = iValue
									pBestPlot = pPlot
		if pBestPlot != -1:
			iX = pBestPlot.getX()
			iY = pBestPlot.getY()
			pPlotCaster.setPortalExitX(iX)
			pPlotCaster.setPortalExitY(iY)
			
			pBestPlot.setImprovementType(gc.getInfoTypeForString('IMPROVEMENT_PORTAL'))
			pBestPlot.setPortalExitX(caster.getX())
			pBestPlot.setPortalExitY(caster.getY())
			
	pExitPlot = CyMap().plot(iX,iY)
	if not pExitPlot.isNone():
		caster.setXY(iX, iY, false, true, true)

That is what I just did in my version. Previously I had a duplicate Portal2 unique feature and hen the map was first created I ran a loop that connected the two portals, but I think this way is a lot better. It saves a little time at the start of the game, it doesn't require a special exception so as not to mess up The Cult, it allows me to place usable portals in the game using worldbuilder, and it makes it unlikely that the portals aren't to close to be useful (comparing pPlot.area().getNumTiles()'s means it will generally lead to a new continent).


I also changed the "portal" outcome of lair exploration to place a portal improvement there and force the unit to cast the spell, rather than triggering an event that just moves the unit to a random tile.




Now if only I could figure out a way to let you target where the portal should go, then maybe I could convince you to reintroduce Dimensional Mana...
 
Some more questions now that the first version of my mod is up and running:

1) Is there a Python check that prevents units from upgrading? I want to prevent the Sheaim AI from upgrading all its warriors on city guard duty to Pyre zombies since that results in lots of military unhappiness.

2) Is there a Python check that prevents rushbuying? As soon as the Khazad get access to rushbuying they waste all their gold.

3) Is there a way in the plot system to check only the fat cross of a city without explicitly mentioning every plot you want to check?
Right now I use the loop that the temple of the hand python effect uses, but that one also checks the plots, which are two diagonal spaces away and not workable by the city.

4) Is there a way in Python to prevent certain units from gaining certain UnitAIs ? I noticed that in FFH the AI will use chariots, berserkers or horse archers as city defenders, which does not make a lot of sense.
 
1) Is there a Python check that prevents units from upgrading? I want to prevent the Sheaim AI from upgrading all its warriors on city guard duty to Pyre zombies since that results in lots of military unhappiness.
Have you already tried adding a NotUnitAI tag for UNITAI_CITY_DEFENSE on Pyre Zombies? I don't know if you're absolutely dead-set on not modding the XML or not. I seem to recall reading in another thread that this didn't solve the problem, though, so... *shrugs*

Only thing that sticks out is the getUpgradePriceOverride method in CvGameUtils. You could try setting it to an impossible-to-afford price, but I think this would just make the Sheaim player try to save up impossible amounts of gold.

2) Is there a Python check that prevents rushbuying? As soon as the Khazad get access to rushbuying they waste all their gold.
I've noticed this, too. AFAIK, this doesn't seem possible to prevent without disabling the Arete civic for them, which you obviously won't want to do as it's pretty much their 'thing' flavour-wise.

3) Is there a way in the plot system to check only the fat cross of a city without explicitly mentioning every plot you want to check?
Right now I use the loop that the temple of the hand python effect uses, but that one also checks the plots, which are two diagonal spaces away and not workable by the city.
You can loop through the number of city squares you're checking (21 for non-sprawling civs and 37 for Kuriotates) and call getCityIndexPlot(iIndex) CyCity object for each one.

4) Is there a way in Python to prevent certain units from gaining certain UnitAIs ? I noticed that in FFH the AI will use chariots, berserkers or horse archers as city defenders, which does not make a lot of sense.
There theoretically shouldn't be any need for this because you can set 'NotUnitAIs' in the XML. Again, if you're dead against modifying the XML, though, it's going to be a little more difficult and you'll probably have to hack your way around it by checking for silly AI choices in the 'onUnitBuilt' event and setting them to something more sensible.
 
I have problems getting the compiler to work. I have tried both with codeblock and makefile from different copies and i get the both errors on same. I have bin sdk-modding in Civ4Col with makefile so i now i have all general step taken care of. I havent done any modding yet, i always start of with a test compile to see if it works unmodded, and it doesn't. The Dllfolder is from the first page. Anyone now what the trouble can be? I usually miss something basic since the onlything i vaguelly understand about c++ is the actual coding.

Spoiler :

1>------ Build started: Project: CvGameCoreDLL, Configuration: Final_Release Win32 ------
1>Performing Makefile project actions
1>Microsoft (R) Program Maintenance Utility Version 9.00.30729.01
1>Copyright (C) Microsoft Corporation. All rights reserved.
1> "C:/Program Files/Microsoft Visual C++ Toolkit 2003/bin/cl.exe" /nologo /MD /Gd /G7 /GR /O2 /W3 /EHsc /DWIN32 /DNDEBUG /D_WINDOWS /D_USRDLL /DCVGAMECOREDLL_EXPORTS /DFINAL_RELEASE /IBoost-1.32.0/include /IPython24/include /I"C:/Program Files/Microsoft Visual C++ Toolkit 2003/include" /I"C:/Program Files/Microsoft Platform SDK/Include" /c CvArea.cpp /FoFinal_Release/CvArea.obj
1>CvArea.cpp
1>c:\MyMods\CvGameCoreDLL\CvString.h(72) : error C2061: syntax error : identifier 'LPCWSTR'
1>c:\MyMods\CvGameCoreDLL\CvString.h(245) : error C2061: syntax error : identifier 'LPCSTR'
1>c:\MyMods\CvGameCoreDLL\CvString.h(426) : error C2065: 'LPCWSTR' : undeclared identifier
1>c:\MyMods\CvGameCoreDLL\CvString.h(426) : error C2146: syntax error : missing ')' before identifier 'lpszFormat'
1>c:\MyMods\CvGameCoreDLL\CvString.h(426) : error C2761: 'void CvWString::Format(void)' : member function redeclaration not allowed
1>c:\MyMods\CvGameCoreDLL\CvString.h(426) : error C2059: syntax error : ')'
1>c:\MyMods\CvGameCoreDLL\CvString.h(427) : error C2143: syntax error : missing ';' before '{'
1>c:\MyMods\CvGameCoreDLL\CvString.h(427) : error C2447: '{' : missing function header (old-style formal list?)
1>c:\MyMods\CvGameCoreDLL\CvString.h(474) : error C2065: 'LPCSTR' : undeclared identifier
1>c:\MyMods\CvGameCoreDLL\CvString.h(474) : error C2146: syntax error : missing ')' before identifier 'lpszFormat'
1>c:\MyMods\CvGameCoreDLL\CvString.h(474) : error C2761: 'void CvString::Format(void)' : member function redeclaration not allowed
1>c:\MyMods\CvGameCoreDLL\CvString.h(474) : error C2059: syntax error : ')'
1>c:\MyMods\CvGameCoreDLL\CvString.h(475) : error C2143: syntax error : missing ';' before '{'
1>c:\MyMods\CvGameCoreDLL\CvString.h(475) : error C2447: '{' : missing function header (old-style formal list?)
1>c:\MyMods\CvGameCoreDLL\CvStructs.h(191) : error C2143: syntax error : missing ';' before '*'
1>c:\MyMods\CvGameCoreDLL\CvStructs.h(191) : error C2501: 'FOWVis::POINT' : missing storage-class or type specifiers
1>c:\MyMods\CvGameCoreDLL\CvStructs.h(191) : error C2501: 'FOWVis::pOffsets' : missing storage-class or type specifiers
1>c:\MyMods\CvGameCoreDLL\CvStructs.h(194) : error C2146: syntax error : missing ';' before identifier 'getOffsets'
1>c:\MyMods\CvGameCoreDLL\CvStructs.h(194) : error C2501: 'FOWVis::POINT' : missing storage-class or type specifiers
1>c:\MyMods\CvGameCoreDLL\CvStructs.h(194) : warning C4183: 'getOffsets': missing return type; assumed to be a member function returning 'int'
1>c:\MyMods\CvGameCoreDLL\CvTalkingHeadMessage.h(9) : error C2062: type 'int' unexpected
1>c:\MyMods\CvGameCoreDLL\CvTalkingHeadMessage.h(9) : error C2238: unexpected token(s) preceding ';'
1>c:\MyMods\CvGameCoreDLL\CvTalkingHeadMessage.h(19) : error C2061: syntax error : identifier 'LPCTSTR'
1>c:\MyMods\CvGameCoreDLL\CvTalkingHeadMessage.h(21) : error C2061: syntax error : identifier 'LPCTSTR'
1>c:\MyMods\CvGameCoreDLL\CvGame.h(451) : error C2146: syntax error : missing ';' before identifier 'getReplayMessageText'
1>c:\MyMods\CvGameCoreDLL\CvGame.h(451) : error C2071: 'CvGame::LPCWSTR' : illegal storage class
1>c:\MyMods\CvGameCoreDLL\CvGame.h(451) : error C2501: 'CvGame::LPCWSTR' : missing storage-class or type specifiers
1>c:\MyMods\CvGameCoreDLL\CvGame.h(451) : warning C4183: 'getReplayMessageText': missing return type; assumed to be a member function returning 'int'
1>c:\MyMods\CvGameCoreDLL\CvDLLInterfaceIFaceBase.h(56) : error C2061: syntax error : identifier 'LPCTSTR'
1>c:\MyMods\CvGameCoreDLL\CvDLLInterfaceIFaceBase.h(56) : error C2059: syntax error : ')'
1>c:\MyMods\CvGameCoreDLL\CvDLLInterfaceIFaceBase.h(56) : fatal error C1903: unable to recover from previous error(s); stopping compilation
1>NMAKE : fatal error U1077: '"C:/Program Files/Microsoft Visual C++ Toolkit 2003/bin/cl.exe"' : return code '0x2'
1>Stop.
1>Project : error PRJ0019: A tool returned an error code from "Performing Makefile project actions"
1>Build log was saved at "file://c:\MyMods\CvGameCoreDLL\Final_Release\BuildLog.htm"
1>CvGameCoreDLL - 31 error(s), 2 warning(s)
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========



When i merge the files with them from FF050 it works again. I don't get it. Still would appritiate some help since i only want to modmod, not modmodmod.
 
You mean capture them in combat? Not without FF's <PythonPostCombatLost> function.

Edit: You can however use the <PythonPostCombatLost> function for individual units in normal FfH. You could give each frostling units this function:
Code:
def postCombatFrostlingLost(pCaster, pOpponent):
	if pOpponent.isHasPromotion(gc.getInfoTypeForString('PROMOTION_WINTERBORN'))
		iPlayer = pOpponent.getOwner()
		pPlayer = gc.getPlayer(iPlayer)
		newUnit = pPlayer.initUnit(pOpponent.getUnitType(), pOpponent.getX(), pOpponent.getY(), UnitAITypes.NO_UNITAI, DirectionTypes.DIRECTION_SOUTH)
		for iCount in range(gc.getNumPromotionInfos()):
			if (unit.isHasPromotion(iCount)):
				if gc.getPromotionInfo(iCount).isEquipment() == False:
					newUnit.setHasPromotion(iCount, true)

You could easily add spells that allow units with winterborn to capture frostlings, a la Domination or Mezmerize Animal.





I believe you could also def onUnitKilled(self, argsList): in CvEventManager.py to make the Illians capture frostlings defeated in battle. You could do the same for the Doviello too if you want, but thematically I see no reason for that. This function cannot give you what unit killed the unit for which it runs, but it does give what player killed it.

I haven't tested it, but this might work:
Code:
		if unit.getRace() == gc.getInfoTypeForString('PROMOTION_FROSTLING')
			if attacker == gc.getInfoTypeForString('CIVILIZATION_ILLIANS'):
				newUnit = attacker.initUnit(unit.getUnitType(), unit.getX(), unit.getY(), UnitAITypes.NO_UNITAI, DirectionTypes.DIRECTION_SOUTH)
				for iCount in range(gc.getNumPromotionInfos()):
					if (unit.isHasPromotion(iCount)):
						if gc.getPromotionInfo(iCount).isEquipment() == False:
							newUnit.setHasPromotion(iCount, true)

(I would just use .convert(), but I hear that can cause big problem when run after the unit is dead. I used it back back in 0.22 or so with no problem.)
 
Python is basicly a raw text document.

Notepad works. Notepad++ (free download) works better, it makes finding errors so much easier and structures the files very nicely.

civdirectory/mods/**modname(fall from heaven 2)/assets/python

I would recommend copying the assets folder to the workboard while modding it.
 
Does anyone know what caused this?

I was editing the DLL to add a leash system and when I started the game some icons and text would look like this:

Civ4ScreenShot0072.jpg

Civ4ScreenShot0073.jpg


EDIT: Bah, it was just a font file, sorrry about that.
 
In one of the first few posts on this thread, there used to be a list of art sites that were used as resources for the mod. What happened to this list, and are any of those sites avaliable anymore?
 
I am having problem with 0.41 source. I can't compile it, as at the linking stage I get :
Spoiler :
CvCity.obj : error LNK2019: unresolved external symbol "public: void __thiscall CvEventReporter::cityHurry(class CvCity *,enum HurryTypes)" (?cityHurry@CvEventReporter@@QAEXPAVCvCity@@W4HurryTypes@@@Z) referenced in function "public: void __thiscall CvCity::hurry(enum HurryTypes)" (?hurry@CvCity@@QAEXW4HurryTypes@@@Z)
CvSelectionGroup.obj : error LNK2001: unresolved external symbol "public: static class CvEventReporter & __cdecl CvEventReporter::getInstance(void)" (?getInstance@CvEventReporter@@SAAAV1@XZ)
CvTeam.obj : error LNK2001: unresolved external symbol "public: static class CvEventReporter & __cdecl CvEventReporter::getInstance(void)" (?getInstance@CvEventReporter@@SAAAV1@XZ)

nad 103 more such errors.

I found it when compiling Orbis updated source, but then checked unchanged FfH files and got the same result (on two different machines, running xp and vista).

I use VS2003. After starting CvGameCoreDLL.vcproj I switch to final release and then start Rebuild CvGameCoreDLL.
It works fine for both previous version of FfH source and 3.19 source that comes with the BtS patch. Only FfH gives me trouble.

Any idea what is wrong and what should I do?
 
I remember having this error when I forgot to add a line in the dll. Maybe you forgot something?
 
I thought that at first, but a search of the forums earlier today revealed that this occurs mostly in groups of one when it gives that error.



Odd, while I was typing this it ran through without any of the hundred errors. I don't have a clue what caused that to happen or fix it.
 
As I mentioned above, I have this problem even if not changing anything in the files, just unpack and try to recompile. Also, checked the refrences and can't find anything wrong.

Tried to compile a couple more times, no luck.
 
I was just trying to add a few minor SDK changes I'd made a couple weeks ago to the 0.41b SDK using WinMerge, and I got to wondering what this new "AI may use Warlords to create super-medic units" stuff I came across was all about. Care to explain?
 
Back
Top Bottom