Changing the UnitArtInfo via python?

SaibotLieh

Emperor
Joined
Sep 25, 2009
Messages
1,589
I would like change the appearance, but nothing else, of single units during the game. Basically changing the UnitArtInfo of the unit would do the trick and at first glance this should actually be possible with python, using this code which should give all new build warriors the appearance of archer units (CvEventManager.py):

Code:
def onUnitBuilt(self, argsList):
		'Unit Completed'
		city = argsList[0]
		unit = argsList[1]
		player = PyPlayer(city.getOwner())

		if iUnitClass == gc.getInfoTypeForString('UNITCLASS_WARRIOR'):
		
			UnitArtInfo = unit.getArtInfo(0,EraTypes.NO_ERA)
			UnitArtInfo.setTag('ART_DEF_UNIT_ARCHER')

# this part's purpose is to control if the tag actually changed

			tagtext = UnitArtInfo.getTag()
			CyInterface().addImmediateMessage(tagtext,'')

# this part's purpose is to control if the tag actually changed - end
		
		CvAdvisorUtils.unitBuiltFeats(city, unit)
	
		if (not self.__LOG_UNITBUILD):
			return
		CvUtil.pyPrint('%s was finished by Player %d Civilization %s' 
			%(PyInfo.UnitInfo(unit.getUnitType()).getDescription(), player.getID(), player.getCivilizationName()))

If this code is used, the game always crashes at the time a warrior unit is build. However, one second before the crash the tagtext is displayed correctly, so I guess the game needs some time to get angry because of the made UnitArtInfo change.
So, is there a way to change the UnitArtInfo via python? I know that FFH2 has a python command called setUnitArtStyleType that seem so do what I want, but I can't find anywhere how it does so.
 
I dug into this a little and found several ways to do it with small changes in the sdk. I am pretty sure there is no pure python solution. I do not know why your python code should crash.

I describe what I was trying to accomplish in this thread.

Planetfall has a small sdk change to redefine the siege tower. See this thread. This is used to put a small boat icon next to a ground unit which is moving on ocean.

FFH has some code which swaps art under certain conditions. You can see some discussion in this thread. This is the approach I actually used in Dune Wars, which is working.

You didn't say much about what you are actually trying to do; maybe one of these approaches will help, or maybe not.
 
It's a rather small thing what I'm trying to do. I've created a female CEO model and would like to have a certain probability that each time a CEO is build it will turn up as the female version. It's just eye-candy, so I wanted to make it as simple as possible, but I guess I'll have to dig in my sdk files again.
 
It's a rather small thing what I'm trying to do. I've created a female CEO model and would like to have a certain probability that each time a CEO is build it will turn up as the female version. It's just eye-candy, so I wanted to make it as simple as possible, but I guess I'll have to dig in my sdk files again.

I guess it doesn't matter if you have two separate units. Would this work? Add a female CEO unit, where the only difference is the art definition. Then in python onUnitBuilt, if it is a male CEO, take a 50% chance to delete the unit and create a female one instead.
 
I've thought about that possibility, but that would put 7 new units in the list for only little benefit. Besides, the CEOs have a maximum number one can build/control at the same time. Adding the seperate female CEOs would undermine this restriction.
 
I've thought about that possibility, but that would put 7 new units in the list for only little benefit. Besides, the CEOs have a maximum number one can build/control at the same time. Adding the seperate female CEOs would undermine this restriction.

The extra units add minimal actual cost. In what I have proposed, there is no change in the maximum number of units existing; when a male unit is created, there is a 50% chance to delete it and add a female unit. I think it would work, and it doesn't require any sdk change.
 
The extra units add minimal actual cost. In what I have proposed, there is no change in the maximum number of units existing; when a male unit is created, there is a 50% chance to delete it and add a female unit. I think it would work, and it doesn't require any sdk change.

The problem is that each civ can have only 3 CEOs (for example) of each company, but this restriction only counts toward the male CEOs this way. Each time one of the male CEOs gets switched with a female one a new male one can be build. Theoretical one civ could have (for another example) 2 female and 3 male CEOs of the Sushi Company at the same time this way. However, in the end this is only a minor problem and I can take this route, thanks for your input btw, I just would favor switching only the UnitArtInfo.
 
Maybe you can instead of re-directing the warrior to the archer artdef try to change the .nif and .kfm from the warrior artdef.

I would be interested, if that works, because i've tried it with buildings, and it worked partially.
The question is, if you can get access/can deal in a good way with the civilization artstyles (this didn't work for me, but i didn't have enough time to dig deeper in it).
 
Maybe you can instead of re-directing the warrior to the archer artdef try to change the .nif and .kfm from the warrior artdef.

I would be interested, if that works, because i've tried it with buildings, and it worked partially.
The question is, if you can get access/can deal in a good way with the civilization artstyles (this didn't work for me, but i didn't have enough time to dig deeper in it).

Tried changing the .nif. Partially is the magic word here, because it in fact changed the appearance of the unit, but only in the display in the lower left corner, but not on the map. I tried to reproduce this just now, but somehow it doesn't work anymore. :(
Anyhow, even if it would have worked it wouldn't be a solution for me, because I want to change the unit sound, too. With changing the whole UnitArtInfo this would be no problem.

Make the female a different UnitType of the same UnitClass, and the national limit will be maintained.

Damn, haven't thought about that at all. Always learning something new here. This makes the extra unit approach a real alternative now. Still I would be more happy with just changing the artwork. Can't have anything I guess. ;)
 
I think I found a workaround for my problem with 'spaming' my civilopedia units list with to many units. I modified The_J's python modcomp 'Civilopedia: Invisible dummy techs' (http://forums.civfanatics.com/downloads.php?do=file&id=13873) to work for units. Have to think about the attribute that will make the units invisible (in the Civilopedia), but that should be no big problem.
 
It seems to me that the most direct solution would be to make is so that if the unit's Civilopedia tag is empty, it just does not show up in the 'pedia.
 
Tried changing the .nif. Partially is the magic word here, because it in fact changed the appearance of the unit, but only in the display in the lower left corner, but not on the map. I tried to reproduce this just now, but somehow it doesn't work anymore. :(
You need to force the game to update the graphics by using CvUnit::reloadEntity() (not sure if this is exposed to python, but probably is). In FFH changing the Art of a Unit (without replacing it with a different Unittype) works flawless, so there is definetly a way.
 
It seems to me that the most direct solution would be to make is so that if the unit's Civilopedia tag is empty, it just does not show up in the 'pedia.

Doesn't that create an empty entry in the Pedia? At least for Techs it does so, haven't tried it for units so far.

You need to force the game to update the graphics by using CvUnit::reloadEntity() (not sure if this is exposed to python, but probably is). In FFH changing the Art of a Unit (without replacing it with a different Unittype) works flawless, so there is definetly a way.

You are absolutely right, the reload is the problem here. I now could reproduce the effect I spoke about if only the .nif is changed (The SHADERNIF has to be deactivated). After reloading the game, the right unitart is displayed (see pictures). Sadly the reloadEntity() function seems not to be exposed to python, at least unit.reloadEntity() doesn't work.
 

Attachments

  • BeforeReload.jpg
    BeforeReload.jpg
    134.2 KB · Views: 80
  • AfterReload.jpg
    AfterReload.jpg
    132.6 KB · Views: 154
Interesting.

I have some questions:
- What happens, when you build your next CEO? Is it male or female?
- What happens, if you load/unload that unit into/from a ship (before or after re-loading)?
- If you try that with a combat unit, what happens in/after a combat? What unit art is displayed?
 
Interesting.

I have some questions:
- What happens, when you build your next CEO? Is it male or female?
- What happens, if you load/unload that unit into/from a ship (before or after re-loading)?
- If you try that with a combat unit, what happens in/after a combat? What unit art is displayed?

The male was build male and doesn't change it's appearance even if load/unload, haven't tested it for combat units so far.
While testing the load/unload part I discovered more funny effects. Reloading the saved game only results in a female CEO if the Civ 4 program wasn't restarted in the mean time. If Civ 4 is restarted, everything turns back male. On the other hand, if the CEO was build once in a game, and the saved game is reloaded it turns out all female when build, even when the last game wasn't saved (and Civ 4 wasn't restarted in the mean time of course). :crazyeye:
My best guess is that the game memorizes the change of the unit as long as the Civ 4 program itself isn't restarted.

If you want to play a bit with switching the .nifs and .kfms, here is the code I used:

Code:
UnitArtInfo = unit.getArtInfo(0,EraTypes.NO_ERA)
UnitArtInfo.setTag('ART_DEF_UNIT_CEO_6_FEMALE')
tagtext = UnitArtInfo.getTag()
CyInterface().addImmediateMessage(tagtext,'')
UnitArtInfo.setNIF('Art/Units/CEO/Logos/CEO_Aluminum_Female.nif')
niftext = UnitArtInfo.getNIF()
CyInterface().addImmediateMessage(niftext,'')
UnitArtInfo.setKFM('Art/Units/CEO/Logos/CEO_Aluminum_Female.kfm')
kfmtext = UnitArtInfo.getKFM()
CyInterface().addImmediateMessage(kfmtext,'')
 
.
While testing the load/unload part I discovered more funny effects. Reloading the saved game only results in a female CEO if the Civ 4 program wasn't restarted in the mean time. If Civ 4 is restarted, everything turns back male. On the other hand, if the CEO was build once in a game, and the saved game is reloaded it turns out all female when build, even when the last game wasn't saved (and Civ 4 wasn't restarted in the mean time of course). :crazyeye:
My best guess is that the game memorizes the change of the unit as long as the Civ 4 program itself isn't restarted.

If you want to play a bit with switching the .nifs and .kfms, here is the code I used:

That's sad, that the information is not stored elsewhere, and that the changes are done globaly :(.
I wished, it could be done instance dependend :(.

Can't play myself here, no civ available until beginning of january :(.
 
It seems to me that the most direct solution would be to make is so that if the unit's Civilopedia tag is empty, it just does not show up in the 'pedia.
Doesn't that create an empty entry in the Pedia? At least for Techs it does so, haven't tried it for units so far.

Well, yes. But consider that I said "make it so that". You said:
Have to think about the attribute that will make the units invisible (in the Civilopedia), but that should be no big problem.
I was just suggesting which tag's behavior it would be logical to change. What could be more logical than making a unit with no data in its Civilopedia tag not show up in the civilopedia? Your only other options are to use some tag that isn't entirely related to the civilopedia or add a new tag, or to look for some specific value stored in the Civilopedia (or other somewhat random) tag (like, "SET_INVISIBLE", for example).
 
That's sad, that the information is not stored elsewhere, and that the changes are done globaly :(. I wished, it could be done instance dependend :(.

In both FFH and DW, unit art is switched on an instance basis. The code is rather small, but it is an sdk change. See the thread I linked above. I guess there is no python *only* solution for this.
 
Back
Top Bottom