Sample SDK Code (basic)

I was wondering if anyone could explain the flow of how the SDK and Python files interact. My understanding on this is very fuzzy at best. To be more specific:

1. how does a .py file reference say a function from the SDK (if they actually can)?

2. how are the .cpp files with Cv prefixes related to the .cpp files with Cy prefixes?

3. what exactly is a wrapper?

4. how does a .cpp file get data from a .py class (is this somehow related to the wrappers?)?

I greatly appreciate any input on these. I have been playing around with the files and sometimes think I understand what is going on, but other times end up confused.

Thanks
 
1. how does a .py file reference say a function from the SDK (if they actually can)?

The function has to be exposed to python in the SDK. If that is the case python can call the function on an object. For example pUnit.getDamage() is calling the SDK call getDamage on the pUnit object.

2. how are the .cpp files with Cv prefixes related to the .cpp files with Cy prefixes?

Cv are SDK functions, Cy are the SDK functions that are "exposed" to python.

3. what exactly is a wrapper?

Wrapper is a python class that creates a list of python functions that can be used on a unit. Modders find them handy to make an easy way to reference common functions.

4. how does a .cpp file get data from a .py class (is this somehow related to the wrappers?)?

It doesn't. Python makes calls into the SDK. The SDK doesn't get data from python. You can make a python call into the SDK that passes data (for example: pUnit.setDamage(10)). But you wouldn't write an SDK function that requested info from python.

Python never directly calls XML either. the SDk calls XML, and python requests the info from the SDK.
 
The function has to be exposed to python in the SDK. If that is the case python can call the function on an object. For example pUnit.getDamage() is calling the SDK call getDamage on the pUnit object.



Cv are SDK functions, Cy are the SDK functions that are "exposed" to python.



Wrapper is a python class that creates a list of python functions that can be used on a unit. Modders find them handy to make an easy way to reference common functions.



It doesn't. Python makes calls into the SDK. The SDK doesn't get data from python. You can make a python call into the SDK that passes data (for example: pUnit.setDamage(10)). But you wouldn't write an SDK function that requested info from python.

Python never directly calls XML either. the SDk calls XML, and python requests the info from the SDK.


Thank you, this clears things up greatly.
 
Bump :) :)
 
Here's a little bit of code that I wrote for Ambreville and Jeckel in the "OIL vs. MOVE" thread. (I just converted what Jeckel did in Python to C++.)

Code:
    // Oil movement restriction - Gaius Octavius
    if (m_pUnitInfo->isMechUnit())
    {
        if (GET_PLAYER(getOwnerINLINE()).getNumAvailableBonuses((BonusTypes)GC.getInfoTypeForString("BONUS_OIL")) < 1)
        {
            return false;
        }
    }

This goes in CvUnit.cpp under the CvUnit::canMove() function. It checks to see whether a civilization has oil, and if it does not, then all mechanized units (tanks, planes, modern ships...) cannot move.

This is far from perfect code, since there are so many little things you'd need to take into account, like the fact that ships can use oil OR uranium - this currently would keep them from moving with no oil even if you have uranium. But I think people will get some use out of it. :)
 
Actually, I don't think you want to use the numavailablebonuses function. use the "hasbonus" function because I think the other one is used for trading to find out if you have resources available to trade.
 
Actually, I don't think you want to use the numavailablebonuses function. use the "hasbonus" function because I think the other one is used for trading to find out if you have resources available to trade.

I think that's what he wanted. You see, if you use "hasbonus" and you only have one supply, and you trade it away, then numavailable returns zero. At least, that was my experience. It worked when only one oil source was connected, and if it used only the tradeable resources, then it would not have worked.
 
My very first SDK mod
This goes in CvUnit.cpp as part of void CvUnit::doCommand

Code:
void CvUnit::doCommand(CommandTypes eCommand, int iData1, int iData2)
{
	CvUnit* pUnit;
	//Master's Mod
	CvCity* pCity;
	int smallUnitClassList [] = {GC.getInfoTypeForString("UNITCLASS_SCOUT"), GC.getInfoTypeForString("UNITCLASS_SPY"), GC.getInfoTypeForString("UNITCLASS_EXPLORER"), GC.getInfoTypeForString("UNITCLASS_EXECUTIVE_1"), GC.getInfoTypeForString("UNITCLASS_EXECUTIVE_2"), GC.getInfoTypeForString("UNITCLASS_EXECUTIVE_3"), GC.getInfoTypeForString("UNITCLASS_EXECUTIVE_4"), GC.getInfoTypeForString("UNITCLASS_EXECUTIVE_5"), GC.getInfoTypeForString("UNITCLASS_EXECUTIVE_6"), GC.getInfoTypeForString("UNITCLASS_EXECUTIVE_7"), GC.getInfoTypeForString("UNITCLASS_JEWISH_MISSIONARY"), GC.getInfoTypeForString("UNITCLASS_CHRISTIAN_MISSIONARY"), GC.getInfoTypeForString("UNITCLASS_ISLAMIC_MISSIONARY"), GC.getInfoTypeForString("UNITCLASS_HINDU_MISSIONARY"), GC.getInfoTypeForString("UNITCLASS_BUDDHIST_MISSIONARY"), GC.getInfoTypeForString("UNITCLASS_CONFUCIAN_MISSIONARY"),GC.getInfoTypeForString("UNITCLASS_WORKBOAT")};
	int i = 0;
	bool small = false;
	//end Master's Mod
	bool bCycle;

	bCycle = false;

	FAssert(getOwnerINLINE() != NO_PLAYER);

	if (canDoCommand(eCommand, iData1, iData2))
	{
		switch (eCommand)
		{
		case COMMAND_PROMOTION:
			promote((PromotionTypes)iData1, iData2);
			break;

		case COMMAND_UPGRADE:
			upgrade((UnitTypes)iData1);
			bCycle = true;
			break;

		case COMMAND_AUTOMATE:
			automate((AutomateTypes)iData1);
			bCycle = true;
			break;

		case COMMAND_WAKE:
			getGroup()->setActivityType(ACTIVITY_AWAKE);
			break;

		case COMMAND_CANCEL:
			getGroup()->popMission();
			break;

		case COMMAND_CANCEL_ALL:
			getGroup()->clearMissionQueue();
			break;

		case COMMAND_STOP_AUTOMATION:
			getGroup()->setAutomateType(NO_AUTOMATE);
			break;

		case COMMAND_DELETE:
			scrap();
			//Master's Mod
			
			for (i=0; i<17; i++)
			{
				if (GC.getUnitInfo(getUnitType()).getUnitClassType() == smallUnitClassList [i])
				{
					small = true;
					continue;
				}
			}
					
			pCity = GC.getMapINLINE().findCity(getX_INLINE(), getY_INLINE(), getOwnerINLINE(), NO_TEAM, false, false);

			if ((pCity != NULL) && !small)
			{
				pCity->changePopulation(1);
			}
			
			//end Master's Mod
			bCycle = true;
			break;

What it does:
Fairly obvious, if you disband a unit inside a city it adds 1 population point.

Edit: added some more code to check whether the unit is what I have called a 'small' unitclass (i.e. being small enough that it would not be a significant population boost) also added code so that population is added to the nearest city rather than having to be inside a city (thanks to xienwolf for that piece of code)

It's really designed to go with a similar function which subtracts a pop point when a unit is built
 
But count the lines to do the same stuff in C++ and in python, and you will see the difference...

For clarification,


The traditional "Hello, World!" statement often used in programming demonstrations:
(And the newline character, since that is used often)
In c++:

Code:
#include <iostream.h>
using namespace std;
void main() //Some IDE's use int main()
{
cout << "Hello, World!\n";
}

In python (3.1):

Code:
print('Hello, World!\n')

Now, a calculator that will do basic addition:
In c++:

Code:
#include <iostream.h>
using namespace std;
void main()
{
int a, b, c;
cout << "Please enter two integers.\n";
cin >> a;
cin >> b;
c = a + b;
cout << "The sum of your numbers is " << c << '\n';
}

In python:

Code:
a = int(input('Enter an integer.'))
b = int(input('Enter another integer.'))
c = a + b
print('The sum of your numbers is ', c)

A calculator that will let you choose what operation to do:
in c++:

Code:
#include <iostream.h>
using namespace std;
void main()
int a, b, c, d;
cout << "Please enter two integers.\n";
cin >> a;
cin >> b;
cout << "Enter 1 to perform addition, 2 for subtraction, 3 for multiplication and 4 for division.\n";
cin >> c;
if(c == 1)
{
     d = a + b;
     cout << d << '\n';
}
if(c == 2)
{
     d = a - b;
     cout << d << '\n';
}
if(c == 3)
{
     d = a * b
     cout << d << '\n';
}
if(c == 4)
{
     d = a/b;
     cout << d << '\n';
}
}

In python:

Code:
a = int(input('Enter an integer'))
b = int(input('Enter another integer'))
c = int(input('What operation would you like to perform?  Enter 1 for addition, 2 for subtraction, 3 for multiplication, 4 for division.'))
if c == 1:
    d = a + b
    print(d)
if c == 2:
    d = a - b
    print(d)
if c == 3:
    d = a * b
    print(d)
if c == 4:
    d = a/b
    print(d)

Much shorter in Python.
 
Back
Top Bottom