God-Emperor
Deity
There is a bug in CvGameTextMgr.cpp regarding getting the description of a unit.
This could be the cause of various mystery crashes. It is probably the culprit in this post by SO, and it also turns up in various other threads (one or two of them also by SO). It could explain any crash pointing to CvMainInterface's updateHelpStrings function (on the line looking like "screen.setHelpTextString( CyInterface().getHelpString() )" in both C2C and RoM:AND.
The issue is the misuse of the getDescription method of the getDescription for the CvUnitInfo class.
Specifically, it hasn't got one so it uses the one inherited from the CvInfoBase. This has no clue about the existence of the "new" (if you consider something probably over 3 years old new) civilization specific unit names. Passing it a civilization type as the argument is wrong.
In CvGameTextMgr::setPlotListHelp when there is a stack of units on the plot that is greater in number than the set limit (15, currently) it runs some code that smaller stacks don't use - the code that shows multiples of units with aggregate promotions and average strength. The relevant line in the v26 code is line 2113, which is in an Afforess comment and looks like this:
The problem is that the getDescription function of the unit info takes as a parameter the "uiForm", that is the form of the text - like the singular masculine or plural female form. If you are playing as civilization 0 this will not be a problem since it will get a correct form. If you are playing as, say, civilization type 42 then the code in the CvInfoBase::getDescription will try to load another 42 forms, which I expect never exist, and load whatever happens to be past the end of the real data as if it were text strings. Most likely as null terminated text strings, so you could end up with some pretty long chunks of random text, or other junk, possibly from whatever is 42 entries later in the stored text data.
The CvUnit::getDescription function (added by Afforess) deals with the civ specific unit names, and does not need to be passed the civ number either - if you do pass it (it may be happening multiple times through the source code) then it will also be treated as the "uiForm" and do the same thing if the unit does not have a civ-specific unit name for your civ. Basically, you should never ever pass the civilization type to the getDescription call for a unit or unit info since the argument is never used for that.
This specific bug is in CvGameTextMgr in at least 4 locations.
In CvGameTextMgr it also does the lookup for the civ specific name correctly in at least one place, and also in the code for CvUnit.getDescription. A fixed version of the above line of code should look more like this, using the same style as the way it is already done in there:
Or something like that (don't forget to define bFound as a bool). Yes, it's a lot more code. Yes, it should probably be made into a function.
I have no idea how many other places in the code outside CvGameTextMgr make this same mistake of passing a civilization type to getDescription for either a CvUnit or CvUnitInfo.
Another 3 places in CvGameTextMgr that do this:
line 14246, in CvGameTextMgr::setBuildingHelpActual
line 14414, in CvGameTextMgr::setBuildingHelpActual also
line 14454, in CvGameTextMgr::setBuildingHelpActual also also
This could be the cause of various mystery crashes. It is probably the culprit in this post by SO, and it also turns up in various other threads (one or two of them also by SO). It could explain any crash pointing to CvMainInterface's updateHelpStrings function (on the line looking like "screen.setHelpTextString( CyInterface().getHelpString() )" in both C2C and RoM:AND.
The issue is the misuse of the getDescription method of the getDescription for the CvUnitInfo class.
Specifically, it hasn't got one so it uses the one inherited from the CvInfoBase. This has no clue about the existence of the "new" (if you consider something probably over 3 years old new) civilization specific unit names. Passing it a civilization type as the argument is wrong.
In CvGameTextMgr::setPlotListHelp when there is a stack of units on the plot that is greater in number than the set limit (15, currently) it runs some code that smaller stacks don't use - the code that shows multiples of units with aggregate promotions and average strength. The relevant line in the v26 code is line 2113, which is in an Afforess comment and looks like this:
Code:
/************************************************************************************************/
/* Afforess Start 08/25/10 */
/* */
/* */
/****************************************************************/************************************************************************************************/
/*
szString.append(CvWString::format(SETCOLR L"%s" ENDCOLR, TEXT_COLOR("COLOR_UNIT_TEXT"), GC.getUnitInfo((UnitTypes)iI).getDescription()));
*/
[B]szString.append(CvWString::format(SETCOLR L"%s" ENDCOLR, TEXT_COLOR("COLOR_UNIT_TEXT"), GC.getUnitInfo((UnitTypes)iI).getDescription(GET_PLAYER((PlayerTypes)iJ).getCivilizationType())));[/B]
/****************************************************************/************************************************************************************************/
/* Afforess END */
/****************************************************************/************************************************************************************************/
The problem is that the getDescription function of the unit info takes as a parameter the "uiForm", that is the form of the text - like the singular masculine or plural female form. If you are playing as civilization 0 this will not be a problem since it will get a correct form. If you are playing as, say, civilization type 42 then the code in the CvInfoBase::getDescription will try to load another 42 forms, which I expect never exist, and load whatever happens to be past the end of the real data as if it were text strings. Most likely as null terminated text strings, so you could end up with some pretty long chunks of random text, or other junk, possibly from whatever is 42 entries later in the stored text data.
The CvUnit::getDescription function (added by Afforess) deals with the civ specific unit names, and does not need to be passed the civ number either - if you do pass it (it may be happening multiple times through the source code) then it will also be treated as the "uiForm" and do the same thing if the unit does not have a civ-specific unit name for your civ. Basically, you should never ever pass the civilization type to the getDescription call for a unit or unit info since the argument is never used for that.
This specific bug is in CvGameTextMgr in at least 4 locations.
In CvGameTextMgr it also does the lookup for the civ specific name correctly in at least one place, and also in the code for CvUnit.getDescription. A fixed version of the above line of code should look more like this, using the same style as the way it is already done in there:
Code:
bFound = false;
if (GC.getUnitInfo((UnitTypes)iI).getCivilizationName(GET_PLAYER((PlayerTypes)iJ).getCivilizationType()) != NULL)
{
if (!CvWString(GC.getUnitInfo((UnitTypes)iI).getCivilizationName(GET_PLAYER((PlayerTypes)iJ).getCivilizationType())).empty())
{
bFound = true;
szUnitName = gDLL->getText(GC.getUnitInfo((UnitTypes)iI).getCivilizationName(GET_PLAYER((PlayerTypes)iJ).getCivilizationType()));
}
}
if (!bFound)
{
szUnitName = GC.getUnitInfo((UnitTypes)iI).getDescription();
}
Or something like that (don't forget to define bFound as a bool). Yes, it's a lot more code. Yes, it should probably be made into a function.
I have no idea how many other places in the code outside CvGameTextMgr make this same mistake of passing a civilization type to getDescription for either a CvUnit or CvUnitInfo.
Another 3 places in CvGameTextMgr that do this:
line 14246, in CvGameTextMgr::setBuildingHelpActual
line 14414, in CvGameTextMgr::setBuildingHelpActual also
line 14454, in CvGameTextMgr::setBuildingHelpActual also also