python question

orlanth

Storm God. Yarr!
Joined
Nov 17, 2001
Messages
1,805
To prevent players from using a captured Treasure to explore around at will, I'm trying to apply promotion to Treasure units that reduces their sight range and gives a negative healing rate. Giving this promotion in Civ4Unitinfos.xml didnt work, so I tried adding the following python code in Cv4EventManager.py .

Code:
	def onUnitCreated(self, argsList):
		'Unit Completed'
		unit = argsList[0]
#treasure promo		
		unitInfo = gc.getUnitInfo(unit.getUnitType())
		if unitInfo == gc.getInfoTypeForString('UNIT_TREASURE'):
			unit.setHasPromotion(gc.getInfoTypeForString("PROMOTION_VULNERABLE"), 1)
#end treasure promo
		if (not self.__LOG_UNITBUILD):
			return

Unfortunately it's still doesn't seem to be doing anything. Can anyone spot what I'm doing wrong?

Spoiler :
<PromotionInfo>
<Type>PROMOTION_VULNERABLE</Type>
<Description>Vulnerable</Description>
<Sound>AS2D_IF_LEVELUP</Sound>
<PromotionPrereq>NONE</PromotionPrereq>
<PromotionPrereqOr1>NONE</PromotionPrereqOr1>
<PromotionPrereqOr2>NONE</PromotionPrereqOr2>
<bLeader>0</bLeader>
<bBlitz>0</bBlitz>
<bAmphib>0</bAmphib>
<bRiver>0</bRiver>
<bEnemyRoute>0</bEnemyRoute>
<bAlwaysHeal>0</bAlwaysHeal>
<bHillsDoubleMove>0</bHillsDoubleMove>
<iVisibilityChange>-1</iVisibilityChange>
<iMovesChange>0</iMovesChange>
<iMoveDiscountChange>0</iMoveDiscountChange>
<iWithdrawalChange>0</iWithdrawalChange>
<iCargoChange>0</iCargoChange>
<iBombardRateChange>0</iBombardRateChange>
<iEnemyHealChange>-10</iEnemyHealChange>
<iNeutralHealChange>-10</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>
<iPillageChange>0</iPillageChange>
<iUpgradeDiscount>0</iUpgradeDiscount>
<iExperiencePercent>0</iExperiencePercent>
<TerrainAttacks/>
<TerrainDefenses/>
<FeatureAttacks/>
<FeatureDefenses/>
<UnitClassAttackMods/>
<UnitClassDefenseMods/>
<UnitCombatMods/>
<DomainMods/>
<TerrainDoubleMoves/>
<FeatureDoubleMoves/>
<UnitCombats/>
<HotKey/>
<bAltDown>0</bAltDown>
<bShiftDown>0</bShiftDown>
<bCtrlDown>0</bCtrlDown>
<bGraphicalOnly>1</bGraphicalOnly>
<iHotKeyPriority>0</iHotKeyPriority>
<Button>Art/Interface/Buttons/units/floating eye.dds</Button>
</PromotionInfo>
 
Hi orlanth,

everything considering logic should better be done in DLL to my opinion. :)

  1. It is easier. You do not need workarounds like promotions.
  2. DLL is much better than Python considering Performance.
  3. Smaller risk of bugs. (Mostly because of the better development tools.)
  4. In DLL you have much more possibilities. Not all methods are available in Python.

Also, what about the following approach ?
(Because it has already been done several times and works very well.)

  1. Treasures cannot move in undiscovered terrains.
  2. Treasures cannot talk to Chiefs.
  3. Treasures cannot move on Goody Huts.

Best regards,
ray

Edit:

Sorry for my post. :blush:
I just read here, that you do not know C++ / DLL-Modding.
It is worth learning though. :thumbsup:
It gives you a lot more "power" and possibilities.
 
Hi everyone,

I'll try to look into it if I have some time...

I've got an idea. Try to allow building treasures (I don't know if it's easy, but it should be simple Xml modding).
Build a treasure. If it has your vulnerable promotion, than means onUnitCreated applies only to newly built units, and not to captured treasures... If it hasn't vulnerable promotion the problem is worse, and we'll have to try something else.

Maybe my idea is a little dumb... I don't know
 
I've got an idea. Try to allow building treasures (I don't know if it's easy, but it should be simple Xml modding).
Build a treasure. If it has your vulnerable promotion, than means onUnitCreated applies only to newly built units, and not to captured treasures... If it hasn't vulnerable promotion the problem is worse, and we'll have to try something else.

That should not be the problem.

1. Promotions should be transferred, when a unit is captured.
(If I remember the code correct.)

2. When a unit is captured, technically a new unit is created.
Therefore onUnitCreated should apply also.

@olranth:

Did you start with a new game ?
Because with a Savegame, there would be problems of course.
(Never test with Savegame ...)
 
To prevent players from using a captured Treasure to explore around at will, I'm trying to apply promotion to Treasure units that reduces their sight range and gives a negative healing rate. Giving this promotion in Civ4Unitinfos.xml didnt work, so I tried adding the following python code in Cv4EventManager.py .

Code:
	def onUnitCreated(self, argsList):
		'Unit Completed'
		unit = argsList[0]
#treasure promo		
		unitInfo = gc.getUnitInfo(unit.getUnitType())
		if unitInfo == gc.getInfoTypeForString('UNIT_TREASURE'):
			unit.setHasPromotion(gc.getInfoTypeForString("PROMOTION_VULNERABLE"), 1)
#end treasure promo
		if (not self.__LOG_UNITBUILD):
			return

Unfortunately it's still doesn't seem to be doing anything. Can anyone spot what I'm doing wrong?

Spoiler :
<PromotionInfo>
<Type>PROMOTION_VULNERABLE</Type>
<Description>Vulnerable</Description>
<Sound>AS2D_IF_LEVELUP</Sound>
<PromotionPrereq>NONE</PromotionPrereq>
<PromotionPrereqOr1>NONE</PromotionPrereqOr1>
<PromotionPrereqOr2>NONE</PromotionPrereqOr2>
<bLeader>0</bLeader>
<bBlitz>0</bBlitz>
<bAmphib>0</bAmphib>
<bRiver>0</bRiver>
<bEnemyRoute>0</bEnemyRoute>
<bAlwaysHeal>0</bAlwaysHeal>
<bHillsDoubleMove>0</bHillsDoubleMove>
<iVisibilityChange>-1</iVisibilityChange>
<iMovesChange>0</iMovesChange>
<iMoveDiscountChange>0</iMoveDiscountChange>
<iWithdrawalChange>0</iWithdrawalChange>
<iCargoChange>0</iCargoChange>
<iBombardRateChange>0</iBombardRateChange>
<iEnemyHealChange>-10</iEnemyHealChange>
<iNeutralHealChange>-10</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>
<iPillageChange>0</iPillageChange>
<iUpgradeDiscount>0</iUpgradeDiscount>
<iExperiencePercent>0</iExperiencePercent>
<TerrainAttacks/>
<TerrainDefenses/>
<FeatureAttacks/>
<FeatureDefenses/>
<UnitClassAttackMods/>
<UnitClassDefenseMods/>
<UnitCombatMods/>
<DomainMods/>
<TerrainDoubleMoves/>
<FeatureDoubleMoves/>
<UnitCombats/>
<HotKey/>
<bAltDown>0</bAltDown>
<bShiftDown>0</bShiftDown>
<bCtrlDown>0</bCtrlDown>
<bGraphicalOnly>1</bGraphicalOnly>
<iHotKeyPriority>0</iHotKeyPriority>
<Button>Art/Interface/Buttons/units/floating eye.dds</Button>
</PromotionInfo>

Hey! :)

You have to enable "USE_ON_UNIT_CREATED_CALLBACK" inside PythonCallbackDefines.xml to make it work.
 
I would say this code line is the reason for your trouble:
Code:
if unitInfo == gc.getInfoTypeForString('UNIT_TREASURE'):
Try:
Code:
#treasure promo		
		unitInfo = gc.getUnitInfo(unit.getUnitType())
		[B]if unitInfo.isTreasure():[/B]
			unit.setHasPromotion(gc.getInfoTypeForString("PROMOTION_VULNERABLE"), 1)
#end treasure promo
:)
 
It's getting closer, but that caused a python callback:
AttributeError: 'CyUnit' object has no attribute 'setHasPromotion'

I looked into the dll.
setHasPromotion is no method in the dll (unless you are using some special dll where somebody coded it for you of course) ...
(neither in CyUnit nor in CvUnit nor anywhere else)

Where did you see that method ? :confused:

What I could find for example is:
(Both can be called from Python from the CyUnit object.)

void setHasRealPromotion(PromotionTypes eIndex, bool bValue);
void promote(PromotionTypes ePromotion, int iLeaderUnitId);

One of these should be what you are looking for.
But I am not really sure, what you really want to do. :dunno:
(Why don't you just assign the Promotion to your unit in XML ?)
 
You're right, changing it to setHasRealPromotion solved the python error. However it looks like my promotion approach doesn't succeed it making Treasure units unable to explore and talk to Chiefs etc; you might be right that this needs a DLL change. You mentioned this has been done before, is it in TAC or another mod?
 
You mentioned this has been done before, is it in TAC or another mod?

No, not in TAC.
But I think I have seen it for example in 1492- Global Colonization from KJ_Jansson.

But what you describe sounds like very simple logic.
You are probably faster when trying yourself, than searching it in other mods.

If I was you, I would probably code it in these mehtods of CvUnit.cpp:

bool CvUnit::canMoveInto(const CvPlot* pPlot, bool bAttack, bool bDeclareWar, bool bIgnoreLoad) const

bool CvUnit::canSpeakWithChief(CvPlot* pPlot) const
 
I tried starting to mod with the SDK but was just making a mess of things :blush: I'd better stick with python for now.

As a separate question, is there any way to do a python check for lake plots (the sea plots that start inland)? I wanted to place a special improvement over these during the python map creation.
 
Back
Top Bottom