Personality Archtypes

AIAndy said:
As far as I can see what you are doing there is adding a new XML file that is nearly entirely a copy of the old. I think it would be better if you add inheritance capability to info classes. That means you have your archetypes as normal leaderheads defined but with some new tag that makes them inactive or declares them abstract or something. Then you add a new tag (best on a similar level as the Replacement code stuff) that allows you to inherit information from one or more base classes. That is a quite generic piece of code and should also work on other info classes as it can use the copyNonDefault methods to copy in the information from the base classes.
One thing that would be needed is for every info class that should support that the copyNonDefault needs to be truely copying, not moving information as it sometimes does now.
A tag that makes info classes inactive is useful for the replacement stuff as well.
I get what you mean but I do have an objection that is not entirely based on not being sure how to establish all that.

I'd really rather make the references much easier to catalog for the modder. If we did it the way you're suggesting then we must recall the leaders that represent particular archetypes. The way I've suggested enables us to label the archetypes very clearly and meaninfully whereas there would be some vagueness in referring to a leader to be the representative of a given archetype structure, wouldn't there? Additionally, I'd like to be able to express the archetypes the leader has in a hoverhelp pop somewhere (down the road this will be more important than it is now.) And I don't want it to basically state: this leader is much the same in this regard as Alexander is. Instead I'd like Alexander and that leader to both be saying, I'm like this common feature.

Does that make any sense?

Now, considering things a bit more, this would mean that if we went about things in the way you're suggesting, I would need to give tags for the leaders that enable them to provide a label of what archetype type they represent if they are being referenced as an archetype model, right?

The plan currently involves having a number of established archetype files by categories of archetypes, basically each being a 'leader info building block' that can be more quickly and generically mixed and matched on new leaders (and will make things much easier for the random leader generation mechanism I'll need in the future.) So a given leader would only represent a portion of his tags as implemented under one particular archetype category, which means each category would have to have a new tag for the leader to define a generic label for that category and so on.

Another concern I have in that idea is that I foresee a VERY huge list of leaders. This would mean that every time a leader value is referenced that then basically states override with an archetype would enforce a huge amount of cycling. Keeping the archetype files to a more simplified list would reduce this. However, it sounds like this would only be a bit of a slowdown in the loading process the way you suggest it as the replacement would happen once on load. But with the list of leaders we could generate, plus an intended random leader mechanism to play off this, the impact of cycling through such a LONG list would still have the occasional unpleasant impact wouldn't it?
 
I get what you mean but I do have an objection that is not entirely based on not being sure how to establish all that.

I'd really rather make the references much easier to catalog for the modder. If we did it the way you're suggesting then we must recall the leaders that represent particular archetypes. The way I've suggested enables us to label the archetypes very clearly and meaninfully whereas there would be some vagueness in referring to a leader to be the representative of a given archetype structure, wouldn't there? Additionally, I'd like to be able to express the archetypes the leader has in a hoverhelp pop somewhere (down the road this will be more important than it is now.) And I don't want it to basically state: this leader is much the same in this regard as Alexander is. Instead I'd like Alexander and that leader to both be saying, I'm like this common feature.

Does that make any sense?
You are not forced to make the "leader" you inherit from a real leader. It can have as little actually filled out values as you want. You might as well use the name of that "leader" to name the archetype.

Now, considering things a bit more, this would mean that if we went about things in the way you're suggesting, I would need to give tags for the leaders that enable them to provide a label of what archetype type they represent if they are being referenced as an archetype model, right?
Yes, I guess that would be a useful tag to add..

The plan currently involves having a number of established archetype files by categories of archetypes, basically each being a 'leader info building block' that can be more quickly and generically mixed and matched on new leaders (and will make things much easier for the random leader generation mechanism I'll need in the future.) So a given leader would only represent a portion of his tags as implemented under one particular archetype category, which means each category would have to have a new tag for the leader to define a generic label for that category and so on.
I don't get what you talk about here. The copyNonDefault behavior will easily allow to combine such patterns without any additional tags. What you set to some non default value on the leader won't be copied from the archetypes and what the first archetype sets will not be copied from the second (in the inheritance list) and so on.

Another concern I have in that idea is that I foresee a VERY huge list of leaders. This would mean that every time a leader value is referenced that then basically states override with an archetype would enforce a huge amount of cycling. Keeping the archetype files to a more simplified list would reduce this. However, it sounds like this would only be a bit of a slowdown in the loading process the way you suggest it as the replacement would happen once on load. But with the list of leaders we could generate, plus an intended random leader mechanism to play off this, the impact of cycling through such a LONG list would still have the occasional unpleasant impact wouldn't it?
I don't get what you mean with cycling.
 
I said:
The plan currently involves having a number of established archetype files by categories of archetypes, basically each being a 'leader info building block' that can be more quickly and generically mixed and matched on new leaders (and will make things much easier for the random leader generation mechanism I'll need in the future.) So a given leader would only represent a portion of his tags as implemented under one particular archetype category, which means each category would have to have a new tag for the leader to define a generic label for that category and so on.
You said:
I don't get what you talk about here. The copyNonDefault behavior will easily allow to combine such patterns without any additional tags. What you set to some non default value on the leader won't be copied from the archetypes and what the first archetype sets will not be copied from the second (in the inheritance list) and so on.
hmm... My current understanding of the copyNonDefault behavior is struggling to keep up with you here. So far as I understand that, the copyNonDefault segment is purely for the modular loader to enable modules to replace or override specific definitions given in a second xml entry for that info type.

Let me back up and explain what the plan is at the moment. A section of leader tags would be defined under one archetype category file. Let's say that category is Warfare, just for an example. Any tags that involve the leader's decisionmaking on warfare issues would be setup in that archetype file. Then there's a tag in the leader infos for <ArchetypeWarfare> which references the info entry in the Warfare Archetypes file and brings those tags definitions assigned there in to replace the leader's if the leader's is undefined, doing so at the get call.

Then that same leader could have some of its tags calling to a reference from its <ArchetypeTrade> for example. Thus one leader mixes and matches a number of archetype types and each category is defined differently.

What I'm saying here is that what I understand of your method would suggest that we'd be limited to only one archetype category and reference that would either replace (at load) the leader's null values that have definition in the archetype file OR would not replace them if the leader had his own assigned values. How would we enable differing categories of archetypes?

I do like the answer you gave about the name of the leader, but we'd have to keep those entries out of the pedia which I'm sure you'd be able to ensure in the same way you keep the option edit entries out of the pedia (unless expressed as a result of currently being actively replacing) now.

I know this stuff is confusing the way I express it... keep in mind I have equal confusion on my end. This is much because I'm learning more from analyzing code than I am from a book or reference explaining it (those lose me more often than not too in the same way.) In short, I come up with my own creative ways to explain what I just understand otherwise and trying to understand what you're talking about is just as tough for me.

I said:
Another concern I have in that idea is that I foresee a VERY huge list of leaders. This would mean that every time a leader value is referenced that then basically states override with an archetype would enforce a huge amount of cycling. Keeping the archetype files to a more simplified list would reduce this. However, it sounds like this would only be a bit of a slowdown in the loading process the way you suggest it as the replacement would happen once on load. But with the list of leaders we could generate, plus an intended random leader mechanism to play off this, the impact of cycling through such a LONG list would still have the occasional unpleasant impact wouldn't it?
You said:
I don't get what you mean with cycling.
for iI = 0; iI < etc... perhaps I should be calling it Looping.
Looping through the list of leaders, as long as it will become, to reference replacement information on its tags would cost a horrendous amount of processing time when I move to using the Archetypes to define randomly generated leaders in the game. I'm not sure if it's necessary to loop through the leader definitions to find the right archetype to copy from at load time the way you work out your method but the random leaders that have only in-game temporary definition entirely by randomized results on the various archetype categories would have to loop through the leader list to find the right archetypes. And if the archetypes are simply defined as additional leaders, that list could become prohibitively large for such looping to take place with any frequency. Thinking far enough ahead to the day when I'm able to randomly define and generate leaders that do not rely on set predefinitions is a big part of what this project is for. Keeping the archetype class lists looped through to a smaller list of the archetypes alone (and not having to loop through ALL leaders) would be beneficial to processing speed wouldn't it?


Now on the flip side, the benefit you're talking about is that your method would take up a lot less ram by not having defined copies of all those tags separately right? Or is there something more to this that I'm not understanding yet?
 
hmm... My current understanding of the copyNonDefault behavior is struggling to keep up with you here. So far as I understand that, the copyNonDefault segment is purely for the modular loader to enable modules to replace or override specific definitions given in a second xml entry for that info type.

Let me back up and explain what the plan is at the moment. A section of leader tags would be defined under one archetype category file. Let's say that category is Warfare, just for an example. Any tags that involve the leader's decisionmaking on warfare issues would be setup in that archetype file. Then there's a tag in the leader infos for <ArchetypeWarfare> which references the info entry in the Warfare Archetypes file and brings those tags definitions assigned there in to replace the leader's if the leader's is undefined, doing so at the get call.

Then that same leader could have some of its tags calling to a reference from its <ArchetypeTrade> for example. Thus one leader mixes and matches a number of archetype types and each category is defined differently.

What I'm saying here is that what I understand of your method would suggest that we'd be limited to only one archetype category and reference that would either replace (at load) the leader's null values that have definition in the archetype file OR would not replace them if the leader had his own assigned values. How would we enable differing categories of archetypes?
In the XML for the archetypes you will only define the values fitting to the specific archetype. So when you copy those in wherever there are no values in the actual leader defined, the values that are neither in the archetype nor in the leader will remain default/NULL values. That means you can copy in the next archetype now and so on.
It won't enforce that you keep to your archetype categories but as long as you do, you will mix and match as well as with a specialized system.

So lets assume you name the type IDs of your archetypes starting with ARCHETYPE_TRADE_ and so on, then at the start of your leader XML you would have:
Code:
<Inherits>
  <Inherit>ARCHETYPE_WARFARE_AGGRESSIVE</Inherit>
  <Inherit>ARCHETYPE_TRADE_MASTER</Inherit>
  <Inherit>ARCHETYPE_WHATEVER_YOUCANCOMEUPWITH</Inherit>
</Inherits>

I do like the answer you gave about the name of the leader, but we'd have to keep those entries out of the pedia which I'm sure you'd be able to ensure in the same way you keep the option edit entries out of the pedia (unless expressed as a result of currently being actively replacing) now.

I know this stuff is confusing the way I express it... keep in mind I have equal confusion on my end. This is much because I'm learning more from analyzing code than I am from a book or reference explaining it (those lose me more often than not too in the same way.) In short, I come up with my own creative ways to explain what I just understand otherwise and trying to understand what you're talking about is just as tough for me.

for iI = 0; iI < etc... perhaps I should be calling it Looping.
Looping through the list of leaders, as long as it will become, to reference replacement information on its tags would cost a horrendous amount of processing time when I move to using the Archetypes to define randomly generated leaders in the game. I'm not sure if it's necessary to loop through the leader definitions to find the right archetype to copy from at load time the way you work out your method but the random leaders that have only in-game temporary definition entirely by randomized results on the various archetype categories would have to loop through the leader list to find the right archetypes. And if the archetypes are simply defined as additional leaders, that list could become prohibitively large for such looping to take place with any frequency. Thinking far enough ahead to the day when I'm able to randomly define and generate leaders that do not rely on set predefinitions is a big part of what this project is for. Keeping the archetype class lists looped through to a smaller list of the archetypes alone (and not having to loop through ALL leaders) would be beneficial to processing speed wouldn't it?
You can always filter out your actual archetypes during load and put them in some extra arrays for fast access when you want to randomly generate a new leader.

Now on the flip side, the benefit you're talking about is that your method would take up a lot less ram by not having defined copies of all those tags separately right? Or is there something more to this that I'm not understanding yet?
The big advantage is not that you use less RAM or anything. It is that you have considerably less effort implementing it and at the same time get a mechanic that can be used for other info classes.
 
In the XML for the archetypes you will only define the values fitting to the specific archetype. So when you copy those in wherever there are no values in the actual leader defined, the values that are neither in the archetype nor in the leader will remain default/NULL values. That means you can copy in the next archetype now and so on.
It won't enforce that you keep to your archetype categories but as long as you do, you will mix and match as well as with a specialized system.

So lets assume you name the type IDs of your archetypes starting with ARCHETYPE_TRADE_ and so on, then at the start of your leader XML you would have:
Code:
<Inherits>
  <Inherit>ARCHETYPE_WARFARE_AGGRESSIVE</Inherit>
  <Inherit>ARCHETYPE_TRADE_MASTER</Inherit>
  <Inherit>ARCHETYPE_WHATEVER_YOUCANCOMEUPWITH</Inherit>
</Inherits>


You can always filter out your actual archetypes during load and put them in some extra arrays for fast access when you want to randomly generate a new leader.


The big advantage is not that you use less RAM or anything. It is that you have considerably less effort implementing it and at the same time get a mechanic that can be used for other info classes.

Ok, those are some good answers but I may be a little confused as to the method you want to implement on this to some extent. I was thinking you were saying we could avoid establishing an archetype class entirely but in the coding example you gave there you are basically insinuating we'd still have an archetype class... it'd just be that we wouldn't have to copy over all the leaderhead class tags to that new archetype class. Instead, we have one tag that enables us to generate a list of tags that this archetype seeks to redefine based on some means to reference the leaderhead tags in the xml. I could also, therefore, include a reference to the type of archetype category this particular entry exists in (which would then mean we need an archetype categories class for generating that list).

The archetype entry also defines the leader entry that the rest of the tag data is then derived FROM and the leaders accessing it use a new tag along the lines of the method you just gave a code example of and that then loads the tag data from that definition... this is beginning to make more sense.

Is this sort of thing possible under this method?:
We have some tags in the leaders that give quite a list of results and ensuing definitions (arrays/vectors, however they're done I'm not sure yet) such as the Diplomacy Memory tag. RtS wanted to have some of those memories come from definitions in one category of archetypes and have some other of those memory definitions come from another category. The way I had figured on doing this would have allowed this but would not have allowed the particular memories to be 'enforced' into their proper categories.

In short, what would be necessary is for the copyNonDefaults to be able to add an extra entry in an array (I believe they are arrays) if THAT entry does not have any definition yet. Is this problematic somehow?

Now then... at this point I'm completely over my own head as to how this would all be implemented. I'm getting the concept of the method I think (though you can correct me on that if anything I've said above is totally off track.) I don't want to have to ask you to do this for me because I really want to learn how this kind of thing could be done and I don't think I can analyze my way through it.

So would you be willing to patiently instruct me one step at a time in its implementation? See... I don't usually ask this kind of thing because I feel its a bit of an imposition.
 
Ok, those are some good answers but I may be a little confused as to the method you want to implement on this to some extent. I was thinking you were saying we could avoid establishing an archetype class entirely but in the coding example you gave there you are basically insinuating we'd still have an archetype class... it'd just be that we wouldn't have to copy over all the leaderhead class tags to that new archetype class. Instead, we have one tag that enables us to generate a list of tags that this archetype seeks to redefine based on some means to reference the leaderhead tags in the xml. I could also, therefore, include a reference to the type of archetype category this particular entry exists in (which would then mean we need an archetype categories class for generating that list).
No archetype class. What I named ARCHETYPE_WHATEVER there are just instances of the leaderhead class with a different type name to state the intention (there is no enforcement that leaderheads start with LEADER_ ).

An example: Lets assume that leaderheads would only have 4 int tags, A, B, C and D. This time I will just use LEADER_ to avoid confusion but you might as well name the infos ARCHETYPE_.

Code:
<LeaderHeadInfo>
  <Type>LEADER_X</Type>
  <A>34</A>
  <B>20</B>
</LeaderHeadInfo>

<LeaderHeadInfo>
  <Type>LEADER_Y</Type>
  <A>0</A>
  <B>0</B>
  <D>-50</D>
</LeaderHeadInfo>

<LeaderHeadInfo>
  <Type>LEADER_Z</Type>
  <A>10</A>
  <B>45</B>
  <C>33</C>
  <D>17</D>
</LeaderHeadInfo>

<LeaderHeadInfo>
  <Type>LEADER_W</Type>
  <Inherits>
    <Inherit>LEADER_X</Inherit>
    <Inherit>LEADER_Y</Inherit>
    <Inherit>LEADER_Z</Inherit>
  </Inherits>
  <Active>1</Active>
  <A>0</A>
  <B>45</B>
</LeaderHeadInfo>
First leaders X, Y and Z are read but they all are inactive because they don't have the Active tag set.
Leader W is then read and it specifies an inheritance list. So after it is read, a copyNonDefault with leader X is executed. It copies in values from X wherever W is at default value, which in this case means that A is copied in. Now W has both A and B at non default values. Next Y is copied in which adds D. Z is the last to be inherited from, but from the tags Z defines, only C will be copied as that is at default value still in W.
 
I was thinking through this today at work and realized I'd backpedalled in my understanding of the method here. Reminding myself of the earliest portions of our conversation on this, I sorted out what you meant would amount to the above. Oops.

Ok, so how does the copyNonDefault work on an array, like the memories? If one Memory type is set does that make the whole Memory types tag be considered to have a set value? Or does it go by the memory type itself - for each memory type, if it finds a definition for a type undefined it fills in the value its reading from the replacement?

So, to put an example to make this question easier to understand. We have tags like MemoryDecays:
Code:
			<MemoryDecays>
				<MemoryDecay>
					<MemoryType>MEMORY_GIVE_HELP</MemoryType>
					<iMemoryRand>200</iMemoryRand>
				</MemoryDecay>
				<MemoryDecay>
					<MemoryType>MEMORY_REFUSED_HELP</MemoryType>
					<iMemoryRand>100</iMemoryRand>
				</MemoryDecay>
And such a list goes on and on with more MemoryDecay Types being listed.

What I'm asking is if Leader_A and Leader B are set as Inherits by Leader_W to fill in values here in the MemoryDecays tag and Leader_A has:
Code:
			<MemoryDecays>
				<MemoryDecay>
					<MemoryType>MEMORY_GIVE_HELP</MemoryType>
					<iMemoryRand>200</iMemoryRand>
				</MemoryDecay>
			</MemoryDecays>
and nothing more (or even some more but not the following, while Leader_B has:
Code:
			<MemoryDecays>
				<MemoryDecay>
					<MemoryType>MEMORY_REFUSED_HELP</MemoryType>
					<iMemoryRand>100</iMemoryRand>
				</MemoryDecay>
			</MemoryDecays>
which is not an entry listed under MemoryDecays in Leader_A's profile, will the copyNonDefaults method set Leader_W with only the first entry from Leader_A since the MemoryDecays tag has some value in it, or both the entries from Leader_A and Leader_B since each specific MemoryType in MemoryDecay differs?
 
In the case of leader heads the array will be combined so you get both memory entries (not all arrays of other info classes behave that way).

Well, actually they will currently not be as Afforess has added code that sets all of the memory and contact entries to non default values at the end of the XML reading of a single leader info. But that is something that breaks modularity so it should be changed anyway.
 
Ok... sooo... that change I'd be quite happy to leave to you if you'd like to take care of that. But what would be my first step in getting moving on this (it'll take a lot of time to complete this project with me asking for instruction on each step but that's fine... I can do this in an alternative project file so that I'm free to work on other things as this progresses.)
 
Ok... sooo... that change I'd be quite happy to leave to you if you'd like to take care of that. But what would be my first step in getting moving on this (it'll take a lot of time to complete this project with me asking for instruction on each step but that's fine... I can do this in an alternative project file so that I'm free to work on other things as this progresses.)
The first step is reading in the new Inherits tag in CvInfoBase::read(CvXMLLoadUtility* pXML).
Since it is not possible to add variables to CvInfoBase (the exe seems to rely on it on a deeper level than it relies on other classes in the DLL so adding variables there crashes the game) the common way is to read into GC variables. So add a new vector there in which you read the Inherits tag.

The next step is then to go into CvXMLLoadUtility::SetGlobalClassInfo and handle the copyNonDefaults if an Inherits tag was set in the pClassInfo->read stuff. The new code should probably be added near where the replacements are handled as well.
 
Ok, so far I have:
in CvGlobals.h
Code:
	bool m_bAnyInherit;
	bool m_bTypeInherit;
	std::vector<CvString> m_paszInheritTypes;
and
Code:
	void resetInherits();
	bool isAnyInherit();
	void setAnyInherit(bool bAnyInherit);
	bool& getTypeInherit();
	void setTypeInherit(bool newValue);
	const int getNumInheritTypes() const;
	void setInheritTypes(const char* szInheritTypes);
	const CvString getInheritTypes(int i) const;

and in CvGlobals.cpp
Code:
void cvInternalGlobals::resetInherits()
{
	m_bAnyInherit = false;
	m_bTypeInherit = false;
	m_paszInheritTypes.clear();
}

bool cvInternalGlobals::isAnyInherit()
{
	return m_bAnyInherit;
}

void cvInternalGlobals::setAnyInherit(bool bAnyInherit)
{
	m_bAnyInherit = bAnyInherit;
}

bool& cvInternalGlobals::getTypeInherit()
{
	return m_bTypeInherit;
}

void cvInternalGlobals::setTypeInherit(bool newValue)
{
	m_bTypeInherit = newValue;
}

const int cvInternalGlobals::getNumInheritTypes() const
{
	return m_paszInheritTypes.size();
}

void cvInternalGlobals::setInheritTypes(const char* szInheritTypes)
{
	m_paszInheritTypes.push_back(szInheritTypes);
}

const CvString cvInternalGlobals::getInheritTypes(int i) const
{
	FAssertMsg(i < GC.getNumInheritTypes(), "Index out of bounds");
	FAssertMsg(i > -1, "Index out of bounds");
	return m_paszInheritTypes.at(i);
}

and in CvInfos.cpp
Code:
	if (!GC.isAnyInherit() )
	{		
		GC.resetInherits(); //make sure this always starts empty!

		if (gDLL->getXMLIFace()->SetToChildByTagName(pXML->GetXML(),"Inherits"))
		{
			GC.setAnyInherit(true);

			int iNumChildren = gDLL->getXMLIFace()->GetNumChildren(pXML->GetXML());

			if (pXML->GetChildXmlVal(szTextVal))
			{
				GC.setInheritTypes(szTextVal);
			
				for ( int iI = 1; iI < iNumChildren; iI++ )
				{
					if (pXML->GetNextXmlVal(szTextVal))
					{
						GC.setInheritTypes(szTextVal);
					}
					else
					{
						break;
					}
				}
				gDLL->getXMLIFace()->SetToParent(pXML->GetXML());
			}
			gDLL->getXMLIFace()->SetToParent(pXML->GetXML());
		}
	}

I noticed a few of these functions in Cv.Globals aren't being put to use yet but I thought they may have had something to do with establishing what type of info class the inherit refers to?

So am I on track here or completely off base?
 
Looks good, except that I am not sure what the outer "if (!GC.isAnyInherit() )" is supposed to do. And I think the GetChildXmlVal does not set the parser to that child so you might need to set it to the first child at that point and then use GetXmlVal to get the first inherit.

I would also suggest to do a resolution of the info type right away instead of storing the strings (unless you want to support inheritance that does not follow the loading order meaning base info loaded before the info that inherits).
 
Looks good, except that I am not sure what the outer "if (!GC.isAnyInherit() )" is supposed to do. And I think the GetChildXmlVal does not set the parser to that child so you might need to set it to the first child at that point and then use GetXmlVal to get the first inherit.

I would also suggest to do a resolution of the info type right away instead of storing the strings (unless you want to support inheritance that does not follow the loading order meaning base info loaded before the info that inherits).

From the dependancy examples, it looked like the !GC.isAnyInherit() was intended to only bother to load if there was nothing yet loaded. For what reason, I'm no more clear on that than you. If that can be safely removed, I'll do so, but then it makes me wonder what GC.isAnyInherit would then be intended for thereafter? Perhaps a display issue no?

And I think the GetChildXmlVal does not set the parser to that child so you might need to set it to the first child at that point and then use GetXmlVal to get the first inherit.
Could you show me with a coding example or point me in the direction of one that shows the difference you're suggesting? I'm not quite following you here.

I would also suggest to do a resolution of the info type right away instead of storing the strings (unless you want to support inheritance that does not follow the loading order meaning base info loaded before the info that inherits).
Again, I'm a little lost on your meaning here. Are you saying that rather than storing the inheritance tag in the globals you simply proceed immediately into replacing? Perhaps the structure should support inheritance that does not follow the loading order... I had not figured on having to add the Archetype entries into the core before all other leaders only. (Or am I missing your point?)
 
From the dependancy examples, it looked like the !GC.isAnyInherit() was intended to only bother to load if there was nothing yet loaded. For what reason, I'm no more clear on that than you. If that can be safely removed, I'll do so, but then it makes me wonder what GC.isAnyInherit would then be intended for thereafter? Perhaps a display issue no?
It should not be needed (for the dependency stuff I think it was intended as an easy check if there is any dependency or not).

Could you show me with a coding example or point me in the direction of one that shows the difference you're suggesting? I'm not quite following you here.
I looked into the code of the function and it seems like GetChildXmlVal actually leaves the parser at the child so the reading code should work (in other words, ignore that comment).

Again, I'm a little lost on your meaning here. Are you saying that rather than storing the inheritance tag in the globals you simply proceed immediately into replacing? Perhaps the structure should support inheritance that does not follow the loading order... I had not figured on having to add the Archetype entries into the core before all other leaders only. (Or am I missing your point?)
Not replacing right away but you could use getInfoTypeForString and store the result instead of storing the strings.
Leader infos don't use two pass loading at the moment so if you want to support out of order inheritance, you would need to store the inheritance info in a map from the type ID to a vector of inherited types (as strings) instead of the simple global vector you have now.
Alternatively switch on two pass loading but that always means a slowdown in loading as all XML files of that type are read twice. In that case you could then just do the inheritance after the second loading pass instead of the first.
 
Not replacing right away but you could use getInfoTypeForString and store the result instead of storing the strings.

Ok, it sounds like you'd like me to change the reading to:
Code:
	GC.resetInherits(); //make sure this always starts empty!

	if (gDLL->getXMLIFace()->SetToChildByTagName(pXML->GetXML(),"Inherits"))
	{
		GC.setAnyInherit(true);

		int iNumChildren = gDLL->getXMLIFace()->GetNumChildren(pXML->GetXML());

		if (pXML->GetChildXmlVal(GC.getInfoTypeForString(szTextVal)))
		{
			GC.setInheritTypes(GC.getInfoTypeForString(szTextVal));
		
			for ( int iI = 1; iI < iNumChildren; iI++ )
			{
				if (pXML->GetNextXmlVal(GC.getInfoTypeForString(szTextVal)))
				{
					GC.setInheritTypes(GC.getInfoTypeForString(szTextVal));
				}
				else
				{
					break;
				}
			}
			gDLL->getXMLIFace()->SetToParent(pXML->GetXML());
		}
		gDLL->getXMLIFace()->SetToParent(pXML->GetXML());
	}
But then do I need to change anything further here? The .at looks a bit suspicious that it may not be meant to handle a non-string value. Not sure what that's for at all.
Code:
void cvInternalGlobals::resetInherits()
{
	m_bAnyInherit = false;
	m_bTypeInherit = false;
	m_paszInheritTypes.clear();
}

bool cvInternalGlobals::isAnyInherit()
{
	return m_bAnyInherit;
}

void cvInternalGlobals::setAnyInherit(bool bAnyInherit)
{
	m_bAnyInherit = bAnyInherit;
}

bool& cvInternalGlobals::getTypeInherit()
{
	return m_bTypeInherit;
}

void cvInternalGlobals::setTypeInherit(bool newValue)
{
	m_bTypeInherit = newValue;
}

const int cvInternalGlobals::getNumInheritTypes() const
{
	return m_paszInheritTypes.size();
}

void cvInternalGlobals::setInheritTypes(const int* szInheritTypes)
{
	m_paszInheritTypes.push_back(szInheritTypes);
}

const CvString cvInternalGlobals::getInheritTypes(int i) const
{
	FAssertMsg(i < GC.getNumInheritTypes(), "Index out of bounds");
	FAssertMsg(i > -1, "Index out of bounds");
	return m_paszInheritTypes.at(i);
}

So if all we need to remember is to make sure the Archetype entries are placed at the beginning of the core Leaderheads infos, that's perfectly fine by me. What if those needed replacements for particular game options though? I could see how that may eventually become a necessity to vary leader definitions on some of the trait option variants.
 
But then do I need to change anything further here? The .at looks a bit suspicious that it may not be meant to handle a non-string value. Not sure what that's for at all.
vec.at(i) is equivalent to vec. But yes, you need to change the type of that vector to use int instead of strings.

So if all we need to remember is to make sure the Archetype entries are placed at the beginning of the core Leaderheads infos, that's perfectly fine by me. What if those needed replacements for particular game options though? I could see how that may eventually become a necessity to vary leader definitions on some of the trait option variants.
The way this is planned at the moment you using the replacement system on archetypes would have no effect as that would be resolved later than the inheritance itself.
If you want that to work, the whole resolution of inheritance would need to be moved to where the actual replacement happens. That also includes storing the entire inheritance tree, applying a topological sort on it (best using the Boost Graph Library) and storing a pristine copy of each info before you apply inheritance.
So while this is possible (and probably not TOO much effort), I fear I would need to do that myself (as I can't explain that well enough for you to implement that efficiently).
 
vec.at(i) is equivalent to vec. But yes, you need to change the type of that vector to use int instead of strings.

Ah... yes. I felt I HAD to be overlooking something and that would certainly be a big part of what I should not have failed to consider there.


The way this is planned at the moment you using the replacement system on archetypes would have no effect as that would be resolved later than the inheritance itself.
If you want that to work, the whole resolution of inheritance would need to be moved to where the actual replacement happens. That also includes storing the entire inheritance tree, applying a topological sort on it (best using the Boost Graph Library) and storing a pristine copy of each info before you apply inheritance.
So while this is possible (and probably not TOO much effort), I fear I would need to do that myself (as I can't explain that well enough for you to implement that efficiently).

Unfortunately, I can really see the need for that to make the Developing Leader mechanism work well for the differing traits sets. It COULD be tolerable to work around that limitation, and my alternative plan would've allowed this as the archetype merely fills in for the return whenever the data is called for rather than attempting to fill in to the core leader data on load. If you feel its worth doing it the way you mentioned, than by all means have at 'er an it'd be appreciated. However, already this little exercise has been extremely illuminating.

I suppose if you're going to move on that, I can step back from this project until you've got that part sorted out huh? How impacting would what you suggest be on the load times?
 
I suppose if you're going to move on that, I can step back from this project until you've got that part sorted out huh? How impacting would what you suggest be on the load times?
I guess so. And I don't think there will be a significant influence on loading times (and how often do you load anyway).
 
Back
Top Bottom