An Idiots Guide to Editing the DLL

You want to create a Widget. That identifies something placed in python which will be handled by the DLL.


There would be quite a few ways to go about your tanker idea. I'll let you play with it to get a feel for which is most intuitive for you (and thus easier to eventually write).

An Area is one continent, or one Ocean. If a worker or workboat could move between two tiles (on a mapwith no cities or improvements), those tiles are in the same area.
 
I can't figure out where the city access to resources is located. I can't find it in cvCity or CvArea. would you have any idea about this ?
 
Do you mean where the data is stored which you see on the top right side of the city detail screen? (number of each resource conntected to the city)?

CvCity::getNumBonuses

Stored in the array m_paiNumBonuses (and those granted by a corporation are from m_paiNumCorpProducedBonuses array).

Use CvCity::changeNumBonuses if you want to change how many bonuses are available in a city.
 
Not exactly. I consider those functions to be "accessors" but what I want is the "above layer" of programming who uses these functions to manage the resources for each city. I "think" this should exist.
 
Use CvCity::changeNumBonuses if you want to change how many bonuses are available in a city.

I'm also messing around with resources... I have some functions that make additional bonus resources available to cities. I'm also using changeNumBonuses to change bonuses. It works, insofar that the additional bonus is available, but only in a single city (where the building which makes the resource available is built). How can I make this bonus available to the entire trade network, and also available for AI trade?
 
Ok, both of your questions are answered by the same function fortunately. You want to mess with a "plotgroup" not a city. Plotgroups carry the tradeable/shared bonuses.

For adding a bonus into a plotgroup, you can do it THROUGH a city with CvCity::changeFreeBonus. But for all the full details of a plotgroup, they have their own file, CvPlotGroup.cpp. I assume that file answers the original question?
 
Ok, please confirm if I understood this correctly... by using changeNumBonuses I can make available a bonus resource in a single city, that is what my code does now. If I instead of changeNumBonuses use changeFreeBonus, I make this resource available in all cities?
 
Ok, both of your questions are answered by the same function fortunately. You want to mess with a "plotgroup" not a city. Plotgroups carry the tradeable/shared bonuses.

For adding a bonus into a plotgroup, you can do it THROUGH a city with CvCity::changeFreeBonus. But for all the full details of a plotgroup, they have their own file, CvPlotGroup.cpp. I assume that file answers the original question?

Yes it does thank you.

But I have another question...I'm following along the lines of this thread http://forums.civfanatics.com/showthread.php?t=334289&highlight=widget and have modified the specified files but I don't understand what gives data to the widget (inside it's struct) cause I need it for further treatment.
 
Ninja2: Correct.

LoneTraveller: The 2 items of data passed to the widget are the two numbers listed in python right after saying WidgetType.WIDGET_WHATEVER. Frequently they are both a -1 due to the widget not needing any data.
 
Ninja2: Correct.

LoneTraveller: The 2 items of data passed to the widget are the two numbers listed in python right after saying WidgetType.WIDGET_WHATEVER. Frequently they are both a -1 due to the widget not needing any data.

Thanks.

With your knowledge I bet you could write a sweet API with quite usefull comments for this SDK.

Now I have another problem. I'm looking for a function that would gimme a pointer to a unit by calling it's "m_iID" from the CvUnit.cpp. I figured that it's in the GC functions but all I saw were about getUnitInfo, getUnitCombat, getUnitArt, etc. I saw nothing requiring an ID integer.

Where should I look ?
 
I could, until I hit the pieces of the API which aren't even in the DLL. Then it would rely on those which I have been forced to muddle through, or some deliberate testing. The lack of info in the damnable API is the main reason I despise being forced to use python for the interface pieces (and avoid it for everything else like the plague)


So you already have the m_iID data, and couldn't have grabbed anything else, or that is what you are using in your widget, since you want to refer to a specific unit and only have integers available? Probably the latter, context clues and whatnot.

Anyway, to use the ID number to find a unit, you also need to know who owns the unit, so I hope you weren't already using the second data item for something else.

From CvGameCoreUtils:

Code:
CvUnit* getUnit(IDInfo unit)
{
	if ((unit.eOwner >= 0) && unit.eOwner < MAX_PLAYERS)
	{
		return (GET_PLAYER((PlayerTypes)unit.eOwner).getUnit(unit.iID));
	}

	return NULL;
}

And the IDInfo object you need to send is built like this:

Code:
IDInfo CvUnit::getIDInfo() const
{
	IDInfo unit(getOwnerINLINE(), getID());
	return unit;
}

So for you it would look something like:

Code:
	IDInfo unit(widgetDataStruct.m_iData1, widgetDataStruct.m_iData2);
	CvUnit* pUnit = getUnit(unit)

Then use pUnit as you desire. Oh, for this setup the Player number for the owner was data1, and the unit's ID was data2
 
the UnitID thing worked out great.

Thanks Xienwolf !

Now...naturally I have another problem...I need to redefine the characteristics of "open borders" diplomatic status. What I mean is to make it so that my internal trade of resources would stop between each plotGroup going through other nation's territory but I would still be able to navigate ships in that foreign territory.

Looking at the list of .cpp files I thought that CvDiploParameters.cpp would be the thing but it strikes me that it relates more to interactions with another civ.

I also looked around for 'open_border' and the only thing that showed up was in AI_doDiplo function of the file I originally looked into.

I'm not sure what to do now...
 
So you want to make it so that having roads through territory not belonging to yourself fail to connect cities for resources?

That would be a bit trickier, as I think the checks are done by simply looking for a valid route between two cities, so the only way to block trade connections is to block unit movement.
 
To display on the unit, you would want to modify CvGameTextMgr::setUnitHelp, or some fairly similar name to that. I do remember that there are a couple such functions, so you want to look at the first argument for the function to make sure it is a CvUnit* pUnit, and not a UnitInfos eUnit. pUnit version is for an actual unit out on the field. If defensiveOnly status is already displayed on units who cannot attack by UnitInfo tag, then you can just search for it and place yours as a simple OR statement appended to the already existing code.

Exposure to python will be a matter of going to CyUnit.cpp and making a function that points at CvUnit.cpp functions, just like all the other functions around it will. And then of course CyUnit.h needs to declare those functions, and finally CyUnitInterface needs to have a single line which acts as the bridge between python and the CyUnit.cpp file, again it will mimic what is all around it for simplicity.


In CvUnit.cpp you would make a function to track the DefensiveOnly status of your unit, and modify ::setHasPromotion to increment a tracking integer when such a promotion is gained. Then you find all locations where isDefensiveOnly() is asked, and point them at CvUnit instead of UnitInfos.
 
Working on what I thought would be a pretty simple tag addition. Adding a tag to UnitInfos so that a Unit will either require, or cannot be built with certain game options. But I've ran into an issue while compiling.

I have the schema set up fine, adding two new tags: ReqGameOption (required game option to build), and NotGameOption (cannot build with this game option selected). Here is my code:

Spoiler :
CvInfos.h
Code:
public:
	CvUnitInfo();
	virtual ~CvUnitInfo();
...

	//phungus Gameoption CanTrain
	[B]int getReqGameOption() const;[/B]									// Exposed to Python
	[B]int getNotGameOption() const;[/B]									// Exposed to Python
	//phungus -end
...
protected:
...
	//phungus GameOption CanTrain
	[B]int m_iReqGameOption;
	int m_iNotGameOption;[/B]	
	//phungus -end
CvInfos.cpp
Code:
CvUnitInfo::CvUnitInfo() :
...
//phungus GameOption CanTrain
[B]m_iReqGameOption(NO_GAMEOPTION),
m_iNotGameOption(NO_GAMEOPTION),[/B]
//phungus -end
...
//phungus GameOption CanTrain
[B]int CvUnitInfo::getReqGameOption() const
{
	return m_iReqGameOption;
}

int CvUnitInfo::getNotGameOption() const
{
	return m_iNotGameOption;
}[/B]
//phungus -end
...
void CvUnitInfo::read(FDataStreamBase* stream)
{
	CvHotkeyInfo::read(stream);

	uint uiFlag=0;
	stream->Read(&uiFlag);	// flags for expansion
...
	//phungus GameOption CanTrain
[B]	stream->Read(&m_iReqGameOption);
	stream->Read(&m_iNotGameOption);[/B]
	//phungus -end
...
void CvUnitInfo::write(FDataStreamBase* stream)
{
	CvHotkeyInfo::write(stream);

	uint uiFlag=0;
	stream->Write(uiFlag);		// flag for expansion
...
	//phungus GameOption CanTrain
[B]	stream->Write(m_iReqGameOption);
	stream->Write(m_iNotGameOption);[/B]
	//phungus -end
...
bool CvUnitInfo::read(CvXMLLoadUtility* pXML)
{
	CvString szTextVal;
	if (!CvHotkeyInfo::read(pXML))
	{
		return false;
	}
...
	//phungus GameOption canTrain
	[B]pXML->GetChildXmlValByName(szTextVal, "ReqGameOption");
	m_iReqGameOption = pXML->FindInInfoClass(szTextVal);

	pXML->GetChildXmlValByName(szTextVal, "NotGameOption");
	m_iNotGameOption = pXML->FindInInfoClass(szTextVal);[/B]
	//phungus -end
...
void CvUnitInfo::copyNonDefaults(CvUnitInfo* pClassInfo)
{	
	CvHotkeyInfo::copyNonDefaults(pClassInfo);

	bool bDefault = false;
	int iDefault = 0;
	int iTextDefault = -1;
	CvString cDefault = CvString::format("").GetCString();
...
	//phungus GameOption canTrain
	[B]if ( m_iReqGameOption == iTextDefault ) m_iReqGameOption = pClassInfo->getReqGameOption();
	if ( m_iNotGameOption == iTextDefault ) m_iNotGameOption = pClassInfo->getNotGameOption();[/B]
	//phungus -end

And finally CvPlayer.cpp (not going to bother showing the CyInterfaceInfo code)
Code:
bool CvPlayer::canTrain(UnitTypes eUnit, bool bContinue, bool bTestVisible, bool bIgnoreCost) const
{
	PROFILE_FUNC();
...
	//phungus GameOption canTrain
	if (GC.getUnitInfo(eUnit).getReqGameOption() != NO_GAMEOPTION)
	{
		if (!(GC.getGameINLINE().isOption(GC.getUnitInfo(eUnit).getReqGameOption())))
		{
			return false;
		}
	}
	
	if (GC.getUnitInfo(eUnit).getNotGameOption() != NO_GAMEOPTION)
	{
		if (GC.getGameINLINE().isOption(GC.getUnitInfo(eUnit).getReqGameOption()))
		{
			return false;
		}
	}
	//phungus End

Here is the error I'm getting:
1>CvPlayer.cpp(6596) : error C2664: 'CvGame::isOption' : cannot convert parameter 1 from 'int' to 'GameOptionTypes'
1> Conversion to enumeration type requires an explicit cast (static_cast, C-style cast or function-style cast)
1>CvPlayer.cpp(6604) : error C2664: 'CvGame::isOption' : cannot convert parameter 1 from 'int' to 'GameOptionTypes'
1> Conversion to enumeration type requires an explicit cast (static_cast, C-style cast or function-style cast)

Now my impression is that the problem is a string vs int definition. But all the stings in CvInfos are declared as ints... So I'm a bit confused. Any idea what's wrong here, and more importantly how to fix?
 
First issue is your CopyNonDefaults, the compiler didn't catch it, but you are comparing an integer against the text default, you want to compare it against -1 instead, as that is the TRUE default (it is no longer a string at that point).

The actual error, is that you need to say:

(GameOptionTypes)gx.getUnitInfo(eUnit).getReqGameOption()

Having the (GameOptionTypes) changes it from 3 to GAMEOPTION_NO_WARRIORS, and thus allows checking it.
 
First issue is your CopyNonDefaults, the compiler didn't catch it, but you are comparing an integer against the text default, you want to compare it against -1 instead, as that is the TRUE default (it is no longer a string at that point).
Isn't that what the m_iReqGameOption(NO_GAMEOPTION), does, doesn't this make it so that RegGameOption returns NO_GAMEOPTION if nothing else is specified? I guess not, but what is being stored in the variable then?

The actual error, is that you need to say:

(GameOptionTypes)gx.getUnitInfo(eUnit).getReqGameOption()

Having the (GameOptionTypes) changes it from 3 to GAMEOPTION_NO_WARRIORS, and thus allows checking it.
I'm not understanding, what's the proper syntax of these lines supposed to be (also the first line didn't return an error, so I'm confused, if it's not returning a string, why was the first line OK)?
if (GC.getUnitInfo(eUnit).getNotGameOption() != NO_GAMEOPTION)
if (GC.getGameINLINE().isOption(GC.getUnitInfo(eUnit).getReqGameOption()))
 
Top Bottom