Strange Coding Problem

Ah... ok... had it backwards.

So that suggests these should look like this:
Code:
	//TB SubCombat Mod begin
	if (getNumSubCombatTypes() != 0)
	{
		m_aiSubCombatTypes.clear();
		for ( int i = 0; i < getNumSubCombatTypes(); i++)
		{
			m_aiSubCombatTypes.push_back(getSubCombatType(i));
		}
	}
	//TB SubCombat Mod end

OR FOR DELAYED RESOLUTION

	if (getNumPrereqBonusTypes() != 0)
	{
		int iNum = getNumPrereqBonusTypes();
		m_aiPrereqBonusTypes.resize(iNum);
		for (int i=0; i<iNum; i++)
		{
			GC.copyNonDefaultDelayedResolution((int*)&(m_aiPrereqBonusTypes[i]), (int*)&(pClassInfo->m_aiPrereqBonusTypes[i]));
		}
	}



EDIT: also... side question: Can I safely use the DelayedResolution method on any given tag as a standard, or should I wait and convert if the first method doesn't work (or better yet, how do I determine whether I will need it or not before I even start?)
 
Ah... ok... had it backwards.

So that suggests these should look like this:
Code:
	//TB SubCombat Mod begin
	if (getNumSubCombatTypes() != 0)
	{
		m_aiSubCombatTypes.clear();
		for ( int i = 0; i < getNumSubCombatTypes(); i++)
		{
			m_aiSubCombatTypes.push_back(getSubCombatType(i));
		}
	}
	//TB SubCombat Mod end

OR FOR DELAYED RESOLUTION

	if (getNumPrereqBonusTypes() != 0)
	{
		int iNum = getNumPrereqBonusTypes();
		m_aiPrereqBonusTypes.resize(iNum);
		for (int i=0; i<iNum; i++)
		{
			GC.copyNonDefaultDelayedResolution((int*)&(m_aiPrereqBonusTypes[i]), (int*)&(pClassInfo->m_aiPrereqBonusTypes[i]));
		}
	}
Now check for == 0 instead of != 0 and it should work.
 
Wouldn't the difference between != and == there be the difference between saying:
!=: if we have content in the module
vs
==: if we don't have content in the module

The other way I could see it (that may support what you're telling me) is:
==: if we haven't yet adjusted due to information in the current module, whether or not there exists any information in the current module, then go ahead and overwrite this tag's info with whatever happens to be (or not be) in the current module.

That wouldn't be quite right because it would force every module to include the original data even if we wanted to leave it alone if there's no changes. Thus a module could not ignore the tag altogether expecting it not to be otherwise overwritten. (and maybe that's the point... by this we're saying we expect all modules to include a full rewrite, with edits, but also with the default values maintained. Is that correct? Or do we say basically this, with an understanding that the system is already set up to assign the original values in the core version if no changes exist - thus getSubCombatType(i) is going to read to the last loaded version of the unit if a tag doesn't exist in the module version?)
 
Wouldn't the difference between != and == there be the difference between saying:
!=: if we have content in the module
vs
==: if we don't have content in the module

The other way I could see it (that may support what you're telling me) is:
==: if we haven't yet adjusted due to information in the current module, whether or not there exists any information in the current module, then go ahead and overwrite this tag's info with whatever happens to be (or not be) in the current module.

That wouldn't be quite right because it would force every module to include the original data even if we wanted to leave it alone if there's no changes. Thus a module could not ignore the tag altogether expecting it not to be otherwise overwritten. (and maybe that's the point... by this we're saying we expect all modules to include a full rewrite, with edits, but also with the default values maintained. Is that correct? Or do we say basically this, with an understanding that the system is already set up to assign the original values in the core version if no changes exist - thus getSubCombatType(i) is going to read to the last loaded version of the unit if a tag doesn't exist in the module version?)
If the number of sub combat types defined in the module are 0, then use the old content by copying it over from the old instance. If there are any sub combat types defined in the new module, then use those and ignore the content in the old instance.
 
Ah... ok, I see how that works there then.

One more set to review... hopefully I've adopted the lessons learned from the last round here. But I have one major concern in the Read(stream) segment as no examples seem to exist for this sort of methodology. Also, I'm still wondering if I can safely utilize these Delayed Resolutions on all these tags or if I must be selective about their use only in situations where it becomes necessary. And one more little question: how much improved performance would we get if we took up the laborious effort of converting all pair tags to vectors?

Anyhow, if you could look this over and let me know if I have any problems, it'd be appreciated:
Spoiler :
Code:
For an integer by type

Step 1 CvProperties.h:

struct UnitCombatModifier
{
	int iModifier;
	UnitCombat eUnitCombat;
};

H files:

Under: class CvPromotionInfo :	public CvHotkeyInfo

	UnitCombatModifier& getUnitCombatCommunicabilityModifier(int index);
	int getNumUnitCombatCommunicabilityModifiers() const;

Under: class CvPromotionInfo :
	public CvInfoBase
{
protected:
	std::vector<UnitCombatModifier> m_aUnitCombatCommunicabilityModifiers;



Then, in the info cpp:


CvPromotionInfo::~CvPromotionInfo()
{

	for (int i=0; i<(int)m_aUnitCombatCommunicabilityModifierTypes.size(); i++)
	{
		GC.removeDelayedResolution((int*)&m_aUnitCombatCommunicabilityModifierTypes.size[i]));
	}





UnitCombatModifier& CvPromotionInfo::getUnitCombatCommunicabilityModifier(int index)
{
	FAssertMsg(index < (int)m_aUnitCombatCommunicabilityModifiers.size(), "Index out of bounds");
	FAssertMsg(index > -1, "Index out of bounds");
	return m_aUnitCombatCommunicabilityModifiers[index];
}

int CvPropertyInfo::getNumUnitCombatCommunicabilityModifiers() const
{
	return (int)m_aUnitCombatCommunicabilityModifiers.size();
}


Under: void CvPromotionInfo::read(FDataStreamBase* stream):

make sure the following is located under this declaration:
	int iNumElements;
	int iElement;
	int iElementInt;

[COLOR="Red"]	stream->Read(&iNumElements);
	m_aUnitCombatCommunicabilityModifierTypes.clear();
	for (int i = 0; i < iNumElements; ++i)
	{
		stream->Read(&iElement);
		stream->Read(&iElementInt);
		m_aUnitCombatCommunicabilityModifierTypes.push_back(std::make_pair((UnitCombatTypes)iElement, iElementInt));
	}[/COLOR] Very concerned this would be entirely incorrect but I can't see how you would've done this since your only examples are in regions that don't require the read(stream).




	stream->Write(m_aUnitCombatCommunicabilityModifierTypes.size());
	for (UnitCombatModifierArray::iterator it = m_aUnitCombatCommunicabilityModifierTypes.begin(); it != m_aUnitCombatCommunicabilityModifierTypes.end(); ++it)
	{
		stream->Write((*it).eUnitCombat);
		stream->Write((*it).iModifier);
	}




	CheckSumC(iSum, m_aUnitCombatCommunicabilityModifierTypes);




Under:
bool CvPromotionInfo::read(CvXMLLoadUtility* pXML):

	if(gDLL->getXMLIFace()->SetToChildByTagName( pXML->GetXML(), "UnitCombatCommunicabilityModifiers"))
	{
		int i = 0;
		int iNum = gDLL->getXMLIFace()->NumOfChildrenByTagName( pXML->GetXML(), "UnitCombatCommunicabilityModifier" );
		m_aUnitCombatCommunicabilityModifiers.resize(iNum); // Important to keep the delayed resolution pointers correct

		if(gDLL->getXMLIFace()->SetToChild( pXML->GetXML() ))
		{

			if (gDLL->getXMLIFace()->LocateFirstSiblingNodeByTagName(pXML->GetXML(), "UnitCombatCommunicabilityModifier"))
			{
				do
				{
					pXML->GetChildXmlValByName(&(m_aUnitCombatCommunicabilityModifiers[i].iModifier), "iModifier");
					pXML->GetChildXmlValByName(szTextVal, "UnitCombatClass");
					GC.addDelayedResolution((int*)&(m_aUnitCombatCommunicabilityModifiers[i].eUnitCombat), szTextVal);
					i++;
				} while(gDLL->getXMLIFace()->LocateNextSiblingNodeByTagName(pXML->GetXML(), "UnitCombatCommunicabilityModifier"));
			}
			gDLL->getXMLIFace()->SetToParent( pXML->GetXML() );
		}
		gDLL->getXMLIFace()->SetToParent( pXML->GetXML() );
	}






Under:
void CvPromotionInfo::copyNonDefaults(CvPromotionInfo* pClassInfo, CvXMLLoadUtility* pXML)

	if (getNumUnitCombatCommunicabilityModifiers() == 0)
	{
		int iNum = pClassInfo->getNumUnitCombatCommunicabilityModifiers();
		m_aUnitCombatCommunicabilityModifiers.resize(iNum);
		for (int i=0; i<iNum; i++)
		{
			[COLOR="Red"]m_aUnitCombatCommunicabilityModifiers[i] = pClassInfo->getUnitCombatCommunicabilityModifier(i);[/COLOR] (a point of concern... didn't we NOT need this in the previous examples?  Why then is it located here in the examples I've found you programmed?)
			GC.copyNonDefaultDelayedResolution((int*)&(m_aUnitCombatCommunicabilityModifiers[i].eUnitCombat), (int*)&(pClassInfo->getUnitCombatCommunicabilityModifiers(i).eUnitCombat));
		}
	}
 
Ah... ok, I see how that works there then.

One more set to review... hopefully I've adopted the lessons learned from the last round here. But I have one major concern in the Read(stream) segment as no examples seem to exist for this sort of methodology. Also, I'm still wondering if I can safely utilize these Delayed Resolutions on all these tags or if I must be selective about their use only in situations where it becomes necessary. And one more little question: how much improved performance would we get if we took up the laborious effort of converting all pair tags to vectors?
Hard to say. In some cases the gain would be quite significant but for some you won't get any speed gain.

Anyhow, if you could look this over and let me know if I have any problems, it'd be appreciated:
Spoiler :
Code:
For an integer by type

Step 1 CvProperties.h:
CvProperties.h seems like a weird place to put that. It does not have anything to do with properties, does it?

Spoiler :
Code:
struct UnitCombatModifier
{
	int iModifier;
	UnitCombat eUnitCombat;
};

H files:

Under: class CvPromotionInfo :	public CvHotkeyInfo

	UnitCombatModifier& getUnitCombatCommunicabilityModifier(int index);
	int getNumUnitCombatCommunicabilityModifiers() const;

Under: class CvPromotionInfo :
	public CvInfoBase
{
protected:
	std::vector<UnitCombatModifier> m_aUnitCombatCommunicabilityModifiers;



Then, in the info cpp:


CvPromotionInfo::~CvPromotionInfo()
{

	for (int i=0; i<(int)m_aUnitCombatCommunicabilityModifierTypes.size(); i++)
	{
		GC.removeDelayedResolution((int*)&m_aUnitCombatCommunicabilityModifierTypes.size[i]));
	}
Please try to at least let the compiler check before posting it here so such simple copy/paste errors are removed.

Spoiler :
Code:
UnitCombatModifier& CvPromotionInfo::getUnitCombatCommunicabilityModifier(int index)
{
	FAssertMsg(index < (int)m_aUnitCombatCommunicabilityModifiers.size(), "Index out of bounds");
	FAssertMsg(index > -1, "Index out of bounds");
	return m_aUnitCombatCommunicabilityModifiers[index];
}

int CvPropertyInfo::getNumUnitCombatCommunicabilityModifiers() const
{
	return (int)m_aUnitCombatCommunicabilityModifiers.size();
}


Under: void CvPromotionInfo::read(FDataStreamBase* stream):

make sure the following is located under this declaration:
	int iNumElements;
	int iElement;
	int iElementInt;

[COLOR="Red"]	stream->Read(&iNumElements);
	m_aUnitCombatCommunicabilityModifierTypes.clear();
	for (int i = 0; i < iNumElements; ++i)
	{
		stream->Read(&iElement);
		stream->Read(&iElementInt);
		m_aUnitCombatCommunicabilityModifierTypes.push_back(std::make_pair((UnitCombatTypes)iElement, iElementInt));
	}[/COLOR] Very concerned this would be entirely incorrect but I can't see how you would've done this since your only examples are in regions that don't require the read(stream).
Correct that it is incorrect.
make_pair only makes pairs, but you have a struct here. Easiest would be to resize the vector after the clear when you know the correct size and then read directly into it.
While it will likely not cause an issue here, mind that vector size is an unsigned int and you should always read into the same variable type that you write from.

Spoiler :
Code:
	stream->Write(m_aUnitCombatCommunicabilityModifierTypes.size());
	for (UnitCombatModifierArray::iterator it = m_aUnitCombatCommunicabilityModifierTypes.begin(); it != m_aUnitCombatCommunicabilityModifierTypes.end(); ++it)
	{
		stream->Write((*it).eUnitCombat);
		stream->Write((*it).iModifier);
	}




	CheckSumC(iSum, m_aUnitCombatCommunicabilityModifierTypes);
That won't work as it does not know how to deal with an arbitrary struct in a vector.

Spoiler :
Code:
Under:
bool CvPromotionInfo::read(CvXMLLoadUtility* pXML):

	if(gDLL->getXMLIFace()->SetToChildByTagName( pXML->GetXML(), "UnitCombatCommunicabilityModifiers"))
	{
		int i = 0;
		int iNum = gDLL->getXMLIFace()->NumOfChildrenByTagName( pXML->GetXML(), "UnitCombatCommunicabilityModifier" );
		m_aUnitCombatCommunicabilityModifiers.resize(iNum); // Important to keep the delayed resolution pointers correct

		if(gDLL->getXMLIFace()->SetToChild( pXML->GetXML() ))
		{

			if (gDLL->getXMLIFace()->LocateFirstSiblingNodeByTagName(pXML->GetXML(), "UnitCombatCommunicabilityModifier"))
			{
				do
				{
					pXML->GetChildXmlValByName(&(m_aUnitCombatCommunicabilityModifiers[i].iModifier), "iModifier");
					pXML->GetChildXmlValByName(szTextVal, "UnitCombatClass");
					GC.addDelayedResolution((int*)&(m_aUnitCombatCommunicabilityModifiers[i].eUnitCombat), szTextVal);
					i++;
				} while(gDLL->getXMLIFace()->LocateNextSiblingNodeByTagName(pXML->GetXML(), "UnitCombatCommunicabilityModifier"));
			}
			gDLL->getXMLIFace()->SetToParent( pXML->GetXML() );
		}
		gDLL->getXMLIFace()->SetToParent( pXML->GetXML() );
	}






Under:
void CvPromotionInfo::copyNonDefaults(CvPromotionInfo* pClassInfo, CvXMLLoadUtility* pXML)

	if (getNumUnitCombatCommunicabilityModifiers() == 0)
	{
		int iNum = pClassInfo->getNumUnitCombatCommunicabilityModifiers();
		m_aUnitCombatCommunicabilityModifiers.resize(iNum);
		for (int i=0; i<iNum; i++)
		{
			[COLOR="Red"]m_aUnitCombatCommunicabilityModifiers[i] = pClassInfo->getUnitCombatCommunicabilityModifier(i);[/COLOR] (a point of concern... didn't we NOT need this in the previous examples?  Why then is it located here in the examples I've found you programmed?)
			GC.copyNonDefaultDelayedResolution((int*)&(m_aUnitCombatCommunicabilityModifiers[i].eUnitCombat), (int*)&(pClassInfo->getUnitCombatCommunicabilityModifiers(i).eUnitCombat));
		}
	}


Also: according to your explanation, shouldn't I have this portion of coding setup like this?:
Code:
	//TB SubCombat Mod begin
	if (getNumSubCombatTypes() == 0)
	{
		m_aiSubCombatTypes.clear();
		for ( int i = 0; i < [COLOR="Red"]pClassInfo->[/COLOR]getNumSubCombatTypes(); i++)
		{
			m_aiSubCombatTypes.push_back([COLOR="Red"]pClassInfo->[/COLOR]getSubCombatType(i));
		}
	}
	//TB SubCombat Mod end
Correct.
 
Please try to at least let the compiler check before posting it here so such simple copy/paste errors are removed.
I can't really compile right now without sorting this out first as a lot of these tags in the process of being changed are linked to existing programming throughout the rest of the files and I'm not really wanting to have to temporarily comment out everything it affects. Normally, though, I'd completely understand your point. The small typos aren't what I'm really concerned with anyhow... I can usually work things that come up in the compiler. My greater concern is making sure I have a working template for each step of adding these tags. I'm completely held up until its sorted out. The first situation looks pretty good but for this method... ugh.

I would probably be quite satisfied with following an example that exists regarding vector pairs... only problem is I don't see anywhere where you've used that method with Delayed Resolution - and that's going to be problematic if I don't sort out how to adapt for that I think.

CvProperties.h seems like a weird place to put that. It does not have anything to do with properties, does it?
Yes, I agree. But it's where the example I followed had placed it, which I would imagine was based on the properties system. There was another example that was somewhat LIKE this one that put a structure of a fairly similar nature in the structs.h file. Should it go there then?

Easiest would be to resize the vector after the clear when you know the correct size and then read directly into it.
hmm... ok. I'll look around and see if I can find an example of reading directly into it.

That won't work as it does not know how to deal with an arbitrary struct in a vector.
Again, the only place you utilized this struct format did not require a write to save either. The closest similar examples used .first and .second but that was under a pair reference. Soooo... I'm not sure what I should do with that. Would the .first and .second references work correctly here still? Would it work with a struct that goes beyond a pair to use .third etc...?


In short, I'm going to try to restructure the entire approach to fall in with the pairing example. I'll then try to sort out how to utilize your Delayed Resolution methods there. Not only is the struct method confusing me, I'm seeing where in the cpp files, you actually have the read and write streams for those methods but done in such a generic form I can't follow the method there either. And I'm not needing anything more complex than the pairing method for the tags I'm using. So I'll repost a new code theory and see what you think. My problem with this is that I'm not sure what the method employed in the delayed resolution tags are actually saying in most cases, so perhaps that's what I should be addressing here.
 
Ok, so bottom line here is that I can't see how to make the following method,
Code:
GC.addDelayedResolution((int*)&(m_aPropertyBuildings[i].eBuilding), szTextVal);
work to fill in for
Code:
m_aUnitCombatCommunicabilityModifiers.push_back(std::make_pair(eUnitCombat, iModifier));
I don't see any way to get the delayed resolution to form a pair in this manner and the struct is just too wildly fractured all over the place for me to resolve into a duplicatable method. Read and Write routines aren't even carried out in the infos files, nor with any direct references to the structures that I'm trying to follow as examples. (Perhaps in some generic fashion, the read and write routines that are in the properties files are taking care of things there but I'm really confused just trying to follow it all so it can be replicated in any useful manner here.)

So I'm finding my only recourse would be to make use of pass 2 and pass 3 in these pair cases where there is a conflict with the load order. Hopefully THAT won't be too bewildering.

I realize I'm probably overcomplicating things but I'm too frustrated to keep trying to understand this. I'm livid with myself for making zero progress this weekend, especially considering I should've been finished with my whole project by the end of this weekend to begin with.

I'm sorry for being so frustrating.
 
I can't really compile right now without sorting this out first as a lot of these tags in the process of being changed are linked to existing programming throughout the rest of the files and I'm not really wanting to have to temporarily comment out everything it affects. Normally, though, I'd completely understand your point. The small typos aren't what I'm really concerned with anyhow... I can usually work things that come up in the compiler.
Usually the compiler gives meaningful feedback even when there are some parts still missing.

My greater concern is making sure I have a working template for each step of adding these tags. I'm completely held up until its sorted out. The first situation looks pretty good but for this method... ugh.

I would probably be quite satisfied with following an example that exists regarding vector pairs... only problem is I don't see anywhere where you've used that method with Delayed Resolution - and that's going to be problematic if I don't sort out how to adapt for that I think.
Well, it is not like you were far off the mark.

Yes, I agree. But it's where the example I followed had placed it, which I would imagine was based on the properties system. There was another example that was somewhat LIKE this one that put a structure of a fairly similar nature in the structs.h file. Should it go there then?
structs.h is a good place for simple structs, yes.


hmm... ok. I'll look around and see if I can find an example of reading directly into it.

Again, the only place you utilized this struct format did not require a write to save either. The closest similar examples used .first and .second but that was under a pair reference. Soooo... I'm not sure what I should do with that. Would the .first and .second references work correctly here still? Would it work with a struct that goes beyond a pair to use .third etc...?
No, pairs are a specific data type, not a struct. It would have been an option, but since you already have a struct with some correct functions, don't bother.

In short, I'm going to try to restructure the entire approach to fall in with the pairing example. I'll then try to sort out how to utilize your Delayed Resolution methods there. Not only is the struct method confusing me, I'm seeing where in the cpp files, you actually have the read and write streams for those methods but done in such a generic form I can't follow the method there either. And I'm not needing anything more complex than the pairing method for the tags I'm using. So I'll repost a new code theory and see what you think. My problem with this is that I'm not sure what the method employed in the delayed resolution tags are actually saying in most cases, so perhaps that's what I should be addressing here.
When the streams are involved, then there is no delayed resolution as the cache writing happens after the resolution.
In the streams you write out your data structure in some serialized form. Usually that means you first write how many entries are there in your array, vector or whatever and then you write the entries one after the other. On reading you do the opposite. You read the number of entries, prepare your array or vector and then read one entry after the other. That is why I said that resize was the easiest way as it actually prepares your vector with the right length and then you don't need to use push_back but instead you can directly access the struct entries you have.

Like this: stream->Read(&(m_aUnitCombatCommunicabilityModifierTypes.iModifier));
 
Ok, I feel a bit better today. I just get frustrated with Sunday nights, knowing that my time to 'get things done' is about to be put off for another work week.

My point is, I have a feeling the compiler would error out in other files before erroring out and showing any problems in the info files here... but I could be wrong. I'll try it later to see. Honestly, I was figuring I'd use it to simply find all the places in the code these tags touch so as to resolve them one by one.

Well, most of my tags would only need the pairing method but when I run up against the need for the delayed response, it would be better to understand the struct method.

If I was that close, well, that's good.

I must admit, I'd have never come up with "stream->Read(&(m_aUnitCombatCommunicabilityModifierType s.iModifier)); " on my own.

I'd had a few problems when trying to figure that out.
1) I'm extremely unsure about what the '&' implies. I've only used it when the compiler asks for it and everything I've found on it in general C++ tutorials are fairly vague about it. I don't think I would've considered its use here.

2)The second thing was that you're suggesting to just write in the .iModifier. So does this mean, this would be one of TWO lines needed in this case? I'll try to code something out based on what I THINK I understand later. During the week I have a lot more patience because I don't expect as much of myself.

Also, this brings up the question, the struct format... I can just put that in the CvStructs.h file without anything backing it up in the .cpp file and it would work right?
 
Ok, I feel a bit better today. I just get frustrated with Sunday nights, knowing that my time to 'get things done' is about to be put off for another work week.

My point is, I have a feeling the compiler would error out in other files before erroring out and showing any problems in the info files here... but I could be wrong. I'll try it later to see. Honestly, I was figuring I'd use it to simply find all the places in the code these tags touch so as to resolve them one by one.

Well, most of my tags would only need the pairing method but when I run up against the need for the delayed response, it would be better to understand the struct method.

If I was that close, well, that's good.

I must admit, I'd have never come up with "stream->Read(&(m_aUnitCombatCommunicabilityModifierType s.iModifier)); " on my own.

I'd had a few problems when trying to figure that out.
1) I'm extremely unsure about what the '&' implies. I've only used it when the compiler asks for it and everything I've found on it in general C++ tutorials are fairly vague about it. I don't think I would've considered its use here.

It is the address operator, giving you a pointer (in other words the memory location) to the variable you specify.

2)The second thing was that you're suggesting to just write in the .iModifier. So does this mean, this would be one of TWO lines needed in this case?
Correct.

I'll try to code something out based on what I THINK I understand later. During the week I have a lot more patience because I don't expect as much of myself.

Also, this brings up the question, the struct format... I can just put that in the CvStructs.h file without anything backing it up in the .cpp file and it would work right?
Correct.
 
Ok. I know its a lot to look over but it should be getting familiar by now ;).

Here's what I have now. Hopefully I'm understanding and applying everything you're saying correctly here. Obviously, the biggest problem areas have been the read and write streams so that's the main thing I need to make sure is correct. But I figured I'd put the whole thing out there one (hopefully last) time to make sure its all in order.

Spoiler :
Code:
For an integer by type (structure with Delayed Resolution)

Step 1 CvStructs.h:

struct UnitCombatModifier
{
	int iModifier;
	UnitCombat eUnitCombat;
};

H files:

Under: class CvPromotionInfo :	public CvHotkeyInfo

	UnitCombatModifier& getUnitCombatCommunicabilityModifier(int index);
	int getNumUnitCombatCommunicabilityModifiers() const;

Under: class CvPromotionInfo :
	public CvInfoBase
{
protected:
	std::vector<UnitCombatModifier> m_aUnitCombatCommunicabilityModifiers;



Then, in the info cpp:


CvPromotionInfo::~CvPromotionInfo()
{

	for (int i=0; i<(int)m_aUnitCombatCommunicabilityModifierTypes.size(); i++)
	{
		GC.removeDelayedResolution((int*)&m_aUnitCombatCommunicabilityModifiers.size[i]));
	}




After CvPromotionInfo::~CvPromotionInfo():

UnitCombatModifier& CvPromotionInfo::getUnitCombatCommunicabilityModifier(int index)
{
	FAssertMsg(index < (int)m_aUnitCombatCommunicabilityModifiers.size(), "Index out of bounds");
	FAssertMsg(index > -1, "Index out of bounds");
	return m_aUnitCombatCommunicabilityModifiers[index];
}

int CvPropertyInfo::getNumUnitCombatCommunicabilityModifiers() const
{
	return (int)m_aUnitCombatCommunicabilityModifiers.size();
}


Under: void CvPromotionInfo::read(FDataStreamBase* stream):

make sure the following is located under this declaration:
	int iNumElements;	
	
	stream->Read(&iNumElements);
	m_aUnitCombatCommunicabilityModifiers.clear();
	m_aUnitCombatCommunicabilityModifiers.resize(iNumElements);
	for (int i = 0; i < iNumElements; ++i)
	{
		stream->Read(&(m_aUnitCombatCommunicabilityModifiers[i].eUnitCombat));
		stream->Read(&(m_aUnitCombatCommunicabilityModifiers[i].iModifier));
	}


make sure the following is located under this declaration:
	int iNumElements;

	iNumElements = m_aUnitCombatCommunicabilityModifiers.size();
	stream->Write(iNumElements);
	for (int i = 0; i < iNumElements; ++i)
	{
		stream->Write(m_aUnitCombatCommunicabilityModifiers[i].eUnitCombat);
		stream->Write(m_aUnitCombatCommunicabilityModifiers[i].iModifier);
	}




	CheckSumC(iSum, m_aUnitCombatCommunicabilityModifiers);




Under:
bool CvPromotionInfo::read(CvXMLLoadUtility* pXML):

	if(gDLL->getXMLIFace()->SetToChildByTagName( pXML->GetXML(), "UnitCombatCommunicabilityModifiers"))
	{
		int i = 0;
		int iNum = gDLL->getXMLIFace()->NumOfChildrenByTagName( pXML->GetXML(), "UnitCombatCommunicabilityModifier" );
		m_aUnitCombatCommunicabilityModifiers.resize(iNum); // Important to keep the delayed resolution pointers correct

		if(gDLL->getXMLIFace()->SetToChild( pXML->GetXML() ))
		{

			if (gDLL->getXMLIFace()->LocateFirstSiblingNodeByTagName(pXML->GetXML(), "UnitCombatCommunicabilityModifier"))
			{
				do
				{
					pXML->GetChildXmlValByName(&(m_aUnitCombatCommunicabilityModifiers[i].iModifier), "iModifier");
					pXML->GetChildXmlValByName(szTextVal, "UnitCombatClass");
					GC.addDelayedResolution((int*)&(m_aUnitCombatCommunicabilityModifiers[i].eUnitCombat), szTextVal);
					i++;
				} while(gDLL->getXMLIFace()->LocateNextSiblingNodeByTagName(pXML->GetXML(), "UnitCombatCommunicabilityModifier"));
			}
			gDLL->getXMLIFace()->SetToParent( pXML->GetXML() );
		}
		gDLL->getXMLIFace()->SetToParent( pXML->GetXML() );
	}






Under:
void CvPromotionInfo::copyNonDefaults(CvPromotionInfo* pClassInfo, CvXMLLoadUtility* pXML)

	if (getNumUnitCombatCommunicabilityModifiers() == 0)
	{
		int iNum = pClassInfo->getNumUnitCombatCommunicabilityModifiers();
		m_aUnitCombatCommunicabilityModifiers.resize(iNum);
		for (int i=0; i<iNum; i++)
		{
			m_aUnitCombatCommunicabilityModifiers[i] = pClassInfo->getUnitCombatCommunicabilityModifier(i);
			GC.copyNonDefaultDelayedResolution((int*)&(m_aUnitCombatCommunicabilityModifiers[i].eUnitCombat), (int*)&(pClassInfo->getUnitCombatCommunicabilityModifiers(i).eUnitCombat));
		}
	}
 
Looks good with the exception of some small syntax issues that the compiler will inform you of and the check sum part, for which you need to use a loop similar to the stream write one and use CheckSum on the single elements of your struct.
 
Ok. Thanks for the advice. I didn't have time tonight to sort that last bit out and repost that portion to see if it checks out but I think I get what you're saying there just fine.

I was a little curious as well about this:
Code:
	if (getNumUnitCombatCommunicabilityModifiers() == 0)
	{
		int iNum = pClassInfo->getNumUnitCombatCommunicabilityModifiers();
		m_aUnitCombatCommunicabilityModifiers.resize(iNum);
		for (int i=0; i<iNum; i++)
		{
			m_aUnitCombatCommunicabilityModifiers[i] = pClassInfo->getUnitCombatCommunicabilityModifier(i);
			GC.copyNonDefaultDelayedResolution((int*)&(m_aUnitCombatCommunicabilityModifiers[i].eUnitCombat), (int*)&(pClassInfo->getUnitCombatCommunicabilityModifiers(i).eUnitCombat));
		}
	}
It doesn't utilize both .iModifier and .eUnitCombat. This is in accordance with the examples you left in your PropertyPromotion section and I was wondering how we get around the need to establish data for both tags?
 
It doesn't utilize both .iModifier and .eUnitCombat. This is in accordance with the examples you left in your PropertyPromotion section and I was wondering how we get around the need to establish data for both tags?
You have to copy the data for both tags, so this line:
m_aUnitCombatCommunicabilityModifiers = pClassInfo->getUnitCombatCommunicabilityModifier(i);

needs to be changed so it refers to iModifier.
 
So they'd be like this?

Code:
For Checksum:

	int iNumElements;

	iNumElements = m_aUnitCombatCommunicabilityModifiers.size();
	for (int i = 0; i < iNumElements; ++i)
	{
		CheckSumC(iSum, m_aUnitCombatCommunicabilityModifiers[i].eUnitCombat);
		CheckSumC(iSum, m_aUnitCombatCommunicabilityModifiers[i].iModifier);
	}
and
Code:
	if (getNumUnitCombatCommunicabilityModifiers() == 0)
	{
		int iNum = pClassInfo->getNumUnitCombatCommunicabilityModifiers();
		m_aUnitCombatCommunicabilityModifiers.resize(iNum);
		for (int i=0; i<iNum; i++)
		{
			GC.copyNonDefaultDelayedResolution((int*)&(m_aUnitCombatCommunicabilityModifiers[i].iModifier), (int*)&(pClassInfo->getUnitCombatCommunicabilityModifiers(i).iModifier));
			GC.copyNonDefaultDelayedResolution((int*)&(m_aUnitCombatCommunicabilityModifiers[i].eUnitCombat), (int*)&(pClassInfo->getUnitCombatCommunicabilityModifiers(i).eUnitCombat));
		}
	}
 
So they'd be like this?

Code:
For Checksum:

	int iNumElements;

	iNumElements = m_aUnitCombatCommunicabilityModifiers.size();
	for (int i = 0; i < iNumElements; ++i)
	{
		CheckSumC(iSum, m_aUnitCombatCommunicabilityModifiers[i].eUnitCombat);
		CheckSumC(iSum, m_aUnitCombatCommunicabilityModifiers[i].iModifier);
	}
CheckSum is the right function to call for single values, not CheckSumC (the C means Container like vector which works without the for loop but only if there is a CheckSum function defined for its elements so it works for a vector of int but not a vector of struct).
and
Code:
	if (getNumUnitCombatCommunicabilityModifiers() == 0)
	{
		int iNum = pClassInfo->getNumUnitCombatCommunicabilityModifiers();
		m_aUnitCombatCommunicabilityModifiers.resize(iNum);
		for (int i=0; i<iNum; i++)
		{
			GC.copyNonDefaultDelayedResolution((int*)&(m_aUnitCombatCommunicabilityModifiers[i].iModifier), (int*)&(pClassInfo->getUnitCombatCommunicabilityModifiers(i).iModifier));
			GC.copyNonDefaultDelayedResolution((int*)&(m_aUnitCombatCommunicabilityModifiers[i].eUnitCombat), (int*)&(pClassInfo->getUnitCombatCommunicabilityModifiers(i).eUnitCombat));
		}
	}
iModifier is a simple int, not something you use delayed resolution for. The eUnitCombat part looks right.

For iModifier the line you had earlier was closer to the mark:
m_aUnitCombatCommunicabilityModifiers = pClassInfo->getUnitCombatCommunicabilityModifier(i);
It just does not refer to iModifier as it should. So it needs to look somewhat like this:
m_aUnitCombatCommunicabilityModifiers.iModifier = pClassInfo->m_aUnitCombatCommunicabilityModifiers.iModifier;
 
Alright. I had wondered about both of those points and suspected you might correct me on those but I wasn't sure if I needed it as you just said or not.

So I have one more last question. I think I can figure out how to convert to utilizing the 'boolean' style vectors in the coding fine. But I'm a little fuzzy on how I would access the information correctly on the structure method. Would I cycle through a 'for loop' using say, NumUnitCombatCommunicabilityModifiers(), looking for getUnitCombatCommunicabilityModifier(iI).eUnitCombat? Then utilize getUnitCombatCommunicabilityModifier(iI).iModifier as the value itself? Do I need to include () at the end of these or just leave that blank? Or am I completely off the mark?
 
Alright. I had wondered about both of those points and suspected you might correct me on those but I wasn't sure if I needed it as you just said or not.

So I have one more last question. I think I can figure out how to convert to utilizing the 'boolean' style vectors in the coding fine. But I'm a little fuzzy on how I would access the information correctly on the structure method. Would I cycle through a 'for loop' using say, NumUnitCombatCommunicabilityModifiers(), looking for getUnitCombatCommunicabilityModifier(iI).eUnitCombat? Then utilize getUnitCombatCommunicabilityModifier(iI).iModifier as the value itself? Do I need to include () at the end of these or just leave that blank? Or am I completely off the mark?
Sounds right. () is only needed when you call a function or method and eUnitCombat and iModifier are neither.
 
Back
Top Bottom