Problem with Python function calls in the SDK

Leoreth

Blue Period
Moderator
Joined
Aug 23, 2009
Messages
37,075
Location
東京藝術大学
Today was the first time I had to call a Python function in the SDK. While I think I've understood the general principle correctly, there still seems to be something wrong with my code. The desired feature is part of my RFC modmod, but I hope I can present my problem without tackling RFC-specific aspects.

I'm trying to edit the CvGameTextMgr.cpp file to display a tile's stability in the mouseover text (box in the left bottom corner that displays terrain etc.). That involves checks if the current plot is within the core and normal area of the active player's civ. The problem is, currently it returns "Core Area" for every land plot, whether it is really in the core area or not. It seems that the respective Python functions that determine if a tile is in Normal/Core don't return anything to the SDK at all. Best take a look at the code now:
Code:
            long result = -1;
            long result2 = -1;
	    CyArgsList argsList;
	    argsList.add(pPlot->getX());
	    argsList.add(pPlot->getY());
	    argsList.add(GC.getGameINLINE().getActivePlayer());
	    gDLL->getPythonIFace()->callFunction(PYRFCUtilsModule, "isCorePlot", argsList.makeFunctionArgs(), &result);
	    long iCore = (long)result;

	    if (pPlot->getPlotType() == PLOT_OCEAN)
	    {
	        szString.append("Ocean");
	    }
	    else if (iCore != 0)
	    {
	        szString.append("Core Area");
	    }
	    else
	    {
	        int iSettlerValue = GET_PLAYER(GC.getGameINLINE().getActivePlayer()).getSettlersMaps(pPlot->getX(), pPlot->getY());
	        CyArgsList argsList2;
	        argsList2.add(pPlot->getX());
                argsList2.add(pPlot->getY());
                argsList2.add(GC.getGameINLINE().getActivePlayer());
                gDLL->getPythonIFace()->callFunction(PYRFCUtilsModule, "isNormalPlot", argsList2.makeFunctionArgs(), &result2);
                long iNormal = (long)result2;

                if (iNormal == 1 && iSettlerValue >= 400)
                {
                    szString.append("Peripheral Area");
                }
                else
                {
                    szString.append("Foreign Area");
                }
	    }

        szString.append(NEWLINE);
The two Python functions I call are defined in RFCUtils.py, which is of course already included into CvDefines.h.
Code:
    def isCorePlot(self, x, y, iCiv):
        if (x >= con.tCoreAreasTL[iCiv][0] and x <= con.tCoreAreasBR[iCiv][0] and y >= con.tCoreAreasTL[iCiv][1] and y <= con.tCoreAreasBR[iCiv][1]): # and not (x, y) in con.tExceptions[iCiv]):
            return 1
        else:
            return 0

    def isNormalPlot(self, x, y, iCiv):
        if (x >= con.tNormalAreasTL[iCiv][0] and x <= con.tNormalAreasBR[iCiv][0] and y >= con.tNormalAreasTL[iCiv][1] and y <= con.tNormalAreasBR[iCiv][1]): # and not (x, y) in con.tNormalAreasSubtract[iCiv]):
            return 1
        else:
            return 0
From my tests I've found out that the value of "result" always stays -1, although the functions can only return 0 or 1. This is why I guess there's an error with the function call itself. Does anybody see my mistake?

Thanks in advance :)
 
I'm no expert on the subject but everything looks OK to me. Are the Pythons function being called? If you print something from the Python functions, is it displayed? If they are not being called, could the problem be with PYRFCUtilsModule not being defined to the correct value? I only bring this up because everything else appears OK.
 
When calling functions in Python from C++, all of the args are received in a single list parameter. Also, those functions appear to be defined in a class which makes them inaccessible from the SDK. You need some facades that a) grab a reference the object that has those methods and b) explodes the parameters.

For example, say those functions are on the class RFCUtils which has a single instance stored in a global variable called gUtils.

Code:
class RFCUtils:
    def isCorePlot(self, x, y, iCiv):
        ...
    def isNormalPlot(self, x, y, iCiv):
        ...
    ...

gUtils = RFCUtils()

In that same module add

Code:
def isCorePlot(argsList):
    return gUtils.isCorePlot(*argsList)

def isNormalPlot(argsList):
    return gUtils.isNormalPlot(*argsList)
 
You're absolutely right. A fellow modder in the RFC subfora already pointed me out to a better Python file to move my functions to, and after I also changed everything to one parameter it worked fine.

Thanks to everyone :)
 
Top Bottom