[SDK] Build Errors... Help!?!

Davinci Fan

Chieftain
Joined
Jun 6, 2007
Messages
86
This began as a problem I'd had with my mod, but since it has been solved, I thought I'd share it with everyone:

Follow Kael's tutorial on adding XML tags in the tutorials forum. Specifically:
Civ4TerrainSchema.XML:

Code:
	<ElementType name="bNoRiverSide" content="textOnly" dt:type="boolean"/>
	[B]<ElementType name="bRequiresWater" content="textOnly" dt:type="boolean"/>[/B] //line 216 in the unmodified version
	<ElementType name="bNormalize" content="textOnly" dt:type="boolean"/>
...
		<element type="bNoRiverSide"/>
		[B]<element type="bRequiresWater"/>[/B] //line 265
		<element type="bNormalize"/>

In CIV4BonusInfos.XML (every entry):

Code:
			<bNoRiverSide>0</bNoRiverSide>
			[B]<bRequiresWater>0</bRequiresWater>[/B] //change to 1 to restrict this resource
			<bNormalize>0</bNormalize>

CvInfos.cpp:

Code:
//------------------------------------------------------------------------------------------------------
//
//  FUNCTION:   CvBonusInfo()
//
//  PURPOSE :   Default constructor
//
//------------------------------------------------------------------------------------------------------
CvBonusInfo::CvBonusInfo() :
...
m_bNoRiverSide(false),
[B]m_bRequiresWater(false),[/B]
m_bNormalize(false),


[CENTER]...[/CENTER]


//------------------------------------------------------------------------------------------------------
//
//  FUNCTION:   ~CvBonusInfo()
//
//  PURPOSE :   Default destructor
//
//------------------------------------------------------------------------------------------------------
CvBonusInfo::~CvBonusInfo()
...
bool CvBonusInfo::[B]isRequiresWater()[/B] const			
{
	return m_bRequiresWater; 
}


[CENTER]...[/CENTER]


void CvBonusInfo::read(FDataStreamBase* stream)
{
...
	stream->Read(&m_bNoRiverSide);
	[B]stream->Read(&m_bRequiresWater);[/B]
	stream->Read(&m_bNormalize);


[CENTER]...[/CENTER]


void CvBonusInfo::write(FDataStreamBase* stream)
...
	stream->Write(m_bNoRiverSide);
	[B]stream->Write(m_bRequiresWater);[/B]
	stream->Write(m_bNormalize);


[CENTER]...[/CENTER]


	pXML->GetChildXmlValByName(&m_bNoRiverSide, "bNoRiverSide");
	[B]pXML->GetChildXmlValByName(&m_bRequiresWater, "bRequiresWater");[/B]
	pXML->GetChildXmlValByName(&m_bNormalize, "bNormalize");

CvInfos.h:

Code:
	DllExport bool isNoRiverSide() const;					// Exposed to Python
	[B]DllExport bool isRequiresWater() const;		[/B]			// Exposed to Python
	DllExport bool isNormalize() const;						// Exposed to Python


[CENTER]...[/CENTER]


	bool m_bNoRiverSide;
	[B]bool m_bRequiresWater;[/B]
	bool m_bNormalize;

To add functionality, modify CvMapGenerator.cpp:

Code:
bool CvMapGenerator::canPlaceBonusAt(BonusTypes eBonus, int iX, int iY, bool bIgnoreLatitude)
{
	...
	if (pPlot->isWater())
	{
		if (((GC.getMapINLINE().getNumBonusesOnLand(eBonus) * 100) / (GC.getMapINLINE().getNumBonuses(eBonus) + 1)) < pInfo.getMinLandPercent())
		{
			return false;
		}
	}

[B]	if (GC.getBonusInfo(eBonus).isRequiresWater())
	{
		if (!(pPlot->isCoastalLand(0) || pPlot->isFreshWater()))
		{
			return false;
		}
	}[/B]
	
	// Make sure there are no bonuses of the same class (but a different type) nearby:

	iRange = pClassInfo.getUniqueRange();
	...

	return true;
}

Remember: the 'i' in isRequiresWater is lower-case...


Below is the original post:​

I'm working on a comp for my mod that adds a tag to BonusInfos that allow me to restrict a resource to coasts and rivers.

I've followed Kael's tutorial to great success in the setup department (thanks for that), but while programming the functionality, I've hit a road block, and my relatively limited experience is unequipped to solve this problem.

There does not appear to be any problem with anything from the tutorial, since everything compiled just fine after that, so for the moment I'd like to hope that the problem here is in my programming.

Here is what I've added thus far:

Code:
bool CvMapGenerator::canPlaceBonusAt(BonusTypes eBonus, int iX, int iY, bool bIgnoreLatitude)
{
	PROFILE_FUNC();

	CvArea* pArea;
	CvPlot* pPlot;
	CvPlot* pLoopPlot;
	int iRange;
	int iDX, iDY;
	int iI;

	pPlot = GC.getMapINLINE().plotINLINE(iX, iY);
	pArea = pPlot->area();
	
	...

	CvBonusInfo& pInfo = GC.getBonusInfo(eBonus);
	CvBonusClassInfo& pClassInfo = GC.getBonusClassInfo((BonusClassTypes) pInfo.getBonusClassType());

	if (pPlot->isWater())
	{
		if (((GC.getMapINLINE().getNumBonusesOnLand(eBonus) * 100) / (GC.getMapINLINE().getNumBonuses(eBonus) + 1)) < pInfo.getMinLandPercent())
		{
			return false;
		}
	}

[B]	if (pInfo.IsRequiresWater)
	{
		if (!(pPlot.IsCoastalLand || pPlot.IsFreshWater))
		{
			return false;
		}
	}[/B]

	...

	return true;
}
IsRequiresWater is a function I modeled according to the tutorial, exactly copying IsNoRiverside (except for the name obviously) with respect to the'get' function.

When I compile, I get three errors:
Error 2039: 'IsRequiresWater' : is not a member of 'CvBonusInfo'
Error 2228: left of '.IsCoastalLand' must have class/struct/union type
Error 2228: left of '.IsFreshWater' must have class/struct/union type

Can someone more literate than I help me out here?

Thanks,
 
I'm working on a comp for my mod that adds a tag to BonusInfos that allow me to restrict a resource to coasts and rivers.

I've followed Kael's tutorial to great success in the setup department (thanks for that), but while programming the functionality, I've hit a road block, and my relatively limited experience is unequipped to solve this problem.

There does not appear to be any problem with anything from the tutorial, since everything compiled just fine after that, so for the moment I'd like to hope that the problem here is in my programming.

Here is what I've added thus far:

Code:
bool CvMapGenerator::canPlaceBonusAt(BonusTypes eBonus, int iX, int iY, bool bIgnoreLatitude)
{
	PROFILE_FUNC();

	CvArea* pArea;
	CvPlot* pPlot;
	CvPlot* pLoopPlot;
	int iRange;
	int iDX, iDY;
	int iI;

	pPlot = GC.getMapINLINE().plotINLINE(iX, iY);
	pArea = pPlot->area();
	
	...

	CvBonusInfo& pInfo = GC.getBonusInfo(eBonus);
	CvBonusClassInfo& pClassInfo = GC.getBonusClassInfo((BonusClassTypes) pInfo.getBonusClassType());

	if (pPlot->isWater())
	{
		if (((GC.getMapINLINE().getNumBonusesOnLand(eBonus) * 100) / (GC.getMapINLINE().getNumBonuses(eBonus) + 1)) < pInfo.getMinLandPercent())
		{
			return false;
		}
	}

[B]	if (pInfo.IsRequiresWater)
	{
		if (!(pPlot.IsCoastalLand || pPlot.IsFreshWater))
		{
			return false;
		}
	}[/B]

	...

	return true;
}
IsRequiresWater is a function I modeled according to the tutorial, exactly copying IsNoRiverside (except for the name obviously) with respect to the'get' function.

When I compile, I get three errors:
Error 2039: 'IsRequiresWater' : is not a member of 'CvBonusInfo'
Error 2228: left of '.IsCoastalLand' must have class/struct/union type
Error 2228: left of '.IsFreshWater' must have class/struct/union type

Can someone more literate than I help me out here?

Thanks,

1.) Do you come from a C# background? If so, there aren't really such things as "properties" in C++, the "IsRequiresWater" function is just that: a function, so it needs the ()'s after it....

2.) pPlot is a pointer to a CvPlot, and because it's a pointer, you need to use "->IsFreshWater" instead of ".IsFreshWater", once again remembering the ()'s.

So...

Code:
if (pInfo.IsRequiresWater[i]()[/i])
	{
		if (!(pPlot[i]->[/i]IsCoastalLand[i]()[/i] || pPlot[i]->[/i]IsFreshWater[i]()[/i]))
		{
			return false;
		}
	}
 
Thank you very much, you've eliminated two of the errors.

I'm a little hazy on the difference between '.' and '->,' could you explain a little more fully?

I'm left only with the first error (Error 2039: 'IsRequiresWater' : is not a member of 'CvBonusInfo'), and I've no clue what's causing it, other than perhaps that I've never modified any file called CvBonusInfo.cpp because as far as I can tell, it doesn't exist...
 
I'm a little hazy on the difference between '.' and '->,' could you explain a little more fully?

To make it quick and easy: As always (Java and so ...) the point "." is used to access the members of an object. In C++ it's possibe that a variable doesn't contain the object itself, but only a pointer to its address in memory (indicated by a star "*"). In this case you have to use the the arrow "->" to get the members. After all the arrow is just a short notation for "(*object).member", which is the same as "object->member".

I'm left only with the first error (Error 2039: 'IsRequiresWater' : is not a member of 'CvBonusInfo'), and I've no clue what's causing it, other than perhaps that I've never modified any file called CvBonusInfo.cpp because as far as I can tell, it doesn't exist...

Looks like a probem in the xml file or its schema file. Did you test your mod after only manipulating theses files?
 
I can't figure out what's wrong with the XML, I think my problem may be here:

Code:
	[B]CvBonusInfo& pInfo = GC.getBonusInfo(eBonus);
	CvBonusClassInfo& pClassInfo = GC.getBonusClassInfo((BonusClassTypes) pInfo.getBonusClassType());
[/B]
	if (pPlot->isWater())
	{
		if (((GC.getMapINLINE().getNumBonusesOnLand(eBonus) * 100) / (GC.getMapINLINE().getNumBonuses(eBonus) + 1)) < pInfo.getMinLandPercent())
		{
			return false;
		}
	}

	if ([B]pInfo[/B].IsRequiresWater())
	{
		if (!(pPlot->isCoastalLand(0) || pPlot->isFreshWater()))
		{
			return false;
		}
	}

Can someone tell me what the first bold part does? I have a feeling I may be using the wrong things. What I want to do is read the value in the XML tag of the bonus in question, then run the if statement if the bonus requires water.
 
I can't figure out what's wrong with the XML

It's not an XML problem. The XML has no effect whatsoever on compiling the SDK, problems may happen when the SDK tries to read from the XML at run time, but not now.

I think my problem may be here:

Code:
Can someone tell me what the first bold part does?  I have a feeling I may be using the wrong things.  What I want to do is read the value in the XML tag of the bonus in question, then run the if statement if the bonus requires water.[/QUOTE]


There are different info classes in the SDK, normally one per XML file. At the beginning of the game, the XML files are loaded, and their values copied into these classes. The CvBonusInfo class stores all the values that you'd see under the CvBonusInfos.xml file. The CvBonusClassInfo class stores all the values that you'd see under the CvBonusClassInfos.xml file. You can find these classes listed in CvInfos.h and CvInfos.cpp.

Because you're using the & character, pInfo becomes a reference object. You  can read more about reference vs. pointer online, it's a tough concept that might take awhile to click if you're not used to it. For now, just know that for all references, use ".", for all pointers, use "->".

In any case, modifying the XML isn't enough. If you haven't yet, read Kael's tutorial on adding XML attributes. You'll see that you'll need to modify the CvInfos.cpp and CvInfos.h files before you can call new functions (such as IsRequiresWater) on the CvBonusInfo class.
 
That's just it, I followed his tutorial, modified the cpp and h files, and compiled and loaded without a hitch. It's only when I tried to add functionality that the problems cropped up.
 
So, an update,

My code now looks like this:
Code:
	if (GC.getBonusInfo(eBonus).[B]IsNoRiverSide[/B]())
	{
		if (!(pPlot->isCoastalLand(0) || pPlot->isFreshWater()))
		{
			return false;
		}
	}
note that the function I'm checking is one that's already part of the base game.

I still get the error: Error 2039: 'IsNoRiverSide' : is not a member of 'CvBonusInfo'

Any tips?
 
So, an update,

My code now looks like this:
Code:
	if (GC.getBonusInfo(eBonus).[B]IsNoRiverSide[/B]())
	{
		if (!(pPlot->isCoastalLand(0) || pPlot->isFreshWater()))
		{
			return false;
		}
	}
note that the function I'm checking is one that's already part of the base game.

I still get the error: Error 2039: 'IsNoRiverSide' : is not a member of 'CvBonusInfo'

Any tips?

I think it's a lowercase 'i'.
 
Top Bottom