Mod-Modders Guide to Fall Further

There is a LOT that can be done with the spellinfos to move things from python to XML. And a bit which could be done with Missions to move all of the equipment spells to be pure DLL which is automatically established by the bEquipment tags in Unit/Building/Promotion XML (so no spell at all).


Overall, there is enough to do with magic that I need to outsource it, or just wait till next summer when I (hopefully) have a lot of spare time :)
 
I just had a sudden burst of inspiration as to what would make an excellent addition to the spell system, if it's reasonably codable.

Could you add a "Target" xml field that calls a python function and returns a specific unit, or possibly an array of units, based on that function? Then have the spells effects only apply to units returned by the target field. This could make a good number of spells that would normally have to be entirely python be possible with only partial python.

EDIT: The "Faith" spell I mentioned to you in PM, xienwolf, would be an excellent example of a spell that would benefit greatly from this.
 
Link updated with our 043 sourcecode, first post not quite fully updated with our changes. Will probably take me a while to find enough time to do that since I have to juggle between 2 posts due to character limit being long since reached.
 
Found a use for "iDuration" almost immediately. I didn't expect a displayed turn-timer - great feature!
 
First posts updated with all of the new fields. I hope.

I think you missed these two from CIV4EmphasizeInfos:

<bAvoidAngryCitizens>
<bAvoidUnhealthyCitizens>

Not very likely anyone else will use them, but for the sake of completeness they should be in the list.
 
I've been trying to add a couple modmods to FF that work on Vanilla FFH. I literally just downloaded both FFH and FF, and unless somethings changed in the past couple of hours, they're up to date. FF gets an error loading XML at the start up and CtDs.

The modmod's are:
From Apepis: AltCivics; AltAmurites; Wonderspack
From Tarquelne: Holy Warriors; Calabim A&S; Elohim with Salsa; Salt Golem; Blasted Garden

I know Tarquelne's are a bit old, so I tried only with Apepis's, then one at a time, then with modular loading on, but no mods. Only the last option worked. I'm pretty tech savvy, but no modder, so I might just be doing something stupid. Help!
 
From Tarquelne: Holy Warriors; Calabim A&S; Elohim with Salsa; Salt Golem; Blasted Garden

I'll check mine. I checked HW and Calabim A&S sometime late 033, IIRC, and they worked. Haven't checked any in 034 so far.
 
There is a very good chance that they simply are not compatible with Fall Further. There aren't many things which can break a modular mod, but there are still some. Among them would be that I have removed a few XML fields from the DLL, but in that case it should just ignore them, not give you a failure to load. (Main field I can think of is that now the WeaponTier in UnitInfos is actually WeaponTierMax & WeaponTierMin instead)
 
...I have removed a few XML fields from the DLL, but in that case it should just ignore them, not give you a failure to load. (Main field I can think of is that now the WeaponTier in UnitInfos is actually WeaponTierMax & WeaponTierMin instead)

That's pretty much it. I started with the Salt Golem - one unit, one promotion.

I replaced the module's UnitSchema with FF's Schema. (Adding "SG_" to the file name). That prevented the loading CTD and gave me a "WTF does "WeaponTier" mean?" error. Or something like that. Deleting the WeaponTier line from the unit file allowed the Salt Golem into the game.
 
Once again I forget to update with a lot of things I have worked on. Been busy lately and squeezing in code time where I can (makes bug testing real fun when you designed something over the course of the last 3 days in small starts and stops!)


If I am actually remembering everything I did:

<iAsset> & <iPower> fields added to PromotionInfos - This will allow promotions on your units to affect the Power rating of your civilization and should keep the AI from attacking someone because they have a small VERY promoted army. So far we have not yet sat down to insert these values however, and I have not worked the <iAsset> tag into AI logic for deciding if it is willing to disband a unit (about the only thing I can tell it is used for in UnitInfos). The problem I realized after I added these is that a straight number on a promotion is silly, since it really depends on the unit you added the promotion to, so it should be a modifier, not an additive. But that change will be completley inside the DLL when it happens, so just realize that these numbers will tend to be slightly different than the ones in UnitInfos for terms of scale (should still be fairly small since a unit will wind up needing a lot of them to change his overall Power equivalent)

CityBonuses gains the tag <bFullMap> - This makes the unit affect every city in the world which is appropriate based on the other boolean identifiers for the bonus, and overrides the range (but not decay rate)


Loyalty type promotions will be removed (one of them if multiple exist on the unit) instead of a unit turning Barbarian when it fails a check and tries to defect. And if the Gameoption is set to disable barbarians, then units which fail their check will die unless they have Loyalty (which they'll lose).


<PyOnDeath> added to UnitInfos - This function will be run if the field exists for a unit whenever the unit should die (just after checking for immortality, so will not run on an immortal unit). Return a value of 1 to stop the death function from running any further. You must be VERY careful with what you do in this function, as you can cause it to call itself in quite a few ways, and if you do NOT make it attempt to call itself, then you cause the unit to be impossible to remove from the game EVER (not even worldbuilder will manage it). NOTE: This is only a concern if you return 1. Return anything else and the death function continues just fine (so for instance you could run Treants death causing a New Forest on the tile through this function. It would call your def TreantDeath function, check if the tile is allowed to have a forest, plant one, then return 0 so the treant can continue with the process of being killed)

To accompany this function is a python command CyUnit.setDisablePyDeath(bool). If you flag this on a unit, then it will disable the python call form happening again. In most cases, you will want to flag this at the start of your python function.

The unit which currently uses this function is Alcinus. He was ressurected and sent to a random new owner by death in combat previously, so if killed by a spell, or by the AI deciding they cannot afford all of their units, he was gone forever. Now however, this function is called (and immediately disabled) and a new owner is decided on. Once the new owner is selected, Alcinus is converted to their control -- That means that this copy of Alcinus is killed, and a new copy is created for the other player. And that is why it is vital to disable his python call on the initial unit, otherwise you get stuck in an endless loop handing out Alcinus units to everyone over and over.

I'm actually re-writing the code now that I think about how things work to automatically disable itself when it runs, just to save future mod-modders from making a silly mistake. You can still turn it back on if you want with the same function (just use false instead of true for the bool).


<bRequiresPermission> - Boolean in PromotionInfos which demands that a unit has been granted permission to use a promotion in order to take it. This permission can be granted by other promotions or UnitInfos (think of it as a very complicated prereqOR group in this sense)

<AllowPromotions> & <DenyPromotions> - Tags exist in both UnitInfos and PromotionInfos, but in PromotionInfos they are called <PromotionAllows> and <PromotionExcludes>. The Allow promotion is required if a promotion is flagged bRequiresPermission, but also allows a unit to ignore the UnitCombat, UnitType, Tier, and WeaponTier prereqs of the promotion. (so for instance I could grant permission to an Eater of Dreams to use City Raider 1 and he would be able to take it upon gaining the right Combat prereq (2?), but if I gave him permission to use City Raider 2 instead, he would never be able to take it since it requires CR1 and he has the wrong unitcombat to take that promotion)

bValidate will check these tags along with WeaponTier (which this system effectively replaces) and appropriate UnitCombat (which this system potentially overrides) when a unit converts.

<TechBuildDiscounts> - Field added to BuildInfos which allows an additive discount to the iTime value based on the tile owner having a certain technology (NOT based on the player constructing the improvement having that technology, but since most things must be built inside borders, this distinction won't come up often)




Pretty sure all the other new stuff has been previously mentioned. But not 100% certain.
 
Is it possible to prohibit a feature from being built on a feature? Can't find a tag for it. Or better yet, reduce the yields on an improvement if it's on a certain feature...

Prohibit an improvement on a feature?

Maybe something like this in CvGameUtils "canBuild":

Spoiler :

Code:
		pPlayer = gc.getPlayer(iPlayer)
		iBuildBeduinVillage = gc.getInfoTypeForString("BUILD_BEDUIN_VILLAGE")
		if pPlayer.getCivilizationType() == gc.getInfoTypeForString('CIVILIZATION_MALAKIM'):
			pPlot = CyMap().plot(iX, iY)
			if pPlot.getOwner() == iPlayer:
				if (iBuild == iBuildBeduinVillage):
					if pPlot.getFeatureType(-1) == gc.getInfoTypeForString('FEATURE_FLOOD_PLAINS'):
						return 0
 
That should work, thank you. :D Will most likely have it in an update tonight... Got PT to go to atm sadly. Damn Navy....

Sorry, I had no idea - I tried to show you the right way to do it. And if it's not it'll merely be the wrong way. Next time I'll see about figuring out the Navy way.

Although I suppose PT before updating may be it... :)
 
Prohibit an improvement on a feature?

Maybe something like this in CvGameUtils "canBuild":

Spoiler :

Code:
		pPlayer = gc.getPlayer(iPlayer)
		iBuildBeduinSit = gc.getInfoTypeForString("BUILD_BEDUIN_SIT")
		if pPlayer.getCivilizationType() == gc.getInfoTypeForString('CIVILIZATION_MALAKIM'):
			pPlot = CyMap().plot(iX, iY)
			if pPlot.getOwner() == iPlayer:
				if (iBuild == iBuildBeduinSit):
					if pPlot.getFeatureType(-1) == gc.getInfoTypeForString('FEATURE_FLOOD_PLAINS'):
						return 0

Hmm.. Where exactly do I put this? I have it in the 'canbuild' section, but it's not blocking construction.
 
Hmm.. Where exactly do I put this? I have it in the 'canbuild' section, but it's not blocking construction.

Right place - I think the -1 is wrong.

Try "getFeatureType()" rather than "getFeatureType(-1)."

The following prevented a scion worker from building a Cottage on a Floodplain, though it could still build one on the desert.

Spoiler :

Code:
	def canBuild(self,argsList):
		iX, iY, iBuild, iPlayer = argsList
# scions start
		pPlayer = gc.getPlayer(iPlayer)
		iDesert = gc.getInfoTypeForString('TERRAIN_DESERT')
		iBuildSCFarm = gc.getInfoTypeForString("BUILD_FARM")
		pCity = argsList[0]
	
		
		if pPlayer.getCivilizationType() == gc.getInfoTypeForString('CIVILIZATION_SCIONS'):
			pPlot = CyMap().plot(iX, iY)
			if pPlot.getOwner() == iPlayer:
				if pPlot.isCity() == False:
					if pPlot.getTerrainType() == iDesert:		
						iBuildSCottage = gc.getInfoTypeForString("BUILD_COTTAGE")
						if (iBuild == iBuildSCottage):
							if pPlot.getFeatureType() == gc.getInfoTypeForString('FEATURE_FLOOD_PLAINS'):
								return 0
							else:
								return 1
 
Top Bottom