Unit Statistics for FFH

Abandon City/Raze Building mod modifies the same file as the unit statistics mod does, CvCustomEventManager.py. This means that only the mod you install last will work properly.
 
If I remember correctly, I noticed that and so merged the two python files together, but still only UnitStats worked. Maybe I just didn't merge them very well.
 
After most modmods had trouble with patch d, a new version for patch e is up and running smoothly.
 
Oh...never mind then. Thanks for updating. I would go ahead and download, but it seems like Vehem is going to include all the schema changes my modmod needs (including this mod), so I might as well wait for that.
 
UnitStats for FFH2 0.32j is up (people seem not to notice when I update it quietly).
 
Update for version l is up. I hope I don't have to repeat this every two days...
 
Just merged this into FF and all seems to work very nicely, with the sole exception of the "Top 10" option.

The exception isn't one that I'm familiar with - any ideas?

At first glance it sounded like something may have changed in 3.17 - though I'm not sure having looked at it.
 

Attachments

  • UnitStats-Top10.jpg
    UnitStats-Top10.jpg
    48.1 KB · Views: 125
Yep, that error pops up when the program is expecting a list/dictionary object, but the object is actually an integer or string.

This usually happens when sdObjectGetVal (line 200, two lines before the line that returns an error) fails (it will then return 0). It will also print the error message "initialize object first!" to the file PythonDbg.log. You can go check if this is indeed the case, which would mean that my diagnosis is correct.

My guess would then be that the 'template' in which the actual values are later filled in (called UnitStatsData in UnitStatisticsDefines.py) is not created for new units, which in turn is most likely caused (assuming that you didn't fiddle with the python files themselves) by a wrong entry in PythonCallbackDefines.xml. USE_ON_UNIT_CREATED_CALLBACK and USE_ON_UNIT_LOST_CALLBACK have to be set to 1 for it to work correctly (and you need to add USE_UNIT_STATISTICS_CALLBACK).
 
Would it be somehow possible that you merge this with the FfH BUG mod? Maybe you and its developer could work together and combine the mods "for good", since I'd guess that nobody would not want one or the other...?
 
Yep, that error pops up when the program is expecting a list/dictionary object, but the object is actually an integer or string.

This usually happens when sdObjectGetVal (line 200, two lines before the line that returns an error) fails (it will then return 0). It will also print the error message "initialize object first!" to the file PythonDbg.log. You can go check if this is indeed the case, which would mean that my diagnosis is correct.

My guess would then be that the 'template' in which the actual values are later filled in (called UnitStatsData in UnitStatisticsDefines.py) is not created for new units, which in turn is most likely caused (assuming that you didn't fiddle with the python files themselves) by a wrong entry in PythonCallbackDefines.xml. USE_ON_UNIT_CREATED_CALLBACK and USE_ON_UNIT_LOST_CALLBACK have to be set to 1 for it to work correctly (and you need to add USE_UNIT_STATISTICS_CALLBACK).

Thanks for the quick reply - the error string is present in PythonDbg.log, but so are the call backs...

Code:
	<Define>
		<DefineName>USE_ON_UNIT_CREATED_CALLBACK</DefineName>
		<iDefineIntVal>1</iDefineIntVal>
	</Define>
	<Define>
		<DefineName>USE_ON_UNIT_LOST_CALLBACK</DefineName>
		<iDefineIntVal>1</iDefineIntVal>
	</Define>
	<Define>
		<DefineName>USE_UNIT_STATISTICS_CALLBACK</DefineName>
		<iDefineIntVal>1</iDefineIntVal>
	</Define>
</Civ4Defines>

Most of the Python files were included untouched - with the exception of the MainInterface.py, though as I understood the code placed there it shouldn't be related to that.

Having looked a little more carefully at things though - I've realised that the details of individual combats (%chance, damage inflicted etc) aren't being stored either. I'm going to take a look at the DLL files again to make sure I haven't missed something there, before going to the Python to find the actual called back functions.
 
Teg, I was wondering about a few lines in UnitStatisticsTools. Lines 87-103:
Code:
			else:
				
				for i in range(14):
					if (htype == DAMAGETYPE[i]):
						for objUnit in unitList:
							damagestats = sdObjectGetVal("UnitStats", objUnit, DAMAGESTATS)
							if (not i / 7):
								data = damagestats[INFLICTED][i % 7]
							else:
								data = damagestats[SUFFERED][i % 7]
							datalist.append(data)
						break
				
				else:
				
					for objUnit in unitList:
						datalist.append(sdObjectGetVal("UnitStats", objUnit, htype))

Line 100 has an ELSE statement which lines up with a FOR statement. Never seen that before and wonder if it is intentional/actually works. And as for the FOR Statement, range 14, and checks for Damagetypes? There are only 7 Damgetypes in FfH, unless that is not meant to be Fire/Ice/Death/Holy/Unholy, but some other Statistics defined Damagetype... A quick search of that file showed that it most likely is some internally defined tracking system.
 
The iTypeofAttack value is passed from the SDK hook to the function onCombatHit:

# iTypeofAttack
# 0: (empty, reserved for total damage)
# 1: Attacker is hit
# 2: Defender is hit
# 3: Collateral damage (defender is hit)
# 4: Flanking strike (defender is hit)
# 5: Air Strike (defender is hit)
# 6: Other (FfH magic?) (defender is hit)

#6 is not used yet. For the high scores, there are 14 damage types (for each of the seven, maximum amount of damage inflicted and suffered). This approach might be a little less transparent at first, but it makes the code more maintainable - there is now a single function that handles damage tracking instead of one for each of these types (as was the case in earlier versions).

About the for statement at the end of a for-loop: Yep, that's intentional
 
FYI: I added a python callback on combat result in 0.33. It will probably break Unit Stats, but its not a huge deal to enable. Its set in the PythonCallbackDefines.xml file.
 
Whoops, looks like I've copied the new source files to the wrong location. I've attached them to this message.
 

Attachments

  • SDKfiles.zip
    101.4 KB · Views: 59
Top Bottom