Setting Attributes for New Unit

OrionVeteran

Deity
Joined
Dec 25, 2003
Messages
2,443
Location
Newport News VA
I hope this is an easy one. I have created a new unit using Python. Now I want to dynamically change some attributes for this new unit to values other than what is in the XML for this unit. The attributes I want to change are:

1. iMoves
2. iCombat
3. iPower
4. iXPValueAttack
5. iXPValueDefense

For Example: Lets say I want to double the following values found in the XML...

1. iMoves = 1
2. iCombat = 5
3. iPower = 5
4. iXPValueAttack = 4
5. iXPValueDefense = 2

How can I make the change to each default value for a unit using python? I want these new values to be permanant for this one unit, without affecting other units of the same type. More specifically, I could have 5 other Axemen in addition to the one Axeman I am changing through python. Only the one Axeman is affected by the update. Can it be done?
 
There are Python calls for the first two via the unit object, but I don't say anything for the other 3.
Moves: CyUnit.setMoves(iNewMoves)
Combat: CyUnit.setBaseCombatStr(iNewCombat)
 
I have got past the unit attributes, but not the promotions. I have set up a global variable for an appended list of promotions. I want to use the global appended list in another function, but the code keeps failing on the variable. :confused:

In the first function, this part works:
Code:
global ArmyPromotions
ArmyPromotions = []

...

for iProm in range(gc.getNumPromotionInfos()):
	if (pUnitZ.isHasPromotion(iProm)):
		ArmyPromotions.append([iProm])

In the second function, this part fails on the variable in Red.
Code:
global ArmyPromotions

...

for iProm in range(len(TargetUnit.[B][COLOR="Red"]ArmyPromotions[/COLOR][/B])):
	if not TargetUnit.isHasPromotion(ArmyPromotions[iProm]):
		TargetUnit.setHasPromotion(ArmyPromotions[iProm], True)

I want to append the appended list of promotions to the TargetUnit. What am I doing wrong?
 
Why are you invoking your list on the CyUnit instance? Just do this:
Code:
for iProm in range(len(ArmyPromotions)):
 
Why are you invoking your list on the CyUnit instance? Just do this:
Code:
for iProm in range(len(ArmyPromotions)):


OK did this:
Code:
for iProm in range(len([COLOR="Red"][B]ArmyPromotions[/B][/COLOR])):
	if not TargetUnit.isHasPromotion(ArmyPromotions[iProm]):
		TargetUnit.setHasPromotion(ArmyPromotions[iProm], True)

And got this message for the same line: Remember "global ArmyPromotions" is defined. :confused:
 

Attachments

  • ArmyPromotions.jpg
    ArmyPromotions.jpg
    19.8 KB · Views: 54
I think "for boo in globalarmypromos:" would work.. but here's how I handle this, and it's a more general solution so perhaps just use it. onUnitCreated checks for certain variables and uses them if they exist. Here is the relevant part of the def:

Code:
	  try :
		  self.nextUnitPromotions
	  except :
		  pass
	  else :
		  for promo in self.nextUnitPromotions:
         	        iPromo = gc.getInfoTypeForString(promo)
                        CvUtil.pyPrint('%s promo is %s' %(promo,iPromo))
		        pUnit.setHasPromotion(iPromo, True)
		  del self.nextUnitPromotions

	  try :
		  self.nextUnitPromotionsIDX
	  except :
		  pass
	  else :
		  for promo in self.nextUnitPromotionsIDX:
         	        # iPromo = gc.getInfoTypeForString(promo)
                        # CvUtil.pyPrint('%s promo is %s' %(promo,iPromo))
		        pUnit.setHasPromotion(promo, True)
		  del self.nextUnitPromotionsIDX

self.slaveUnitName = "Blemmyes"
self.nextUnitPromotions = ["PROMOTION_CITY_RAIDER1","PROMOTION_CITY_RAIDER2"]
pPlayer.initUnit(self.iLybianMercID, iX, iY, UnitAITypes.UNITAI_ATTACK_CITY)
 
And got this message for the same line: Remember "global ArmyPromotions" is defined. :confused:
Try adding the global statement in the function:
Code:
[B]global ArmyPromotions[/B]
for iProm in range(len(ArmyPromotions)):
	if not TargetUnit.isHasPromotion(ArmyPromotions[iProm]):
		TargetUnit.setHasPromotion(ArmyPromotions[iProm], True)
 
Ok, we're both clearly missing something here. What is the full script for this?

This is actually a good candidate for using Object-Oriented Programming (a class, basically) in order to avoid using global variables...
 
Ok, we're both clearly missing something here. What is the full script for this?

This is actually a good candidate for using Object-Oriented Programming (a class, basically) in order to avoid using global variables...

I decided to make a major change to how I created the Army unit. I have found a way to isolate and bring in the new Army unit earlier. This allowed me to modify it from only one function instead of two. Everything needed to create and update the unit works, including the promotion function. As a result, this difficult problem is now obsolete. The final code is way too much to publish here. However, you will get your chance to see the final code when I release the all new Army unit for CiV4. ...Just a few more supplimental ideas to implement and the new mod will be finished. :dance:

I thank all of you, who tried to help resolve this difficult issue.

:thanx:
 
While my PYTHON promotion code works, the more I look at it, the more it needs to be tweaked. So, I'm going to ask for your ideas on how to improve this code.

Some background information: I have taken the promotions from a selected group of units an applied all of those promotions to one new Army unit. (That's one powerful unit!). What I want to do is determine which of the promotions the Army can keep and which ones will be removed. It is not a simple as giving each promotion a randum chance. No. The problem here is there could be a promotion, say Combat 4, that has prerequisite promotions all the way down to Combat 1. So I can't just remove Combat 1, 2 or 3, with a randum chance. If I keep Combat 4, I have to keep all of the prerequisite promotions 1, 2 and 3. So, I'm not sure how to run a randum chance and exclude the prerequisite promotions as needed. This code needs to work with all available promotions the Army unit may receive, not just my example combat promotions. Any ideas would be helpful.
 
It should only be a matter of logic, really. Figuring out a smart way of doing it would of course be very satisfying. So I might give it a try if I have the time. :D
 
It should only be a matter of logic, really. Figuring out a smart way of doing it would of course be very satisfying.

Absolutely! I have created a data table that will return the Promotion level for a given promotion. Its kind of long, but might be the key to getting this done. It can be called like this:

Code:
for iProm in range(gc.getNumPromotionInfos()):
	if MyNewArmyUnit.isHasPromotion(iProm):
		if Army.getPromotionLevel(iProm) == 4:

The Promotion level is where the promotion exists in the promotion tree, not the actual number for a promotion like Combat 4.

What else can be done?
 
Oh, a getPromotionLevel() metmod simplifies would simplify this a lot! :king: Unfortunately I can't seem to find anything like it in the API. :confused:

I'm not quite sure how this would work, though. So the new Army unit inherits promotions from units "merging" with it then? What promotions are available for the unit? All? Why is there a random chance at all?

A way to start would be to build a data structures with all the valid promotions. Because then it would be a matter of checking whether or not any promotion matches it:
Code:
if ePromotion in promotionsArray:
 
Oh, a getPromotionLevel() metmod simplifies would simplify this a lot! :king: A way to start would be to build a data structures with all the valid promotions. Because then it would be a matter of checking whether or not any promotion matches it:

Yes indeed. I have a quick question. I am trying to create a function with a counter that works in reverse.

Code:
iMax = getHighestPromotionLevel(kGroup)

for (i = iMax; i >= 0; --i):

The for line blows up. How can I fix it?
 
Oh, this is in the SDK, right? Why can't you make the same function with Python?
 
Oh, this is in the SDK, right? Why can't you make the same function with Python?

No. Its Python. I think I got it:

Code:
for i in range(i = iMax, 1, -1):

Nope. That blew up to.

This worked:

Code:
iMax = getHighestPromotionLevel(kGroup)
	
for i in range(iMax, 0, -1):
 
I now have a full set of logical functions to handle the promotions. Whew! Lots of work. Now I want to improve the efficiency: I have a for loop command and I want to group repeating field values to only one occurance on the return.

Example:

Instead of returning:

COMBAT
COMBAT
COMBAT
COMBAT
COMBAT
COMBAT
COMBAT
GUERILLA
GUERILLA
GUERILLA

I want to get:

COMBAT
GUERILLA

Here is the for statement:

Code:
for szPromotion, (iPromotionLevel, strGroup) in dPromotionList.iteritems():

The field I want to group is the strGroup field.

Hopefully this is an easy one for you.
 
Why exactly are you iterating dPromotionsList? I would assume that you would want the dictionary:
Code:
{
"COMBAT1" : (1, "COMBAT"),
"COMBAT2 : (2, "COMBAT"),
"COMBAT3 : (3, "COMBAT"),
"COMBAT4 : (4, "COMBAT"),
"COMBAT5 : (5, "COMBAT"),
"COMBAT6 : (6, "COMBAT"),
"COMBAT7 : (7, "COMBAT"),
"GUERILLA1 : (1, "GUERILLA"),
"GUERILLA2 : (2, "GUERILLA"),
"GUERILLA3 : (3, "GUERILLA"),
}
...to return the index values of PromotionTypes.PROMOTION_COMBAT7 and PromotionTypes.PROMOTION_GUERILLA3. Because you wanna do something with these enums, right?
 
Back
Top Bottom