Portable Resources from Dungeon Adventure

Lutefisk Mafia

Inscrutable Enforcer
Joined
Jun 15, 2007
Messages
544
Location
Minnesota
Wish you could move resources around on the map? Now you can!

I created the following mechanism for my Dungeon Adventure modmod, but it should work for any FfH2 game or other modmod, too.

The link to the original discussion in the Dungeon Adventure thread is here:

http://forums.civfanatics.com/showpost.php?p=6977766&postcount=521

And is also reproduced in full below:

**************************

It always annoyed me when a resource appeared on the map exactly where I wanted to build a future city. I also wondered why you can't move animal resouces like horses and cows.

Well, now you can! I worked up this code to add value to my Dungeon Adventure modmod, but it is useable for any ffH2 offshoot.

In the examples below, I have posted the coding for moveable horses. This code can be modified to work with any other resource, too.

Okay, first things first.

Below is the code for new spell called "Grab Horses." It lets a unit "pick up" a horse resource if the unit is in the same plot as a horse resource. From CIV4SpellInfos.xml:

Spoiler :
Code:
        <SpellInfo>
            <Type>SPELL_GRAB_HORSES</Type>
            <Description>TXT_KEY_SPELL_GRAB_HORSES</Description>
            <Civilopedia>TXT_KEY_SPELL_PLACEHOLDER_PEDIA</Civilopedia>
            <Strategy>NONE</Strategy>
            <Help>TXT_KEY_SPELL_GRAB_HORSES_HELP</Help>
            <PromotionPrereq1>NONE</PromotionPrereq1>
            <PromotionPrereq2>NONE</PromotionPrereq2>
            <UnitPrereq>NONE</UnitPrereq>
            <UnitClassPrereq>NONE</UnitClassPrereq>
            <UnitCombatPrereq>NONE</UnitCombatPrereq>
            <UnitInStackPrereq>NONE</UnitInStackPrereq>
            <CivilizationPrereq>NONE</CivilizationPrereq>
            <ReligionPrereq>NONE</ReligionPrereq>
            <StateReligionPrereq>NONE</StateReligionPrereq>
            <TechPrereq>NONE</TechPrereq>
            <bAllowAI>1</bAllowAI>
            <bAdjacentToWaterOnly>0</bAdjacentToWaterOnly>
            <bCausesWar>1</bCausesWar>
            <bGlobal>0</bGlobal>
            <bInBordersOnly>0</bInBordersOnly>
            <bInCityOnly>0</bInCityOnly>
            <iAIWeight>50</iAIWeight>
            <bDisplayWhenDisabled>0</bDisplayWhenDisabled>
            <bHasCasted>1</bHasCasted>
            <bIgnoreHasCasted>0</bIgnoreHasCasted>
            <bResistable>0</bResistable>
            <iRange>0</iRange>
            <iResistModify>0</iResistModify>
            <iDamage>0</iDamage>
            <iDamageLimit>0</iDamageLimit>
            <DamageType>NONE</DamageType>
            <AddPromotionType1>PROMOTION_HORSE_THIEF</AddPromotionType1>
            <AddPromotionType2>NONE</AddPromotionType2>
            <AddPromotionType3>NONE</AddPromotionType3>
            <RemovePromotionType1>NONE</RemovePromotionType1>
            <RemovePromotionType2>NONE</RemovePromotionType2>
            <RemovePromotionType3>NONE</RemovePromotionType3>
            <bBuffCasterOnly>1</bBuffCasterOnly>
            <ConvertUnitType>NONE</ConvertUnitType>
            <CreateBuildingType>NONE</CreateBuildingType>
            <CreateFeatureType>NONE</CreateFeatureType>
            <CreateImprovementType>NONE</CreateImprovementType>
            <SpreadReligion>NONE</SpreadReligion>
            <CreateUnitType>NONE</CreateUnitType>
            <iCreateUnitNum>0</iCreateUnitNum>
            <bPermanentUnitCreate>0</bPermanentUnitCreate>
            <CreateUnitPromotion>NONE</CreateUnitPromotion>
            <bImmuneTeam>0</bImmuneTeam>
            <bImmuneNeutral>0</bImmuneNeutral>
            <bImmuneEnemy>0</bImmuneEnemy>
            <bImmuneFlying>0</bImmuneFlying>
            <bImmuneNotAlive>0</bImmuneNotAlive>
            <bDispel>0</bDispel>
            <bPush>0</bPush>
            <bRemoveHasCasted>0</bRemoveHasCasted>
            <bSacrificeCaster>0</bSacrificeCaster>
            <iChangePopulation>0</iChangePopulation>
            <iCost>0</iCost>
            <iImmobileTurns>0</iImmobileTurns>
            <iMiscastChance>0</iMiscastChance>
            <PyMiscast></PyMiscast>
            <PyResult>spellGrabHorses(pCaster)</PyResult>
            <PyRequirement>reqGrabHorses(pCaster)</PyRequirement>
            <Effect>EFFECT_SPELL1</Effect>
            <Sound>AS3D_SPELL_TRAIN</Sound>
            <HotKey></HotKey>
            <bAltDown>0</bAltDown>
            <bShiftDown>0</bShiftDown>
            <bCtrlDown>0</bCtrlDown>
            <bGraphicalOnly>1</bGraphicalOnly>
            <iHotKeyPriority>0</iHotKeyPriority>
            <Button>Art/Interface/Buttons/actions/grabhorse.dds</Button>
        </SpellInfo>

Note that there are custom requirement and spell python entries for this spell. Also, the button art for the action interface is one I made up. It is just the horse resource button with a green "+" superimposed.

Here is the "drop horses" spell:

Spoiler :
Code:
        <SpellInfo>
            <Type>SPELL_DROP_HORSES</Type>
            <Description>TXT_KEY_SPELL_DROP_HORSES</Description>
            <Civilopedia>TXT_KEY_SPELL_PLACEHOLDER_PEDIA</Civilopedia>
            <Strategy>NONE</Strategy>
            <Help>TXT_KEY_SPELL_DROP_HORSES_HELP</Help>
            <PromotionPrereq1>PROMOTION_HORSE_THIEF</PromotionPrereq1>
            <PromotionPrereq2>NONE</PromotionPrereq2>
            <UnitPrereq>NONE</UnitPrereq>
            <UnitClassPrereq>NONE</UnitClassPrereq>
            <UnitCombatPrereq>NONE</UnitCombatPrereq>
            <UnitInStackPrereq>NONE</UnitInStackPrereq>
            <CivilizationPrereq>NONE</CivilizationPrereq>
            <ReligionPrereq>NONE</ReligionPrereq>
            <StateReligionPrereq>NONE</StateReligionPrereq>
            <TechPrereq>NONE</TechPrereq>
            <bAllowAI>1</bAllowAI>
            <bAdjacentToWaterOnly>0</bAdjacentToWaterOnly>
            <bCausesWar>0</bCausesWar>
            <bGlobal>0</bGlobal>
            <bInBordersOnly>0</bInBordersOnly>
            <bInCityOnly>0</bInCityOnly>
            <iAIWeight>50</iAIWeight>
            <bDisplayWhenDisabled>1</bDisplayWhenDisabled>
            <bHasCasted>1</bHasCasted>
            <bIgnoreHasCasted>0</bIgnoreHasCasted>
            <bResistable>0</bResistable>
            <iRange>0</iRange>
            <iResistModify>0</iResistModify>
            <iDamage>0</iDamage>
            <iDamageLimit>0</iDamageLimit>
            <DamageType>NONE</DamageType>
            <AddPromotionType1>NONE</AddPromotionType1>
            <AddPromotionType2>NONE</AddPromotionType2>
            <AddPromotionType3>NONE</AddPromotionType3>
            <RemovePromotionType1>PROMOTION_HORSE_THIEF</RemovePromotionType1>
            <RemovePromotionType2>NONE</RemovePromotionType2>
            <RemovePromotionType3>NONE</RemovePromotionType3>
            <bBuffCasterOnly>1</bBuffCasterOnly>
            <ConvertUnitType>NONE</ConvertUnitType>
            <CreateBuildingType>NONE</CreateBuildingType>
            <CreateFeatureType>NONE</CreateFeatureType>
            <CreateImprovementType>NONE</CreateImprovementType>
            <SpreadReligion>NONE</SpreadReligion>
            <CreateUnitType>NONE</CreateUnitType>
            <iCreateUnitNum>0</iCreateUnitNum>
            <bPermanentUnitCreate>0</bPermanentUnitCreate>
            <CreateUnitPromotion>NONE</CreateUnitPromotion>
            <bImmuneTeam>0</bImmuneTeam>
            <bImmuneNeutral>0</bImmuneNeutral>
            <bImmuneEnemy>0</bImmuneEnemy>
            <bImmuneFlying>0</bImmuneFlying>
            <bImmuneNotAlive>0</bImmuneNotAlive>
            <bDispel>0</bDispel>
            <bPush>0</bPush>
            <bRemoveHasCasted>0</bRemoveHasCasted>
            <bSacrificeCaster>0</bSacrificeCaster>
            <iChangePopulation>0</iChangePopulation>
            <iCost>0</iCost>
            <iImmobileTurns>0</iImmobileTurns>
            <iMiscastChance>0</iMiscastChance>
            <PyMiscast></PyMiscast>
            <PyResult>spellDropHorses(pCaster)</PyResult>
            <PyRequirement>reqDropHorses(pCaster)</PyRequirement>
            <Effect>EFFECT_SPELL1</Effect>
            <Sound>AS3D_SPELL_TRAIN</Sound>
            <HotKey></HotKey>
            <bAltDown>0</bAltDown>
            <bShiftDown>0</bShiftDown>
            <bCtrlDown>0</bCtrlDown>
            <bGraphicalOnly>1</bGraphicalOnly>
            <iHotKeyPriority>0</iHotKeyPriority>
            <Button>Art/Interface/Buttons/actions/drophorse.dds</Button>
        </SpellInfo>

Pretty similar. It reverses the actions of the "grab horses" spell. The custom button for this spell is the horses resource button with a red "-" superimposed.

And here are the relevant CvSpellInterface.py entires for both spells:

Spoiler :
Code:
def reqGrabHorses(caster):
	pPlot = caster.plot()
	if caster.isHasPromotion(gc.getInfoTypeForString('PROMOTION_HORSE_THIEF')):
		return False
	if pPlot.getBonusType(-1) != gc.getInfoTypeForString('BONUS_HORSE'):
		return False
	return True

def spellGrabHorses(caster):
	pPlot = caster.plot()
	pPlot.setBonusType(-1)
	pPlot.setImprovementType(-1)
	if pPlot.isOwned():
		startWar(caster.getOwner(), pPlot.getOwner())

def reqDropHorses(caster):
	pPlot = caster.plot()
#	if pPlot.getOwner() != caster.getOwner():
#		return False
	if pPlot.isWater():
		return false
	if pPlot.isCity():
		return False
	if pPlot.getBonusType(-1) != -1:
		return False
	return True

def spellDropHorses(caster):
	pPlot = caster.plot()
	iBonus = gc.getInfoTypeForString('BONUS_HORSE')
	pPlot.setBonusType(iBonus)

The "req" entries for "grab" make sure that you can't grab horses if you already have some, or if the plot in question doesn't have horses in it. The req entries for "drop" make sure you can't drop the horse resource on a plot that is water, a city, or already has a resource of some kind. The commented out part, if reactivated, would only let you drop the horses in a plot that you owned.

Grabbing horses removes the resource from the tile (and destroys any improvements -- this can be commented out, though), and then gives the unit a special promotion called PROMOTION_HORSE_THIEF. Dropping the horses removes the promotion and plops a horse resource down on the current plot.

Also, grabbing horses from a plot that someone else owns starts a war.

And here is the example of the promotion from the CIV4PromotionInfos.xml file:

Spoiler :
Code:
        <PromotionInfo>
            <Type>PROMOTION_HORSE_THIEF</Type>
            <Description>TXT_KEY_PROMOTION_HORSE_THIEF</Description>
            <Help></Help>
            <Sound>AS2D_IF_LEVELUP</Sound>
            <LayerAnimationPath>NONE</LayerAnimationPath>
            <PromotionPrereq>NONE</PromotionPrereq>
            <PromotionPrereqOr1>NONE</PromotionPrereqOr1>
            <PromotionPrereqOr2>NONE</PromotionPrereqOr2>
            <TechPrereq>NONE</TechPrereq>
            <StateReligionPrereq>NONE</StateReligionPrereq>
            <bLeader>0</bLeader>
            <bBlitz>0</bBlitz>
            <bAmphib>0</bAmphib>
            <bRiver>0</bRiver>
            <bEnemyRoute>0</bEnemyRoute>
            <bAlwaysHeal>0</bAlwaysHeal>
            <bHillsDoubleMove>0</bHillsDoubleMove>
            <bImmuneToFirstStrikes>0</bImmuneToFirstStrikes>
            <iVisibilityChange>0</iVisibilityChange>
            <iMovesChange>1</iMovesChange>
            <iMoveDiscountChange>0</iMoveDiscountChange>
            <iAirRangeChange>0</iAirRangeChange>
            <iInterceptChange>0</iInterceptChange>
            <iEvasionChange>0</iEvasionChange>
            <iWithdrawalChange>0</iWithdrawalChange>
            <iCargoChange>0</iCargoChange>
            <iCollateralDamageChange>0</iCollateralDamageChange>
            <iBombardRateChange>0</iBombardRateChange>
            <iFirstStrikesChange>0</iFirstStrikesChange>
            <iChanceFirstStrikesChange>0</iChanceFirstStrikesChange>
            <iEnemyHealChange>0</iEnemyHealChange>
            <iNeutralHealChange>0</iNeutralHealChange>
            <iFriendlyHealChange>0</iFriendlyHealChange>
            <iSameTileHealChange>0</iSameTileHealChange>
            <iAdjacentTileHealChange>0</iAdjacentTileHealChange>
            <iCombatPercent>0</iCombatPercent>
            <iCityAttack>0</iCityAttack>
            <iCityDefense>0</iCityDefense>
            <iHillsAttack>0</iHillsAttack>
            <iHillsDefense>0</iHillsDefense>
            <iKamikazePercent>0</iKamikazePercent>
            <iRevoltProtection>0</iRevoltProtection>
            <iCollateralDamageProtection>0</iCollateralDamageProtection>
            <iPillageChange>0</iPillageChange>
            <iUpgradeDiscount>0</iUpgradeDiscount>
            <iExperiencePercent>0</iExperiencePercent>
            <TerrainAttacks>
            </TerrainAttacks>
            <TerrainDefenses>
            </TerrainDefenses>
            <FeatureAttacks>
            </FeatureAttacks>
            <FeatureDefenses>
            </FeatureDefenses>
            <UnitCombatMods>
            </UnitCombatMods>
            <DomainMods>
            </DomainMods>
            <TerrainDoubleMoves>
            </TerrainDoubleMoves>
            <FeatureDoubleMoves>
            </FeatureDoubleMoves>
            <UnitCombats>
            </UnitCombats>
            <HotKey></HotKey>
            <bAltDown>0</bAltDown>
            <bShiftDown>0</bShiftDown>
            <bCtrlDown>0</bCtrlDown>
            <bGraphicalOnly>0</bGraphicalOnly>
            <iHotKeyPriority>0</iHotKeyPriority>
            <Button>Art/Interface/Buttons/WorldBuilder/Horse.dds</Button>
            <bBoarding>0</bBoarding>
            <bOnlyDefensive>0</bOnlyDefensive>
            <bDispellable>0</bDispellable>
            <bDoubleFortifyBonus>0</bDoubleFortifyBonus>
            <bEquipment>0</bEquipment>
            <bFear>0</bFear>
            <bFlying>0</bFlying>
            <bHiddenNationality>0</bHiddenNationality>
            <bIgnoreBuildingDefense>0</bIgnoreBuildingDefense>
            <bImmortal>0</bImmortal>
            <bImmuneToCapture>0</bImmuneToCapture>
            <bImmuneToFear>0</bImmuneToFear>
            <bImmuneToMagic>0</bImmuneToMagic>
            <bInvisible>0</bInvisible>
            <bMutation>0</bMutation>
            <bNotAlive>0</bNotAlive>
            <bPrereqAlive>0</bPrereqAlive>
            <bRace>0</bRace>
            <bRemovedByCasting>0</bRemovedByCasting>
            <bRemovedByCombat>0</bRemovedByCombat>
            <bRemovedWhenHealed>0</bRemovedWhenHealed>
            <bTargetWeakestUnit>0</bTargetWeakestUnit>
            <bTargetWeakestUnitCounter>0</bTargetWeakestUnitCounter>
            <bTwincast>0</bTwincast>
            <bValidate>0</bValidate>
            <bWaterWalking>0</bWaterWalking>
            <iAIWeight>0</iAIWeight>
            <iBetrayalChance>0</iBetrayalChance>
            <iBetterDefenderThanPercent>0</iBetterDefenderThanPercent>
            <iCasterResistModify>0</iCasterResistModify>
            <iCombatCapturePercent>0</iCombatCapturePercent>
            <iCombatHealPercent>0</iCombatHealPercent>
            <iCombatPercentDefense>0</iCombatPercentDefense>
            <iCombatPercentGlobalCounter>0</iCombatPercentGlobalCounter>
            <iCombatPercentInBorders>0</iCombatPercentInBorders>
            <iExpireChance>0</iExpireChance>
            <iExtraCombatStr>0</iExtraCombatStr>
            <iExtraCombatDefense>0</iExtraCombatDefense>
            <iFreeXPPerTurn>0</iFreeXPPerTurn>
            <iFreeXPFromCombat>0</iFreeXPFromCombat>
            <iModifyGlobalCounter>0</iModifyGlobalCounter>
            <iResistMagic>0</iResistMagic>
            <iSpellCasterXP>0</iSpellCasterXP>
            <iSpellDamageModify>0</iSpellDamageModify>
            <CaptureUnitCombat>NONE</CaptureUnitCombat>
            <PromotionCombatApply>NONE</PromotionCombatApply>
            <PromotionImmune1>NONE</PromotionImmune1>
            <PromotionImmune2>NONE</PromotionImmune2>
            <PromotionImmune3>NONE</PromotionImmune3>
            <PromotionRandomApply>NONE</PromotionRandomApply>
            <PromotionSummonPerk>NONE</PromotionSummonPerk>
            <BonusPrereq>NONE</BonusPrereq>
            <PromotionPrereqOr3>NONE</PromotionPrereqOr3>
            <PromotionPrereqOr4>NONE</PromotionPrereqOr4>
            <PromotionPrereqAnd>NONE</PromotionPrereqAnd>
            <PromotionNextLevel>NONE</PromotionNextLevel>
            <PyPerTurn></PyPerTurn>
            <iGroupSize>0</iGroupSize>
            <UnitArtStyleType>NONE</UnitArtStyleType>
            <PromotionCombatType>NONE</PromotionCombatType>
            <iPromotionCombatMod>0</iPromotionCombatMod>
            <DamageTypeCombats>
            </DamageTypeCombats>
            <BonusAffinities>
            </BonusAffinities>
            <DamageTypeResists>
            </DamageTypeResists>
        </PromotionInfo>

Really all it does is act as an indicator that the unit is "carrying" horses and allow the unit to cast the "drop horses" spell. Just for fun, I also made this promotion give the unit +1 movement.

******************

That's it. It really is that simple. Using this model, it is possible to make any resource portable.

The only downside currently is that if a carrying unit is killed, the resource does not get dropped like equipment. Instead, it is just lost forever. I am still playing around with expanding this concept to allow a free flow between special equipment-like units, a traditional resource, and the indicator promotions. That way, for example,a unit carrying horses could either place them as a resource, or "set them free" to create a horse unit of some kind.

I really like this idea, especially for animal resources. Potentially, a player would have to go out an "catch" a wild horses unit before ever being able to get a horses resource. Same could work for elephants to ivory!

Anyway, that was the concept I had working right before the pre-Alpha release of DA got irreparably buggy under Vista. The free conversion between resource, promotion, and unit really opens up new possibilities!

Well, that's it for this one. Hope you like it!
 
This is superb, it was what I intended in my thread about portable resources, before it got hijacked by the whole Great People thing (grrrrrrr..) Congrats and thanks for doing this.
How do I use the code in game? Is it just a case of copy/pasting into the xml? Can any unit pick up horses?
 
sometimes having a resource in a city can be good (its unpillageable, and some provide yields that allow you to exceed the 2/1/1 standard minimum) so i wouldnt bar people from putting a resource down in a city, instead id only bar them from putting the resources on terrain thats not appropriate or where theres already a resource
 
sometimes having a resource in a city can be good (its unpillageable, and some provide yields that allow you to exceed the 2/1/1 standard minimum) so i wouldnt bar people from putting a resource down in a city, instead id only bar them from putting the resources on terrain thats not appropriate or where theres already a resource

To make resources droppable in cities, you would need only to delete or comment out that portion of the def reqDropHorses entry in the CvSpellInterface.py file that deals with the city location restriction.

So the

if pPlot.isCity():
return False

would just get taken out.
 
i think im going to finally use this to make a spell for Warhammer: "dis lil piggy" the aim of the spell is to allow the orcs to get access to the pigs resource in every game by polymorphing an enemy unit into a new barbarian 'pig' unit, the pig can be captured by recon units and moved to a greenskin city and settled to make a pig resource. alternatively, i was thinking of it allowing the orcs to 'pick up' pigs, sheep, cows, horse or game and creating the 'pig' unit, which settles as a pig resource. do you think this idea will work with this mod gliblet?
 
Easily.

Just use the pick up and drop spells as I have suggested. For the orcs, then create a new spell that allows them to convert any animal resource to pigs. One way to do this would be as a promotion conversion.

For example, if an orc unit is currently "carrying" cows, and has the "cows" promotion, it would be able to cast a spell that converts the cows promotion to a pigs promotion. Under my pick up/drop system, the orc unit woul dnow be able to drop a pigs resource.
 
Top Bottom