How to check if a unit is in a capital

LyTning94

Dragonborn
Joined
Nov 10, 2010
Messages
397
Location
Skyrim
Is there an easy way to check if a specific unit is in a specific capital? I have tried different things with CvCity::plot() and CvUnit::plot() but I can't seem to get anything to work. In addition, does GC.getNumUnitInfos() return the number of units in the game (like one for warrior, one for archer, one for axeman, etc.) or the number of units currently in play (on the map). If it returns the former, do I have to use CvPlayer::firstUnit() and CvPlayer::nextUnit() to get a specific unit?

Thanks in advance! :)
 
Are you starting off with a CvUnit, CvCity or a CvPlayer?

The problem should be trivial in any case, so expect a solution shortly.
 
Okay, I think I figured out how to do it. But now I have another problem. In this new function from CvPlayerAI:

Code:
int CvPlayerAI::AI_getCapitalDiploAttitude(PlayerTypes ePlayer)
{
	int iAttitude;
	int eUnit;
	CvUnitInfo* pUnit = NULL;
	for (eUnit = 0; eUnit < GC.getNumUnitInfos(); eUnit++)
	{
		[COLOR="Red"]pUnit = eUnit;[/COLOR]		
                if (pUnit->getCapitalDiploModifier())
		{
			if (isUnitInCapital(ePlayer, pUnit))
			{
				iAttitude += pUnit->getCapitalDiploModifier();
			}
		}
	}
	return iAttitude;
}

the compiler says I can't convert 'int' to 'CvUnitInfo*'.

I am having the same problem with this line:

Code:
[COLOR="red"]if (isUnitInCapital(ePlayer, pUnit))[/COLOR]

because it calls this function:

Code:
bool CvPlayer::isUnitInCapital(PlayerTypes ePlayer, [COLOR="red"]CvUnit* pUnit[/COLOR]) const
{
	CvCity* pCapital = GET_PLAYER(ePlayer).getCapitalCity();
	if (pCapital->plot() == pUnit->plot())
	{
		return true;
	}
	else
	{
		return false;
	}
}

and, as you can see, I need this function to take a CvUnit* pointer.

I don't really know much about pointers, so could someone show me how to convert between different types and between integers and pointers? Or, if this can't be done, how to avoid having to do this?
 
I realize that your question is C++ specific, but since I don't know any C++ I can only answer this in Python terms. (The Python API is just a mirror of the real C++ one anyway.)

To get a CvUnitInfo instance in Python you have to call CyGlobalContext.getUnitInfo(eUnitType). So first you need to get the UnitType value with CyUnit.getUnitType().

And to get a CyUnit instance corresponding to a indexed unit you use CyPlayer.getUnit(iIndex). Units aren't indexed globally, but every player has a linked list of unit to call their own.

This should translate pretty closely to C++ but I'm unsure on the syntax and stuff.
 
I fixed my problem with the pointers, and made a few changes based on what you said. Here is my current function:

Code:
int CvPlayerAI::AI_getCapitalDiploAttitude(PlayerTypes ePlayer) const
{
	int iAttitude;
	int eUnit;
	int eUnitType;
	for (eUnit = 0; eUnit < getNumUnits(); eUnit++)
	{
		eUnitType = getUnit(eUnit)->getUnitType();
		if (GC.getUnitInfo((UnitTypes)eUnitType).getCapitalDiploModifier())
		{
			if (isUnitInCapital(ePlayer, (CvUnit*)eUnitType))
			{
				iAttitude += GC.getUnitInfo((UnitTypes)eUnitType).getCapitalDiploModifier();
			}
		}
	}
	return iAttitude;
}

However, the game crashes when calling getUnitType(). I know you don't program C++, but can you see anything I did wrong? I'm assuming I called the wrong function(s) somewhere.

I'm especially not sure about getUnit() in this line:

Code:
eUnitType = getUnit(eUnit)->getUnitType();

getUnit(int iID) calls getAt(iID). I'm not sure what getAt() does, so I don't know if eUnit will work there.
Code:
CvUnit* CvPlayer::getUnit(int iID) const
{
	return (m_units.getAt(iID));
}
 
Nah, its all pretty much Greek to me... :dunno:
 
It looks like getUnitType() causes the crash because the unit object with that ID doesn't exist. Unit and City IDs are dynamic so they have to be iterated using the provided iterators, not consecutive numbers. In other words, replace your loop with this:

Code:
	int iLoop;
	CvUnit* pLoopUnit;
	for(pLoopUnit = firstUnit(&iLoop); pLoopUnit != NULL; pLoopUnit = nextUnit(&iLoop))
	{
		eUnitType = pLoopUnit->getUnitType();
		// rest of the code
	}
 
Yeah, If I would have been able to read even 30% of the C++ code I would probably have come to the same conclusion. :rolleyes:

I need to look into this C++ business, even if only to become more effective at Python modding.
 
Turns out I didn't need getUnitType() at all. I was wondering if I needed to use firstPlayer() and nextPlayer() to get a specific unit, but wasn't sure...

Thanks for your help. :king:
 
Top Bottom