Copy the BonusInfo.xml Tag <TechReveal> to FeatureInfos.xml

Monaldinio

Prince
Joined
Jan 6, 2010
Messages
415
Location
Rostock
As can be seen from the title , I would like to copy the <TechReveal> xml Tag and his fuction from the BonusInfo.xml to the FeatureInfos.xml


I have defined the XML tag in the CvInfo.cpp and .h

I have this function in CvPlot.cpp

Code:
FeatureTypes CvPlot::getFeatureType(TeamTypes eTeam) const
{
	if (eTeam != NO_TEAM)
	{
		if (m_eFeatureType != NO_FEATURE)
		{
			if (!GET_TEAM(eTeam).isHasTech((TechTypes)(GC.getFeatureInfo((FeatureTypes)m_eFeatureType).getTechReveal())))
			{
				return NO_FEATURE;
			}
		}
	}
	return (FeatureTypes)m_eFeatureType;
}

After compiling i get this error mesage

1>CvPlot.cpp(6016) : error C2511: 'FeatureTypes CvPlot::getFeatureType(TeamTypes) const' : overloaded member function not found in 'CvPlot'
1> c:\Users\Martin\Desktop\Civ\CIV 4\Civ 4 Kram\28.08.2015 NEUE DLL COC\CvGameCoreDLL\CvPlot.h(41) : see declaration of 'CvPlot'
1>NMAKE : warning U4010: 'Release\CvPlot.obj' : build failed; /K specified, continuing ...

So i have a look to the CvPlot.h...and look for this funktion, but only find this

DllExport FeatureTypes getFeatureType() const;

(For comparison, the bonus function
Code:
DllExport BonusTypes getBonusType(TeamTypes eTeam = NO_TEAM) const;
)

Can I change the function in this way ?

Code:
DllExport FeatureTypes getFeatureType(TeamTypes eTeam = NO_TEAM) const;
 
The problem is DllExport. It exposes the function to the game exe and this runtime linking can't handle overloaded function names. It might be fixable by simply not adding this keyword to your own function declaration. If not, then name your function something else.

It serves no purpose to add DllExport to functions you add yourself as the game exe is unaware of those and will never call them. In fact I recommend never to use it as it will help the compiler.

Code:
GET_TEAM(eTeam).isHasTech((TechTypes)(GC.getFeatureInfo((FeatureTypes)m_eFeatureType).getTechReveal()))
This looks like it will get the job done. However at the same time, it looks slow. This function is called all the time and performance affects the overall performance.

I recommend reducing it to
Code:
GET_TEAM(eTeam).canSeeFeature((FeatureTypes)m_eFeatureType)
CvTeam then has a bool array of length NumFeatures and the function returns a bool from that array.

This array should then be recalculated on game load and if a tech is added/removed. Changing the array content should also mark the entire screen dirty to force the game to draw features you just discovered.

This approach should be faster as less data needs to be looked up. You could even argue about caching which teams can see the feature in each plot, in which case GET_TEAM can be skipped as only eTeam is needed to look up a bool. It's a bit harder to make memory friendly, but it can be done with just 32 or 64 bit of memory, or one or two ints.

This is pure performance, not functionality. If it sounds too complex to do, then don't and see how badly it affects performance. Presumably it will not make the game unplayably slow.
 
Thanks fo yor answer.
A little overlook what i have done so far...


CvInfo.cpp

Code:
//======================================================================================================
//					CvFeatureInfo
//======================================================================================================

//------------------------------------------------------------------------------------------------------
//
//  FUNCTION:   CvFeatureInfo()
//
//  PURPOSE :   Default constructor
//
//------------------------------------------------------------------------------------------------------
CvFeatureInfo::CvFeatureInfo() :
m_iMovementCost(0),
m_iSeeThroughChange(0),
m_iHealthPercent(0),
m_iAppearanceProbability(0),
m_iDisappearanceProbability(0),
[COLOR="#008000"]m_iTechReveal(0),[/COLOR]


Code:
CvFeatureInfo::~CvFeatureInfo()
{
	SAFE_DELETE_ARRAY(m_piYieldChange);
	SAFE_DELETE_ARRAY(m_piRiverYieldChange);
	SAFE_DELETE_ARRAY(m_piHillsYieldChange);
	SAFE_DELETE_ARRAY(m_pi3DAudioScriptFootstepIndex);
	SAFE_DELETE_ARRAY(m_pbTerrain);

	// ************************
	// Added for CoC
	// ************************
	// Feature Tech Yield Changes
	int iI;
	if (m_ppiTechYieldChanges != NULL)
	{
		for (iI=0;iI<GC.getNumTechInfos();iI++)
		{
			SAFE_DELETE_ARRAY(m_ppiTechYieldChanges[iI]);
		}
		SAFE_DELETE_ARRAY(m_ppiTechYieldChanges);
	}
	// ************************
	// End Added for CoC
	// ************************
}

int CvFeatureInfo::getMovementCost() const
{
	return m_iMovementCost;
}

int CvFeatureInfo::getSeeThroughChange() const
{
	return m_iSeeThroughChange;
}

int CvFeatureInfo::getHealthPercent() const
{
	return m_iHealthPercent;
}

int CvFeatureInfo::getAppearanceProbability() const
{
	return m_iAppearanceProbability;
}

int CvFeatureInfo::getDisappearanceProbability() const
{
	return m_iDisappearanceProbability;
}

[COLOR="#008000"]int CvFeatureInfo::getTechReveal() const
{
	return m_iTechReveal;
}[/COLOR]

Code:
bool CvFeatureInfo::read(CvXMLLoadUtility* pXML)
{
	CvString szTextVal;
	if (!CvInfoBase::read(pXML))
	{
		return false;
	}

	pXML->GetChildXmlValByName( szTextVal, "ArtDefineTag");
	setArtDefineTag(szTextVal);

	if (gDLL->getXMLIFace()->SetToChildByTagName(pXML->GetXML(),"YieldChanges"))
	{
		pXML->SetYields(&m_piYieldChange);
		gDLL->getXMLIFace()->SetToParent(pXML->GetXML());
	}
	else
	{
		pXML->InitList(&m_piYieldChange, NUM_YIELD_TYPES);
	}

	if (gDLL->getXMLIFace()->SetToChildByTagName(pXML->GetXML(),"RiverYieldChange"))
	{
		pXML->SetYields(&m_piRiverYieldChange);
		gDLL->getXMLIFace()->SetToParent(pXML->GetXML());
	}
	else
	{
		pXML->InitList(&m_piRiverYieldChange, NUM_YIELD_TYPES);
	}

	if (gDLL->getXMLIFace()->SetToChildByTagName(pXML->GetXML(),"HillsYieldChange"))
	{
		pXML->SetYields(&m_piHillsYieldChange);
		gDLL->getXMLIFace()->SetToParent(pXML->GetXML());
	}
	else
	{
		pXML->InitList(&m_piHillsYieldChange, NUM_YIELD_TYPES);
	}

	pXML->GetChildXmlValByName(&m_iMovementCost, "iMovement");
	pXML->GetChildXmlValByName(&m_iSeeThroughChange, "iSeeThrough");
	pXML->GetChildXmlValByName(&m_iHealthPercent, "iHealthPercent");
	pXML->GetChildXmlValByName(&m_iDefenseModifier, "iDefense");
	pXML->GetChildXmlValByName(&m_iAdvancedStartRemoveCost, "iAdvancedStartRemoveCost");
	pXML->GetChildXmlValByName(&m_iTurnDamage, "iTurnDamage");
	pXML->GetChildXmlValByName(&m_iAppearanceProbability, "iAppearance");
	pXML->GetChildXmlValByName(&m_iDisappearanceProbability, "iDisappearance");
	[COLOR="#008000"]pXML->GetChildXmlValByName(&m_iTechReveal, "iTechReveal");[/COLOR]




CvInfo.h

Code:
CvFeatureInfo();
	virtual ~CvFeatureInfo();

	int getMovementCost() const;							// Exposed to Python
	int getSeeThroughChange() const;					// Exposed to Python
	int getHealthPercent() const;							// Exposed to Python
	int getAppearanceProbability() const;			// Exposed to Python
	int getDisappearanceProbability() const;	// Exposed to Python
[COLOR="#008000"]	int getTechReveal() const;					// Exposed to Python[/COLOR]

Code:
	//---------------------------------------PROTECTED MEMBER VARIABLES---------------------------------
protected:

	int m_iMovementCost;
	int m_iSeeThroughChange;
	int m_iHealthPercent;
	int m_iAppearanceProbability;
	int m_iDisappearanceProbability;
	[COLOR="#008000"]int m_iTechReveal;[/COLOR]


CvPlot.cpp


Code:
FeatureTypes CvPlot::getFeatureType(TeamTypes eTeam) const
{
	if (eTeam != NO_TEAM)
	{
		if (m_eFeatureType != NO_FEATURE)
		{
			if (!GET_TEAM(eTeam).isHasTech((TechTypes)(GC.getFeatureInfo((FeatureTypes)m_eFeatureType).getTechReveal())))
			{
				return NO_FEATURE;
			}
		}
	}
	return (FeatureTypes)m_eFeatureType;
}

CvPlot.h

Code:
DllExport FeatureTypes getFeatureType(TeamTypes eTeam = NO_TEAM) const;

No Error Message after Compiling....


Addet the new tag to every feature in the featerInfo.xml...

Code:
<FeatureInfo>
			<Type>FEATURE_ASTEROIDS</Type>
			<Description>TXT_KEY_FEATURE_ASTEROIDS</Description>
			<iNatureHabitableAtFloweringCounter>9999</iNatureHabitableAtFloweringCounter>
			<iCityPlanetPercent>0</iCityPlanetPercent>
			<TechYieldChanges>
				<TechYieldChange>
					<PrereqTech>NONE</PrereqTech>
					<TechYields>
						<iYield>0</iYield>
						<iYield>0</iYield>
						<iYield>0</iYield>
					</TechYields>
				</TechYieldChange>
				<TechYieldChange>
					<PrereqTech>NONE</PrereqTech>
					<TechYields>
						<iYield>0</iYield>
						<iYield>0</iYield>
						<iYield>0</iYield>
					</TechYields>
				</TechYieldChange>
				<TechYieldChange>
					<PrereqTech>NONE</PrereqTech>
					<TechYields>
						<iYield>0</iYield>
						<iYield>0</iYield>
						<iYield>0</iYield>
					</TechYields>
				</TechYieldChange>
			</TechYieldChanges>
			<Civilopedia>TXT_KEY_FEATURE_ASTEROIDS_PEDIA</Civilopedia>
			<ArtDefineTag>ART_DEF_FEATURE_ASTEROIDS</ArtDefineTag>
			<YieldChanges>
				<iYieldChange>0</iYieldChange>
				<iYieldChange>0</iYieldChange>
				<iYieldChange>0</iYieldChange>
			</YieldChanges>
			<RiverYieldChange>
				<iYield>0</iYield>
				<iYield>0</iYield>
				<iYield>0</iYield>
			</RiverYieldChange>
			<HillsYieldChange/>
			<iMovement>2</iMovement>
			<iSeeThrough>1</iSeeThrough>
			<iHealthPercent>0</iHealthPercent>
			<iDefense>50</iDefense>
			<iAppearance>300</iAppearance>
			<iDisappearance>0</iDisappearance>
			[COLOR="SeaGreen"]<TechReveal>TECH_ORBITAL_FLIGHT</TechReveal>[/COLOR]
			<iGrowth>0</iGrowth>
			<iTurnDamage>0</iTurnDamage>
			<bNoCoast>0</bNoCoast>
			<bNoRiver>0</bNoRiver>
			<bNoAdjacent>0</bNoAdjacent>
			<bRequiresFlatlands>0</bRequiresFlatlands>
			<bRequiresRiver>0</bRequiresRiver>
			<bAddsFreshWater>0</bAddsFreshWater>
			<bImpassable>0</bImpassable>
			<bNoCity>0</bNoCity>
			<bNoImprovement>0</bNoImprovement>
			<bVisibleAlways>0</bVisibleAlways>
			<bNukeImmune>0</bNukeImmune>
			<OnUnitChangeTo/>
			<TerrainBooleans>
				<TerrainBoolean>
					<TerrainType>TERRAIN_COAST</TerrainType>
					<bTerrain>1</bTerrain>
				</TerrainBoolean>
				<TerrainBoolean>
					<TerrainType>TERRAIN_SHELF</TerrainType>
					<bTerrain>1</bTerrain>
				</TerrainBoolean>
				<TerrainBoolean>
					<TerrainType>TERRAIN_OCEAN</TerrainType>
					<bTerrain>1</bTerrain>
				</TerrainBoolean>
			</TerrainBooleans>
			<FootstepSounds>
			</FootstepSounds>
			<WorldSoundscapeAudioScript>ASSS_SPACE_RADIATION_SELECT_AMB</WorldSoundscapeAudioScript>
			<EffectType>NONE</EffectType>
			<iEffectProbability>0</iEffectProbability>
			<iAdvancedStartRemoveCost>0</iAdvancedStartRemoveCost>
		</FeatureInfo>

Adding the tag ( <TechReveal> ) to the TerrainSchemata is not necessary because already exists for Bonus...

Afterinitialize a game i have a ctd...

DebuggDLL message...

http://www.civforum.de/attachment.php?attachmentid=1310425&d=1442659523

http://www.civforum.de/attachment.php?attachmentid=1310426&d=1442659523

http://www.civforum.de/attachment.php?attachmentid=1310427&d=1442659523
 
Code:
m_iTechReveal(0),
Shouldn't that be -1 or NO_TECH?

Looks like the crash happens in the exe, which makes debugging harder. I think the problem is here:
Code:
DllExport FeatureTypes getFeatureType(TeamTypes eTeam = NO_TEAM) const;
You can't change arguments to a function called by the exe. The default value is assigned at compile time, meaning the function always takes the argument. If the calling line lacks an argument, the compiler simply hardcodes NO_TEAM in the argument field. The exe leaves the field untouched, meaning it can contain anything and can crash from loading the art for feature 739634 or whatever happens to be stored in that register.

One solution, which might work is this:
Code:
DllExport FeatureTypes getFeatureType([S]TeamTypes eTeam = NO_TEAM[/S]) const;
[S]DllExport[/S] FeatureTypes getFeatureType(TeamTypes eTeam [S]= NO_TEAM[/S]) const;
This makes the vanilla function work as originally intended and can be called by the exe without issues. You however can add an argument, in which case the compiler (or actually linker) will provide you with your new function, which has added features. Naturally you need to restore the original getFeatureType to the cpp file and have both versions present, only to be told apart by the different arguments.

If this doesn't work, then try renaming your own function into something else to prevent overloading and possibly nameclashing. That should surely work. However I don't see why an overloaded function name shouldn't work here, but DllExport can be funny at times.
 
m_iTechReveal(0),
Shouldn't that be -1 or NO_TECH?


I dont know i copy it from the Bonus entries, you should be able to use a certain Tech as you can see here...
The Tag should work like the Tag in the bonusinfo XML...

<TechReveal>TECH_ORBITAL_FLIGHT</TechReveal>

Should i try One of both functions or both together?

Code:
DllExport FeatureTypes getFeatureType() const;
FeatureTypes getFeatureType(TeamTypes eTeam) const;
 
If the default tech is 0, it will reveal the feature if the team has tech 0, which is the first in the xml file. That's likely not what you want for a default value. NO_TECH sounds more like it and then you should make the check somewhat like:
Code:
FeatureTypes CvPlot::getFeatureType(TeamTypes eTeam) const
{
	if (eTeam != NO_TEAM)
	{
		if (m_eFeatureType != NO_FEATURE)
		{
			[B]TechTypes eTech = (TechTypes)(GC.getFeatureInfo((FeatureTypes)m_eFeatureType).getTechReveal());
			if (eTech != NO_TECH && !GET_TEAM(eTeam).isHasTech(eTech))[/B]
			{
				return NO_FEATURE;
			}
		}
	}
	return (FeatureTypes)m_eFeatureType;
}

And yes, you need both versions of getFeatureType. Regardless of what you do, you need to provide a version with DllExport and no arguments for the exe to function as intended. You may consider that one to return the value of getFeatureType(team ID of current player) as this will be what is displayed on the map.
Code:
FeatureTypes CvPlot::getFeatureType() const
{
	PlayerTypes ePlayer = GC.getGameINLINE().getActivePlayer();
	if (ePlayer != NO_PLAYER)
	{
		return getFeatureType(GET_PLAYER(ePlayer).getTeam());
	}
	return (FeatureTypes)m_eFeatureType;
}
I think that will make the game display the map as the human player is supposed to see the map. Even if you in theory can rely on this for setting the team, I would add it in all calls from the DLL, just to be sure that you get the feature visible to the correct team.
 
You could try hardcoding it to call the get feature for team 0 (which should be the human team in singleplayer). It's not the correct solution, but it's a fairly quick way to detect if this is the only problem.

...okay but how can i do that, how would the code look like? Im not a pro in coder
 
Thanks for the fast answer!;)


...so that both functions are consecutively written ?!


PHP:
FeatureTypes CvPlot::getFeatureType(TeamTypes eTeam) const
{
	if (eTeam != NO_TEAM)
	{
		if (m_eFeatureType != NO_FEATURE)
		{
			TechTypes eTech = (TechTypes)(GC.getFeatureInfo((FeatureTypes)m_eFeatureType).getTechReveal());
			if (eTech != NO_TECH && !GET_TEAM(eTeam).isHasTech(eTech))
			{
				return NO_FEATURE;
			}
		}
	}
	return (FeatureTypes)m_eFeatureType;
}


FeatureTypes CvPlot::getFeatureType() const
{
	// hardcoding for testing purposes 
	return getFeatureType((TeamTypes)0);
}
 
Back
Top Bottom