General DLL programming questions

There's a lot of possible ways to have a problem there and if its not saying much about why then its tough to diagnose. So here's a list of things to check:
  • Make sure that your declared tags in the tech schema aren't declared elsewhere.
  • Make sure you've not only declared the tag but have also stated a call for it in the tech info section.
  • Check to make sure you have declared the tag(s) as being not required (minOccurs="0")
  • Ensure that the tag, wherever applied in the info file, is in the correct order.
  • Be wary of comment lines in the info file - often the way those process will create a mysterious load error.
Check those first. Since you have an XML load error, its probably in the way the XML was done, not in the load sequence in the code.
 
There's a lot of possible ways to have a problem there and if its not saying much about why then its tough to diagnose. So here's a list of things to check:
  • Make sure that your declared tags in the tech schema aren't declared elsewhere.
  • Make sure you've not only declared the tag but have also stated a call for it in the tech info section.
  • Check to make sure you have declared the tag(s) as being not required (minOccurs="0")
  • Ensure that the tag, wherever applied in the info file, is in the correct order.
  • Be wary of comment lines in the info file - often the way those process will create a mysterious load error.
Check those first. Since you have an XML load error, its probably in the way the XML was done, not in the load sequence in the code.

It is not a schema error, that much I was able to determine. I've attached the CvInfos for you to look at, that are the only place that it could be. Look for my "//ls612: Tech Commerce Changes" comments are to see where my new stuff is.
 

Attachments

Code:
	<ElementType name="iCommerce" content="textOnly" dt:type="int"/>
	<ElementType name="CommerceModifiers" content="eltOnly">
		<element type="iCommerce" minOccurs="0" maxOccurs="*"/>
	</ElementType>
You have not declared iCommerce yet (the first line in the set above). I just highlighted iCommerce and searched for it in your schema and its only there in an applied state (the third line in the set above.) I know I told you to be concerned about it possibly already being declared (as multiple declarations will give an error) but apparently in that schema it hasn't been yet (which is a bit ironic considering how common iCommerce is applied in our files usually.)

Anyhow, just as simple as that. Usually the really confounding errors are the simplest ones ;) Everything else looked to be in good shape.
 
@Koshling:

I've implemented some basic AI For tech commerce modifiers, but on game load the game gets stuck for a very long time on this block of code in AI_techValue. I've measured it outside the debugger, and it takes more than ten minutes of unresponsiveness, after that I killed the process.

What am I doing wrong here?

PHP:
	//ls612: Tech Commerce Modifiers
	for (int iI = 0; iI < NUM_COMMERCE_TYPES; iI++)
	{
		if (GC.getTechInfo(eTech).getCommerceModifier(iI) != 0)
		{
			iValue += (GC.getTechInfo(eTech).getCommerceModifier(iI) * 100);
		}

		//Extra check for financially challenged AIs
		if (iI = 0 && GC.getTechInfo(eTech).getCommerceModifier(iI) < 0)
		{
			if (AI_isFinancialTrouble())
			{
				iValue -= 100;
			}
		}
	}
 
Well, I solved that problem by checking the array to see if it wasn't NULL. Problem is that that method does not allow the AI to understand negative numbers in the Tech commerce Modifiers, so I'd like for some help figuring out what the issue was with the old code.
 
How would I best go about determining the chance that a Nuke heading towards a plot will be intercepted by a nearby unit? Currently what I've done is made the following function in CvPlot

PHP:
int CvPlot::getUnitNukeIntercept(PlayerTypes eOwner) const
{
	CLLNode<IDInfo>* pUnitNode;
	CvUnit* pLoopUnit;
	int iChance;
	int iTempValue = 0;
	iChance = 0;

	pUnitNode = headUnitNode();

	while (pUnitNode != NULL)
	{
		pLoopUnit = ::getUnit(pUnitNode->m_data);
		pUnitNode = nextUnitNode(pUnitNode);

		if (((eOwner == NO_PLAYER) || (pLoopUnit->getOwnerINLINE() == eOwner)) && (pLoopUnit->getUnitInfo().getNukeInterceptionProbability() > iTempValue))
		{
			iChance = pLoopUnit->getUnitInfo().getNukeInterceptionProbability();
			iTempValue = iChance;
		}
	}

	return iChance;
}

Which returns the best nuke intercept unit's probability on that tile. But I don't know how to get it to work at range, or if the way I'm doing it for single plots is good or not. Any ideas?
 
@Koshling:

I've implemented some basic AI For tech commerce modifiers, but on game load the game gets stuck for a very long time on this block of code in AI_techValue. I've measured it outside the debugger, and it takes more than ten minutes of unresponsiveness, after that I killed the process.

What am I doing wrong here?

PHP:
	//ls612: Tech Commerce Modifiers
	for (int iI = 0; iI < NUM_COMMERCE_TYPES; iI++)
	{
		if (GC.getTechInfo(eTech).getCommerceModifier(iI) != 0)
		{
			iValue += (GC.getTechInfo(eTech).getCommerceModifier(iI) * 100);
		}

		//Extra check for financially challenged AIs
		if (iI = 0 && GC.getTechInfo(eTech).getCommerceModifier(iI) < 0)
		{
			if (AI_isFinancialTrouble())
			{
				iValue -= 100;
			}
		}
	}

The issue is with this line:

Code:
		//Extra check for financially challenged AIs
		if (iI = 0 && GC.getTechInfo(eTech).getCommerceModifier(iI) < 0)

Should be 'iI == 0' NOT 'iI = 0'
 
How would I best go about determining the chance that a Nuke heading towards a plot will be intercepted by a nearby unit? Currently what I've done is made the following function in CvPlot

PHP:
int CvPlot::getUnitNukeIntercept(PlayerTypes eOwner) const
{
	CLLNode<IDInfo>* pUnitNode;
	CvUnit* pLoopUnit;
	int iChance;
	int iTempValue = 0;
	iChance = 0;

	pUnitNode = headUnitNode();

	while (pUnitNode != NULL)
	{
		pLoopUnit = ::getUnit(pUnitNode->m_data);
		pUnitNode = nextUnitNode(pUnitNode);

		if (((eOwner == NO_PLAYER) || (pLoopUnit->getOwnerINLINE() == eOwner)) && (pLoopUnit->getUnitInfo().getNukeInterceptionProbability() > iTempValue))
		{
			iChance = pLoopUnit->getUnitInfo().getNukeInterceptionProbability();
			iTempValue = iChance;
		}
	}

	return iChance;
}

Which returns the best nuke intercept unit's probability on that tile. But I don't know how to get it to work at range, or if the way I'm doing it for single plots is good or not. Any ideas?

That's fine for a single plot. Hard to answer the question re range without knowing exactly how you would want range interception to operate. However, what you PROABBLY want to do is turn what you have into a standard PUF function (see the functions with names beginning PUF_ in CvGameCoreUtils.cpp) and access it via a method based on CvPlot.plotCount() which takes a range and allows arbitrary PUF_ functions to be aggregaed over a range.
 
The issue is with this line:

Code:
		//Extra check for financially challenged AIs
		if (iI = 0 && GC.getTechInfo(eTech).getCommerceModifier(iI) < 0)

Should be 'iI == 0' NOT 'iI = 0'

:hammer2: Goodness that was a stupid error. I wish the compiler would at least warn me about that. Thanks

That's fine for a single plot. Hard to answer the question re range without knowing exactly how you would want range interception to operate. However, what you PROABBLY want to do is turn what you have into a standard PUF function (see the functions with names beginning PUF_ in CvGameCoreUtils.cpp) and access it via a method based on CvPlot.plotCount() which takes a range and allows arbitrary PUF_ functions to be aggregaed over a range.

OK, I'll try that. For background I'm trying to implement the two int tags listed here for units, as part of a Nuke revamp.
 
New question now. I've been trying again to get the DLL to compile in Visual Studio 2012 Express, and I think the issue is with the environment variables and directories. They are controlled in 2012 in this window

attachment.php


But I can't find where they are in VC++ 2008. I figure that if I change all of the directories in 2012 to what they are in 2008 that it may compile. Does someone know where that data is kept in the 2008 version of Visual C++?
 

Attachments

  • Capture.PNG
    Capture.PNG
    28.9 KB · Views: 297
Wow... its been a long time since I've had to manipulate things there. Its also entirely possible that there could be some funny issues with attempting to use 2012. I never had enough real understanding of what I was doing to get set up that I could offer any assistance here. Just followed the tutorials and struggled with it a lot until it was working and now I don't touch it with a 10' pole!
 
I have another question. What is needed to add a gameoption. I've added it to the CvEnums and to the GameText files, but will that be enough to make it work? Or will I need to add some python for it as well?

Also I'm thinking of making several obsolete or bad options invisible and defaulted off. The candidates OTOH are

  • Lock Modified Assets
  • The 4 ones related to civ switching (final 5, high to low, etc)
  • No Positive Traits

Regarding the last one, Thunderbrd said that that one is specifically for use with Leaderhead Levelups. In that case I'd suggest just building that into the Leaderhead Levelup system and not making a separate option that could confuse people.
 
No Positive Traits on Gamestart is not ONLY for Developing Leaders. It's also so that a player may choose to simply play without traits if combined with No Negative Traits. Might be an interesting game variant that way and I also want to keep the ability to play Developing Leaders without the No Positive Traits on Gamestart option so that leaders may maintain their classic selections when they begin the game.

I believe Lock Modified is already turned off and invisible. The civ switching ones are appreciated by some I think. However, imo, Useable Mountains should be on and invisible. (I would've said unlimited wonders too but it seems there's nowhere near the consensus there I would've expected! lol)

Those settings are simply a part of the gameoptioninfos.xml file.

No python is necessary to add, but you do need a correlating entry in the gameoptioninfos.xml file and you cannot delete one from the enums nor from the xml once one is made without screwing up the savegame compatibility.
 
No python is necessary to add, but you do need a correlating entry in the gameoptioninfos.xml file and you cannot delete one from the enums nor from the xml once one is made without screwing up the savegame compatibility.

Game option ids are remapped by the max compatibility save code, so deleting them should be ok too (though it may not have been explicitly tested, so would be as well to test if you do)
 
Game option ids are remapped by the max compatibility save code, so deleting them should be ok too (though it may not have been explicitly tested, so would be as well to test if you do)

OK, good to know then. I'll try that and make sure it doesn't break anything.
 
A python question really but I need to get the name of the properties or to be more precise I need to know which property is which. In game on the properties tap the properties change order and if zero sometimes don't show. AIAndy uses pHeadSelectedCity.getProperties() to get the proper details into I think getPropertyDisplay(index) gives the icon and the name but I a not sure. I need the icon and name as separate entities.
 
A python question really but I need to get the name of the properties or to be more precise I need to know which property is which. In game on the properties tap the properties change order and if zero sometimes don't show. AIAndy uses pHeadSelectedCity.getProperties() to get the proper details into I think getPropertyDisplay(index) gives the icon and the name but I a not sure. I need the icon and name as separate entities.
getProperty(index) returns the property id for which you can then query the info:
GC.getPropertyInfo(id).getChar() is the icon character but I fear not much more is exposed to Python at the moment (can be exposed in CyInfoInterface4.cpp).
 
getProperty(index) returns the property id for which you can then query the info:
GC.getPropertyInfo(id).getChar() is the icon character but I fear not much more is exposed to Python at the moment (can be exposed in CyInfoInterface4.cpp).

I was playing around with the idea of fuel gauge buttons with the properties similar to the Revolutions one where it shows if the property is getting better or worse and gives you a clue how much attention you should give it right now. One problem is that they all have differing values which can be considered "safe" at different times. For Crime 75 can be considered bad if you have Currency but a higher value is fine before that tech has been researched. So I was aiming for a text to say "safe", "warning" and "attention now" (or something) with the hover over saying the current numbers with maybe a tip like "this value is dangerous if you discover currency" if they don't have currency. Another problem is that they all have different minimum and maximum values. Both these things mean that I need to know which one I am dealing with. In python would expect o use something like GC.getPropertyInfo(id).getType() == PROPERTY_CRIME to identify the crime one for example.

Edit I was also trying to get them on the main screen but there is just not enough real estate is there! :(
 
I was playing around with the idea of fuel gauge buttons with the properties similar to the Revolutions one where it shows if the property is getting better or worse and gives you a clue how much attention you should give it right now. One problem is that they all have differing values which can be considered "safe" at different times. For Crime 75 can be considered bad if you have Currency but a higher value is fine before that tech has been researched. So I was aiming for a text to say "safe", "warning" and "attention now" (or something) with the hover over saying the current numbers with maybe a tip like "this value is dangerous if you discover currency" if they don't have currency. Another problem is that they all have different minimum and maximum values. Both these things mean that I need to know which one I am dealing with. In python would expect o use something like GC.getPropertyInfo(id).getType() == PROPERTY_CRIME to identify the crime one for example.

Edit I was also trying to get them on the main screen but there is just not enough real estate is there! :(
That line is equivalent to
id == PROPERTY_CRIME
(as long as you got PROPERTY_CRIME from gc.getInfoTypeForString("PROPERTY_CRIME") )

You can also query the value of a specific property with
pHeadSelectedCity.getProperties().getValueByProperty(PROPERTY_CRIME)
or the change since last turn with
pHeadSelectedCity.getProperties().getChangeByProperty(PROPERTY_CRIME)
 
Good, thank you. At the moment the bar is occurring on the wrong side of the wrong screen, but that seems normal when I play around with python screens:blush:
 
Back
Top Bottom