Unit Prereq BuildingClass Array

In the Civilopedia pCity will be NULL. In that case you can use GC.getGameINLINE().getActivePlayer() to acquire the active player's ID and use it to get the civilization type.

Code:
if city is null or city doesn't have building type
  if city is null
    display message using active player to get building type
  else
    display message using city to get building type
 
In the Civilopedia pCity will be NULL. In that case you can use GC.getGameINLINE().getActivePlayer() to acquire the active player's ID and use it to get the civilization type.

Code:
if city is null or city doesn't have building type
  if city is null
    display message using active player to get building type
  else
    display message using city to get building type

Like this:

Code:
                if ((pCity == NULL) || (pCity->getNumActiveBuilding((BuildingTypes)GC.getCivilizationInfo(pCity->getCivilizationType()).getCivilizationBuildings(iI)) <= 0))
                {
                    if (pCity == NULL)
                    {
                        GC.getGameINLINE().getActivePlayer().getCivilizationBuildings()
                    }
                    else
                    {
                        GC.getBuildingClassInfo((BuildingClassTypes)(pCity->getCivilizationType()).getCivilizationBuildings(iI))
                    }
                }
 
getActivePlayer() returns a PlayerTypes. Use GET_PLAYER to get the CvPlayer on which you can call getCivilizationType(). Then use the functions just below that line to get to the building. And you need to use the building type to display the message as your old code had.
 
getActivePlayer() returns a PlayerTypes. Use GET_PLAYER to get the CvPlayer on which you can call getCivilizationType(). Then use the functions just below that line to get to the building. And you need to use the building type to display the message as your old code had.

So this?

Code:
                if ((pCity == NULL) || (pCity->getNumActiveBuilding((BuildingTypes)GC.getCivilizationInfo(pCity->getCivilizationType()).getCivilizationBuildings(iI)) <= 0))
                {
                    if (pCity == NULL)
                    {
                        GET_PLAYER(GC.getGameINLINE().getActivePlayer()).getCivilizationBuildings()
                    }
                    else
                    {
                        GC.getBuildingClassInfo((BuildingClassTypes)(pCity->getCivilizationType()).getCivilizationBuildings(iI))
                    }
                }

Maybe I'm missing the point here, but how does that fix my text problems? This code doesn't add any text to the game at all...
 
You need to merge that new code with the old code:

Code:
if ((pCity == NULL) || (pCity->getNumActiveBuilding((BuildingTypes)GC.getCivilizationInfo(pCity->getCivilizationType()).getCivilizationBuildings(iI)) <= 0))
{
	CivilizationTypes eCiv;
	
	if (pCity == NULL)
	{
		eCiv = GET_PLAYER(GC.getGameINLINE().getActivePlayer()).getCivilizationType();
	}
	else
	{
		eCiv = pCity->getCivilizationType();
	}
	
	szBuffer.append(NEWLINE);
	szBuffer.append(gDLL->getText("TXT_KEY_UNIT_REQUIRES_STRING", GC.getBuildingInfo((BuildingTypes)GC.getCivilizationInfo(eCiv).getCivilizationBuildings(iI)).getTextKeyWide()));
}

This uses either the player or the city to look up the civilization type. From there it looks up the correct building and adds it to the text.
 
One thing I just noticed is that the similar code for required building type calls getNumBuilding() instead of getNumActiveBuilding(). You might want to change your code to match.
 
One thing I just noticed is that the similar code for required building type calls getNumBuilding() instead of getNumActiveBuilding(). You might want to change your code to match.

I take it the active part means that it's not obsolete, correct?
 
That's right. The effects of the building no longer apply (except culture), but it should probably continue to allow the unit to be built. If you want the unit to obsolete with the building, just obsolete the unit with the tech that obsoletes the building. This way you have more possibilities for the modder.
 
Another question, I set up the CvGameTextMgr, and it compiled, but in game, when the spearman was set to require the forge, it said "Requires Forbidden Palace". [...]


I just want to say, that this bug also appears, when you in normal BtS give a unit a prereq building, so it would be nice to see this also fixed in the unofficial patch.
 
You need to merge that new code with the old code:

Code:
if ((pCity == NULL) || (pCity->getNumActiveBuilding((BuildingTypes)GC.getCivilizationInfo(pCity->getCivilizationType()).getCivilizationBuildings(iI)) <= 0))
{
    CivilizationTypes eCiv;
    
    if (pCity == NULL)
    {
        eCiv = GET_PLAYER(GC.getGameINLINE().getActivePlayer()).getCivilizationType();
    }
    else
    {
        eCiv = pCity->getCivilizationType();
    }
    
    szBuffer.append(NEWLINE);
    szBuffer.append(gDLL->getText("TXT_KEY_UNIT_REQUIRES_STRING", GC.getBuildingInfo((BuildingTypes)GC.getCivilizationInfo(eCiv).getCivilizationBuildings(iI)).getTextKeyWide()));
}
This uses either the player or the city to look up the civilization type. From there it looks up the correct building and adds it to the text.

I finally had time to test this code, and it gives a python exception, and then the UI is broken. I'm thinking it's the NULL issue I had last time. So, shouldn't this line be like this:

Code:
    if ((pCity == NULL) || (!pCity))

Edit:

That change didn't fix anything. Here's the exception I'm getting:
Traceback (most recent call last):

File "CvScreensInterface", line 543, in showWorldBuilderScreen

File "CvWorldBuilderScreen", line 122, in interfaceScreen

File "CvWorldBuilderScreen", line 2367, in refreshPlayerTabCtrl

RuntimeError: unidentifiable C++ exception
ERR: Python function showWorldBuilderScreen failed, module CvScreensInterface
 
"pCity == NULL" is the same as "!pCity". Are you testing this from the main menu? If so, there is no active player and we need to handle that. Oops!

Code:
BuildingTypes eRequiredBuilding = NO_BUILDING;

if (!pCity)
{
	if (GC.getGameINLINE().getActivePlayer() != NO_PLAYER)
	{
		// show unique building for active player
		eRequiredBuilding = (BuildingTypes)GC.getCivilizationInfo(GET_PLAYER(GC.getGameINLINE().getActivePlayer()).getCivilizationType()).getCivilizationBuildings(iI);
	}
	else
	{
		// show default building
		eRequiredBuilding = (BuildingTypes)GC.getBuildingClassInfo(iI).getDefaultBuildingIndex();
	}
}
else
{
	// show unique building for city's owner if city doesn't have any
	eRequiredBuilding = (BuildingTypes)GC.getCivilizationInfo(pCity->getCivilizationType()).getCivilizationBuildings(iI);
	if (pCity->getNumActiveBuilding(eRequiredBuilding) > 0)
	{
		eRequiredBuilding = NO_BUILDING;
	}
}
if (eRequiredBuilding != NO_BUILDING)
{
    szBuffer.append(NEWLINE);
    szBuffer.append(gDLL->getText("TXT_KEY_UNIT_REQUIRES_STRING", GC.getBuildingInfo(eRequiredBuilding).getTextKeyWide()));
}
 
That doesn't compile:

1>CvGameTextMgr.cpp(10524) : error C2664: 'CvBuildingClassInfo &CvGlobals::getBuildingClassInfo(BuildingClassTypes)' : cannot convert parameter 1 from 'int' to 'BuildingClassTypes'
1> Conversion to enumeration type requires an explicit cast (static_cast, C-style cast or function-style cast)
1>CvGameTextMgr.cpp(10524) : error C2228: left of '.getDefaultBuildingIndex' must have class/struct/union type
1>NMAKE : fatal error U1077: '"C:/Program Files (x86)/Microsoft Visual C++ Toolkit 2003/bin/cl.exe"' : return code '0x2'
 
BuildingTypes, PlayerTypes, DomainTypes, etc are all enumerations. To convert from an int like 2 to a BuildingClassTypes you use an explicit cast which looks like this:

(BuildingClassTypes)iI​
 
BuildingTypes, PlayerTypes, DomainTypes, etc are all enumerations. To convert from an int like 2 to a BuildingClassTypes you use an explicit cast

I know what casting is. I know BuildingTypes and BuildingClassTypes are different datatypes. However, this isn't working:

Code:
eRequiredBuilding = (BuildingClassTypes)GC.getBuildingClassInfo(iI).getDefaultBuildingIndex();

Obviously, I'm missing some big point here...
 
Notice in the error message that is says the first parameter to getBuildingClassInfo() is a BuildingClassTypes. iI is only an int. You need to cast iI to BCT instead of changing the cast that's already there.

Code:
eRequiredBuilding = [B](BuildingTypes)[/B]GC.getBuildingClassInfo([B](BuildingClassTypes)[/B]iI).getDefaultBuildingIndex();
 
Notice in the error message that is says the first parameter to getBuildingClassInfo() is a BuildingClassTypes. iI is only an int. You need to cast iI to BCT instead of changing the cast that's already there.

Code:
eRequiredBuilding = [B](BuildingTypes)[/B]GC.getBuildingClassInfo([B](BuildingClassTypes)[/B]iI).getDefaultBuildingIndex();

Ohh...

Okay. Thanks. I'll see how that works.
 
Well, I just tested the new code with the Malinese, who have a UB that replaces the forge. I set spearmen to require the forge. Building the Malinese UB unlocks spearmen, correctly, but the text before I built it said "Requires Castle" instead of "Requires Mint"
 
The Civilopedia should show a Forge before starting a game. Once you start a game as MM it should show a Mint. When you open a city it should show a Mint if it doesn't have one.

Are you sure you compiled the above changes and are running that DLL? Can you add some text to each of those cases like this:

Code:
BuildingTypes eRequiredBuilding = NO_BUILDING;

if (!pCity)
{
	if (GC.getGameINLINE().getActivePlayer() != NO_PLAYER)
	{
		// show unique building for active player
		eRequiredBuilding = (BuildingTypes)GC.getCivilizationInfo(GET_PLAYER(GC.getGameINLINE().getActivePlayer()).getCivilizationType()).getCivilizationBuildings(iI);
		[B]szBuffer.append(NEWLINE L"Unique Building for Active Player");[/B]
	}
	else
	{
		// show default building
		eRequiredBuilding = (BuildingTypes)GC.getBuildingClassInfo((BuildingClassTypes)iI).getDefaultBuildingIndex();
		[B]szBuffer.append(NEWLINE L"Default Building");[/B]
	}
}
else
{
	// show unique building for city's owner if city doesn't have any
	eRequiredBuilding = (BuildingTypes)GC.getCivilizationInfo(pCity->getCivilizationType()).getCivilizationBuildings(iI);
	if (pCity->getNumActiveBuilding(eRequiredBuilding) > 0)
	{
		eRequiredBuilding = NO_BUILDING;
		[B]szBuffer.append(NEWLINE L"City Has Unique Building");[/B]
	}
	[B]else
	{
		szBuffer.append(NEWLINE L"Unique Building for City");
	}[/B]
}
if (eRequiredBuilding != NO_BUILDING)
{
    szBuffer.append(NEWLINE);
    szBuffer.append(gDLL->getText("TXT_KEY_UNIT_REQUIRES_STRING", GC.getBuildingInfo(eRequiredBuilding).getTextKeyWide()));
}
 
Back
Top Bottom