bTestVisible on funcs like canCreate()?

davidlallen

Deity
Joined
Apr 28, 2008
Messages
4,743
Location
California
I have just added some projects in xml, which require other projects as prerequisites. In vanilla, for example, the spaceship part projects require the apollo project to be complete first:
Code:
			<PrereqProjects>
				<PrereqProject>
					<ProjectType>PROJECT_APOLLO_PROGRAM</ProjectType>
					<iNeeded>1</iNeeded>
				</PrereqProject>
			</PrereqProjects>

I have a line of four projects, each requiring the previous. So at the start of the game, only the first one should be available to be built and the others should not be. But, in my city build queue, I see all four available to be built. This is wrong.

Looking into CvPlayer::canCreate(), I see that there is a loop to check this:
Code:
		for (iI = 0; iI < GC.getNumProjectInfos(); iI++)
		{
			if (GET_TEAM(getTeam()).getProjectCount((ProjectTypes)iI) < GC.getProjectInfo(eProject).getProjectsNeeded(iI))
			{
				return false;
			}
		}
This loop is inside a test !bTestVisible, which I see in many such canXxx() functions. Can anybody help me understand what this flag is for, and why this loop should only be checked when this flag is false?

The only reason I can think of for all my projects to appear in the queue, is if CvPlayer::canCreate() is called with bTestVisible true. If that is the problem, then other projects like the space ship parts should be available without their prerequisites. I cannot quite follow the call stack all the way up, to figure it out.
 
OK, I am more confused now. The PrereqProject is clearly working in vanilla; cvgametextmgr is printing the correct "Requires" and "Required by" into the pedia. But in dune wars, it is not working. The "Requires" and "Required by" never shows up in the pedia. In general, how does an xml item get resolved, when it refers to other items of the same type? Perhaps that has stopped working for my projects for an unknown reason. For example, while parsing a tech xml, you may come across PrereqTech for another tech, which is later in the file. That all works. Where is that done for projects?
 
The bTestVisible flag is set to TRUE to see if the item should display at all in your city. If it passes this check, you see it. Then it is set to FALSE to see if the item can be constructed. If it fails this check, but passed the previous one, it shows up as a "greyed out" item, and typically CvGameTextMgr is set up to properly display what requirements you have not met yet.

Projects come packages with a PrereqProject from base BtS, do they not? If so, then the loading of the XML is handled for you during CvProjectInfo::readPass2. If not, then you need to write it to be handled in that location. readPass2 is specifically for anything in a XML file that refers to other items in the same XML file.
 
The spaceship part projects in BTS require team project. Is this special cased, or is a team project just a normal project that every player in the team gains once one player builds it? Check in canConstruct() to see if the team is being asked if it has the prereq project or if the player is being asked. If the player, then you should be okay, but it certainly sounds like it thinks the player has the prereq or doesn't see the prereq at all.
 
Also project interdependencies are hardcoded into the RevDCM dll; something to do with WoC messing with the code. So while technologies still can make a project buildable, interdependcies for other projects do not, which may or may not be messing with the canCreate function, I don't know (but certainly worth noting).

This is the code that hardcodes the spaceship, it's in CvInfos.cpp. Without similar code, as far as I know, there is no way to define prereqs for projects (other then technologies), if using a RevDCM core:
Code:
int CvProjectInfo::getProjectsNeeded(int i) const
{
	FAssertMsg(i < GC.getNumProjectInfos(), "Index out of bounds");
	FAssertMsg(i > -1, "Index out of bounds");
	// RevolutionDCM interim patch to Apollo Program bug
	// CvProjectInfo::readPass2() does not fill the m_piProjectsNeeded array.
	// Problem manifests as the info screen displaying a completed apollo project at the start of the game.
	if (i == 2 && m_bSpaceship) return 1; else return 0;
	// original BTS code
	// return m_piProjectsNeeded ? m_piProjectsNeeded[i] : false; 
}
 
Also project interdependencies are hardcoded into the RevDCM dll; something to do with WoC messing with the code.

Oh, wonderful. That must be the root cause. Can anybody help understand *why* CvProjectInfo::readPass2() does not fill the m_piProjectsNeeded array?
 
That is a standard issue with WoC because it has modules launch a pass2 without doing a pass1 IIRC. The simple solution is just to ensure that the array is initialized if it does not exist yet before trying to use it in pass2 (or copynondef), and to ensure that the array is initialized even if not included in the XML file.
 
I did not quite follow the simple solution. Can you describe in a little more detail? The CvXMLLoadUtilitySet.cpp file I have contains this:
Code:
template <class T>
void CvXMLLoadUtility::LoadGlobalClassInfo(std::vector<T*>& aInfos, const char* szFileRoot, const char* szFileDirectory, const char* szXmlPath, bool bTwoPass, CvCacheObject* (CvDLLUtilityIFaceBase::*pArgFunction) (const TCHAR*))
{
	bool bLoaded = false;
	bool bWriteCache = true;
	CvCacheObject* pCache = NULL;
	GC.addToInfosVectors(&aInfos);

/*************************************************************************************************/
/** MODULAR_LOADING_CONTROL                 05/17/08                                MRGENIE      */
/**                                                                                              */
/** This method is a replacement for the bTwoPass, if stuff that is depending on each other in   */
/** a loop, the bTwoPass would fail since it doesn't look first in the other Modules!            */
/*************************************************************************************************/
	bool bTwoPassReplacement = true; // Use this if you wanna use the regular Firaxis bTwoPass
	if ( bTwoPassReplacement )
	{
		if (!bTwoPass )
		{
			bTwoPassReplacement = false;
		}
		bTwoPass = false;
	}

So, since Dune Wars is not using any modular loading, can I simply set bTwoPassReplacement false? Or does it require digging through the code in a lot more detail to make this work?

It is also a little confusing that the lack of readpass2 only causes a problem for project dependencies. Lots and lots of other files depend on themselves. For example, techs have prereqtechs, promos have and/orprereqs, etc. If this is a global problem with pass2 failing to resolve these dependencies, why do these self-references work?
 
It is just a special case for having an array in pass2, most other dependancies are not arrays, or were properly handled already. Not sure why this one wasn't done right since it is not too hard to fix, as long as you know what is needed, which the WoC team (at least eventually) did.

I would not touch any WoC stuff in CvXMLLoad, that is dangerous water to tread unless you know exactly what each step does, and I can't remember for certain if you can safely eliminate the bTwoPassReplacement like that.
 
Not sure why this one wasn't done right since it is not too hard to fix, as long as you know what is needed, which the WoC team (at least eventually) did ... I would not touch any WoC stuff in CvXMLLoad.

I understand the concept of the second pass; we have to leave certain items as strings until the entire file is parsed, and then in the second pass, convert the strings to their integers. Since you don't think that CvXMLLoad is the right place to attack this problem, and I am not an expert on the internals of the second pass, can you point me a little more specifically at how to make project prereqs work again?
 
Actually what you describe is how the third pass works. Second pass isn't actually loaded as strings at all, it is simply skipped initially, then at the end of the file the program goes back through and appends the second pass to the pre-existing data.

In WoC, when you get to the modules, there is no pre-existing data to append into, the second pass is run on a blank background, which is the source of this particular issue.


Code:
m_piVictoryMinThreshold(NULL),
m_piProjectsNeeded(NULL),

Code:
	SAFE_DELETE_ARRAY(m_piVictoryMinThreshold);
	SAFE_DELETE_ARRAY(m_piProjectsNeeded);

Code:
int CvProjectInfo::getProjectsNeeded(int i) const
{
	FAssertMsg(i < GC.getNumProjectInfos(), "Index out of bounds");
	FAssertMsg(i > -1, "Index out of bounds");
	return m_piProjectsNeeded ? m_piProjectsNeeded[i] : false;
}

Code:
	pXML->SetVariableListTagPair(&m_piProjectsNeeded, "PrereqProjects", sizeof(GC.getProjectInfo((ProjectTypes)0)), GC.getNumProjectInfos());

	pXML->GetChildXmlValByName(szTextVal, "AnyonePrereqProject");
	m_iAnyoneProjectPrereq = GC.getInfoTypeForString(szTextVal);

In CvProjectInfo::copyNonDefaults
Code:
	// Readpass2 stuff
	if (m_iAnyoneProjectPrereq				== NO_PROJECT)			m_iAnyoneProjectPrereq			= pClassInfo->getAnyoneProjectPrereq();
	if(!m_piProjectsNeeded)											pXML->InitList(&m_piProjectsNeeded, GC.getNumProjectInfos(), 0);
	for (int i = 0; i < GC.getNumProjectInfos(); ++i)
	{
		if(getProjectsNeeded(i)				== 0)					m_piProjectsNeeded[i]			= pClassInfo->getProjectsNeeded(i);
	}

In CvProjectInfo::copyNonDefaultsReadPass2
Code:
	if(!m_piProjectsNeeded)											pXML->InitList(&m_piProjectsNeeded, GC.getNumProjectInfos(), 0);
	for (int i = 0; i < GC.getNumProjectInfos(); ++i)
	{
		if(bOver || pClassInfo->getProjectsNeeded(i)	!= 0)		m_piProjectsNeeded[i]			= pClassInfo->getProjectsNeeded(i);
	}



I will admit that I have not personally tested projects extensively and I do recall some reports that there were issues with pieces of the modular loading here and there, but I do not recall this specific one coming up. Though this tag isn't heavily used, so it may be that even with my code there is an issue.

Mostly the important bits are the two "initlist" commands in the copyNonDefault passes.
 
I have merged your code with the current DW code, adjusted slightly so that it compiles, and it is working! I am now able to set project prereqs in the xml, and it works correctly in game. I understand that WOC is mostly dead, so there is noplace for me to post the working code back to; but at least it works now in DW. Thanks a million!
 
davidallen please post the working code in the RevDCM forum, probably in the Specific code Proposals thread.
 
The changes are contained in CvInfos.cpp. I have also made dozens of other changes in this file for other random DW things, and I am not sure how my file may relate to other versions of this file anymore. I can post the *instructions* in that thread, but posting the *code* may be too confusing. I could post diffs, but that is a unix thing and nobody may understand it. What is your recommendation?
 
When I submit code for RevDCM I download the latest SVN source, and merge my current code with that and comment it. I will then upload the files that contain my changes, and if the changes are small I will also simply post the code in the thread along with the files I upload. I suppose you can look through the thread to see what I mean, though alot of the attachments have been removed; as I delete old ones that are picked and have been updtated into the current version of RevDCM. You'd also be fine not using the current SVN (though it makes merging easier for jdog/glider), and you could just use the current "official" source code for 2.6 in your upload.
 
For reference here is the thread I mean:
http://forums.civfanatics.com/showthread.php?t=328664

I'm pretty tired right now, so my post above may not be too coherent. Basically just think of it this way: Put yourself in jdog and glider's place; working on a big project, and someone comes up with a bug fix/improvement. What would be the best/easiest way for them to submit the code to you so you could get the fix/improvement into the project? Whatever you come up with is probably a good way to do it.
 
Hrm, sucks to hear that WoC has died out, or ground to a halt if that is the case instead. They did some interesting things over there.

I don't think the project is technically dead, but all the SDK coders, like Mr. Genie, seem to have vanished, leaving the project to, well, die a slow death. They had some really good ideas for modular loading, they planned on adding a pre-start screen that allowed players to pick and choose modules to load without touching the XML. It's too bad they never became the modding standard they had hoped for, WoC is pretty useful from a modmoder's perspective.
 
@Xienwolf and DaveAllen
Thanks brothers. Beautiful work. As a woc newcomer that decided not to let woc die and to put it into RevDCM permanently, I fell victim to some of the intricacies of the woc system thanks to ignorance. The fix for project interdependencies you have discussed here works and so I am now a little less ignorant as to it's fundamental cause :mischief:. Faichele helped me to try to fix the fault some time ago, but neither of us could not nail the problem as you have done here because we missed the readpass2 fix goodjob:. Thank you!

I don't know how deep the woc rabbit hole goes yet and hope this is as far as it does go. I say this because I will be trying to debug why RevDCM is dead for multiplayer and locked modified assets, particularly regarding the multiplayer need for LMA. I do not yet know whether the woc xml system plays a part in this.

Cheers.
 
Back
Top Bottom