davidlallen
Deity
Remind me again why you need the bool? Suppose you had just the tech integer. Could you test if that is -1, instead of having a second array?
Yeah, I searched all through the XML, and couldn't find any examples. Would it be possible to code the parser to read 3 children, or is this in the Exe / is too difficult to do? I can of curse set up two tags, but it just doesn't look as clean, and it also runs into logic coding problems, if someone sets a building in one tag, but forgets to in another, etc. Ultimately I'll probably settle on that aproach though, but figure I should ask if this is at least feasible.
<BonusTypeStructs>
<BonusTypeStruct>
<BonusType>BONUS_MARBLE</BonusType>
<bBonusMakesValid>1</bBonusMakesValid>
<bBonusTrade>1</bBonusTrade>
<iDiscoverRand>0</iDiscoverRand>
<YieldChanges>
<iYieldChange>0</iYieldChange>
<iYieldChange>1</iYieldChange>
<iYieldChange>2</iYieldChange>
</YieldChanges>
</BonusTypeStruct>
</BonusTypeStructs>
void CvXMLLoadUtility::SetVariableListTagPair(
bool **ppbList, [B][COLOR="Red"]int **ppiOtherList,[/COLOR][/B] const TCHAR* szRootTagName,
int iInfoBaseSize, int iInfoBaseLength, bool bDefaultListVal[B][COLOR="Red"], int iDefaultOtherListVal[/COLOR][/B])
{
...
InitStringList(ppbList, iInfoBaseLength, bDefaultListVal);
[B][COLOR="Red"]InitStringList(ppiOtherList, iInfoBaseLength, iDefaultOtherListVal);[/COLOR][/B]
...
iIndexVal = FindInInfoClass(szTextVal);
if (iIndexVal != -1)
{
[B][COLOR="Red"]if (GetNextXmlVal(szTextVal))
{
(*ppbList)[iIndexVal] = FindInInfoClass(szTextVal);
}[/COLOR][/B]
}
gDLL->getXMLIFace()->SetToParent(m_pFXml);
...
}
void CvXMLLoadUtility::SetVariableListTagPair(
bool **ppbList, const TCHAR* szRootTagName,
int iInfoBaseSize, int iInfoBaseLength, bool bDefaultListVal,
[B][COLOR="Red"]int **ppiOtherList = NULL, int iDefaultOtherListVal = 0[/COLOR][/B])
{
...
InitStringList(ppbList, iInfoBaseLength, bDefaultListVal);
[B][COLOR="Red"]if (ppiOtherList != NULL)
{
InitStringList(ppiOtherList, iInfoBaseLength, iDefaultOtherListVal);
}[/COLOR][/B]
...
iIndexVal = FindInInfoClass(szTextVal);
if (iIndexVal != -1)
{
GetNextXmlVal(ppbList[iIndexVal]);
[B][COLOR="Red"]if (ppiOtherList != NULL)
{
if (GetNextXmlVal(szTextVal))
{
(*ppbList)[iIndexVal] = FindInInfoClass(szTextVal);
}
}[/COLOR][/B]
}
gDLL->getXMLIFace()->SetToParent(m_pFXml);
...
}
<PrereqBuildingClasses>
<PrereqBuildingClass>
<BuildingClassType>BUILDINGCLASS_FORGE</BuildingClassType>
<bPrereq>1</bPrereq>
</PrereqBuildingClass>
<PrereqBuildingClasses>
<PrereqBuildingClasses>
<PrereqBuildingClass>
<BuildingClassType>BUILDINGCLASS_FORGE</BuildingClassType>
<TechTypeOverride>NONE</TechTypeOverride>
</PrereqBuildingClass>
<PrereqBuildingClass>
<BuildingClassType>BUILDINGCLASS_BARRACKS</BuildingClassType>
<TechTypeOverride>TECH_MACHINERY</TechTypeOverride>
</PrereqBuildingClass>
<PrereqBuildingClasses>
bool CvUnitInfo::getPrereqBuildingClass(int iType)
{
return m_bpPrereqBuldingClass[iType];
}
bool CvCity::hasBuildingClassesRequired(UnitTypes eUnit) const
{
for ( int i = 0; i < GC.getNumBuildingClassInfos(); i++)
{
if (GC.getUnitInfo(eUnit).getPrereqBuildingClass(i) == -1)
{
if (!isHasBuildingClass(i))
{
return false;
}
}
else if (GC.getUnitInfo(eUnit).getPrereqBuildingClass(i) > -1)
{
if (!GET_TEAM(getTeam()).isHasTech((TechTypes)(GC.getUnitInfo(eUnit).getPrereqBuildingClass(i))))
{
if (!isHasBuildingClass(i))
{
return false;
}
}
}
}
return true;
}
Sure, but you're talking about 4 * NUM_TECHS * NUM_BUILDING_CLASSES bytes. I try to avoid overloading the value of enums when I can. The whole point of an enum is that you can depend on it taking on only a prescribed set of values. Adding new values to it shouldn't be done lightly. Complicating the accessor code to save 40k (100 techs and 100 building classes) doesn't seem worth it to me here.
As for messing up the enums, create a couple helper functions. The user code can still work fine if you just add a few of those.
What should isBuildingClassRequired(int i) return when the array slot holds a valid tech? The CvUnitInfo won't have access to the player to check for the tech. I agree it's totally doable; I just have a gut feel the other solution will be easier and robust enough.
so GC.getTechInfo(-2) is going to be nasty to track down
void CvXMLLoadUtility::SetVariableListTagPair(int **ppiList, const TCHAR* szRootTagName,
int iInfoBaseSize, int iInfoBaseLength, int iDefaultListVal)
{
int i;
int iIndexVal;
int iNumSibs;
TCHAR szTextVal[256];
int* piList;
if (0 > iInfoBaseLength)
{
char szMessage[1024];
sprintf( szMessage, "Allocating zero or less memory in CvXMLLoadUtility::SetVariableListTagPair \n Current XML file is: %s", GC.getCurrentXMLFile().GetCString());
gDLL->MessageBox(szMessage, "XML Error");
}
InitList(ppiList, iInfoBaseLength, iDefaultListVal);
if (gDLL->getXMLIFace()->SetToChildByTagName(m_pFXml,szRootTagName))
{
if (SkipToNextVal())
{
iNumSibs = gDLL->getXMLIFace()->GetNumChildren(m_pFXml);
piList = *ppiList;
if (0 < iNumSibs)
{
if(!(iNumSibs <= iInfoBaseLength))
{
char szMessage[1024];
sprintf( szMessage, "There are more siblings than memory allocated for them in CvXMLLoadUtility::SetVariableListTagPair \n Current XML file is: %s", GC.getCurrentXMLFile().GetCString());
gDLL->MessageBox(szMessage, "XML Error");
}
if (gDLL->getXMLIFace()->SetToChild(m_pFXml))
{
for (i=0;i<iNumSibs;i++)
{
if (GetChildXmlVal(szTextVal))
{
iIndexVal = FindInInfoClass(szTextVal);
if (iIndexVal != -1)
{
GetNextXmlVal(&piList[iIndexVal]);
}
gDLL->getXMLIFace()->SetToParent(m_pFXml);
}
if (!gDLL->getXMLIFace()->NextSibling(m_pFXml))
{
break;
}
}
gDLL->getXMLIFace()->SetToParent(m_pFXml);
}
}
}
gDLL->getXMLIFace()->SetToParent(m_pFXml);
}
}
void SetVariableListTagPair(int **ppiList, const TCHAR* szRootTagName,
int iInfoBaseSize, int iInfoBaseLength, int iDefaultListVal = 0,
const TCHAR* szValueTagName, int iValueInfoBaseLength)
//Variables we need, and initializes the list so that all parts of the array hold the value defined in the default value:
int i;
int iIndexVal;
int iNumSibs;
TCHAR szTextVal[256];
int* piList;
if (0 > iInfoBaseLength)
{
char szMessage[1024];
sprintf( szMessage, "Allocating zero or less memory in CvXMLLoadUtility::SetVariableListTagPair \n Current XML file is: %s", GC.getCurrentXMLFile().GetCString());
gDLL->MessageBox(szMessage, "XML Error");
}
InitList(ppiList, iInfoBaseLength, iDefaultListVal);
//defines the parent tag (for instance "BuildingHappinessChanges") defined in the CvInfos, then drops to the tag below this to begin reading
if (gDLL->getXMLIFace()->SetToChildByTagName(m_pFXml,szRootTagName))
{
if (SkipToNextVal())
//Reads the value of that tag to set the position in the array it will assign the value to; throws error if it reads an index outside the accepted array range
iNumSibs = gDLL->getXMLIFace()->GetNumChildren(m_pFXml);
piList = *ppiList;
if (0 < iNumSibs)
{
if(!(iNumSibs <= iInfoBaseLength))
{
char szMessage[1024];
sprintf( szMessage, "There are more siblings than memory allocated for them in CvXMLLoadUtility::SetVariableListTagPair \n Current XML file is: %s", GC.getCurrentXMLFile().GetCString());
gDLL->MessageBox(szMessage, "XML Error");
}
//drop to the next tag and assign the value in this tag to the position in the array set above.
//The question is how do I tell it to drop to the specified tag passed into the function in szValueTagName and check to make sure it is in the accepted range?
if (gDLL->getXMLIFace()->SetToChild(m_pFXml))
{
for (i=0;i<iNumSibs;i++)
{
if (GetChildXmlVal(szTextVal))
{
iIndexVal = FindInInfoClass(szTextVal);
if (iIndexVal != -1)
{
GetNextXmlVal(&piList[iIndexVal]);
}
gDLL->getXMLIFace()->SetToParent(m_pFXml);
}
if (!gDLL->getXMLIFace()->NextSibling(m_pFXml))
{
break;
}
}
void CvXMLLoadUtility::SetVariableListTagPair(int **ppiList, const TCHAR* szRootTagName,
int iInfoBaseSize, int iInfoBaseLength,
const TCHAR* szValueTagName, int iValueInfoBaseLength, int iDefaultListVal)
{
int i;
int iIndexVal;
int iNumSibs;
TCHAR szTextVal[256];
int* piList;
if (0 > iInfoBaseLength)
{
char szMessage[1024];
sprintf( szMessage, "Allocating zero or less memory in CvXMLLoadUtility::SetVariableListTagPair \n Current XML file is: %s", GC.getCurrentXMLFile().GetCString());
gDLL->MessageBox(szMessage, "XML Error");
}
InitList(ppiList, iInfoBaseLength, iDefaultListVal);
if (gDLL->getXMLIFace()->SetToChildByTagName(m_pFXml,szRootTagName))
{
if (SkipToNextVal())
{
iNumSibs = gDLL->getXMLIFace()->GetNumChildren(m_pFXml);
piList = *ppiList;
if (0 < iNumSibs)
{
if(!(iNumSibs <= iInfoBaseLength))
{
char szMessage[1024];
sprintf( szMessage, "There are more siblings than memory allocated for them in CvXMLLoadUtility::SetVariableListTagPair \n Current XML file is: %s", GC.getCurrentXMLFile().GetCString());
gDLL->MessageBox(szMessage, "XML Error");
}
if (gDLL->getXMLIFace()->SetToChildByTagName(m_pFXml,szValueTagName))
{
for (i=0;i<iNumSibs;i++)
{
if (GetChildXmlVal(szTextVal))
{
iIndexVal = FindInInfoClass(szTextVal);
if (iIndexVal != -1)
{
GetNextXmlVal(&piList[iIndexVal]);
}
if( (iIndexVal > iValueInfoBaseLength) || (iIndexVal < -1) )
{
char szMessage[1024];
sprintf( szMessage, "A defined value for an array is outside of the accepted size of the infoclass!\n Current XML file is: %s", GC.getCurrentXMLFile().GetCString());
gDLL->MessageBox(szMessage, "XML Error");
}
gDLL->getXMLIFace()->SetToParent(m_pFXml);
}
if (!gDLL->getXMLIFace()->NextSibling(m_pFXml))
{
break;
}
}
gDLL->getXMLIFace()->SetToParent(m_pFXml);
}
}
}
gDLL->getXMLIFace()->SetToParent(m_pFXml);
}
}
bool CvUnitInfo::isBuildingClassPrereqOverridden(int iType) const
{
return m_bpPrereqBuldingClass[iType] > -1;
}
bool CvUnitInfo::isBuildingClassPrereq(int iType) const
{
return m_bpPrereqBuldingClass[iType] != -2;
}