PushMission() in Python and SDK

Padmewan

King
Joined
Nov 26, 2003
Messages
748
Location
Planet
I'm trying to override some default AI behaviors (we need suicide pillagers) and am seeking documentation for the PushMission method of CyUnit.

In Python, it is defined as

Code:
VOID pushMission (MissionType eMission, INT iData1, INT iData2, INT iFlags, BOOL bAppend, BOOL bManual, MissionAIType eMissionAI, CyPlot pMissionAIPlot, CyUnit pMissionAIUnit)

So far as I can tell:

eMission = one of the enumerated missions, e.g. MISSION_PILLAGE
iData1 = (no idea)
iData2 = (no idea)
iFlags = (no idea)
bAppend = Add this to the end of the existing mission queue (?)
bManual = Switch this unit to manual control
eMissionAI = Some second set of mission types, often requiring participation of another unit, e.g. MISSIONAI_LOAD_SETTLER
pMissionAIPlot = Plot targeted in eMission or eMissionAI (?)
pMissionAIUnit = Unit targeted in eMission or eMissionAI (?)

Now I've spooled through the SDK (the implementation seems to be in CvSelectionGroup.cpp), and at least as far as I can comprehend, not every parameter is used for every mission. It seems that iData1 and iData2 are used as follows:

MISSION_MOVE_TO, MISSION_ROUTE_TO:
iData1 = X
iData2 = Y

MISSION_MOVE_TO_UNIT:
iData1 = Civ ID
iData2 = Unit ID

It looks like MISSION_PILLAGE uses none of these parameters. What data do I pass, then, or do I just skip all of them and do pushMission(MISSION_PILLAGE) ?
 
Padmewan said:
I'm trying to override some default AI behaviors (we need suicide pillagers) and am seeking documentation for the PushMission method of CyUnit.

In Python, it is defined as

Code:
VOID pushMission (MissionType eMission, INT iData1, INT iData2, INT iFlags, BOOL bAppend, BOOL bManual, MissionAIType eMissionAI, CyPlot pMissionAIPlot, CyUnit pMissionAIUnit)

So far as I can tell:

eMission = one of the enumerated missions, e.g. MISSION_PILLAGE
iData1 = (no idea)
iData2 = (no idea)
iFlags = (no idea)
bAppend = Add this to the end of the existing mission queue (?)
bManual = Switch this unit to manual control
eMissionAI = Some second set of mission types, often requiring participation of another unit, e.g. MISSIONAI_LOAD_SETTLER
pMissionAIPlot = Plot targeted in eMission or eMissionAI (?)
pMissionAIUnit = Unit targeted in eMission or eMissionAI (?)

Now I've spooled through the SDK (the implementation seems to be in CvSelectionGroup.cpp), and at least as far as I can comprehend, not every parameter is used for every mission. It seems that iData1 and iData2 are used as follows:

MISSION_MOVE_TO, MISSION_ROUTE_TO:
iData1 = X
iData2 = Y

MISSION_MOVE_TO_UNIT:
iData1 = Civ ID
iData2 = Unit ID

It looks like MISSION_PILLAGE uses none of these parameters. What data do I pass, then, or do I just skip all of them and do pushMission(MISSION_PILLAGE) ?

I don't think you can just do pushMission(MISSION_PILLAGE), since Python doesn't have access to the default parameter values. You need to supply a value for each argument, even if it's "junk" data. For any value not used, you can always check at the default value in the CvSelectionGroup file and use those, with the correct python-equivalent code of course.

From CvSelectionGroup.h:

Code:
void pushMission(MissionTypes eMission, int iData1 = -1, int iData2 = -1, int iFlags = 0, bool bAppend = false, bool bManual = false, MissionAITypes eMissionAI = NO_MISSIONAI, CvPlot* pMissionAIPlot = NULL, CvUnit* pMissionAIUnit = NULL);		// Exposed to Python

Thus, it's completely legitimate to do:

Code:
pUnit.getGroup().pushMission(MissionTypes.MISSION_PILLAGE, -1, -1, 0, False, False, MissionAITypes.NO_MISSIONAI, NONE, NONE)
 
Hold on, let me back up a second here. My main question here is: how do you get units to do things? Is this the right (or only) way?

First of all, I am calling this from the AI_unitUpdate function of the CvGameInterface. Is that the right place to override the default AI? (From what I could figure out in the SDK, it should be).

Second, turns out it's SelectionGroups that can pushMission, not Units. I changed my call to:

Code:
pUnit.getGroup().pushMission(gc.getInfoTypeForString('MISSION_PILLAGE'), -1, -1, 0, False, False, 0, pUnit.plot(), pUnit)

but I still get this error:
Code:
ArgumentError: Python argument types in
    CySelectionGroup.pushMission(CySelectionGroup, int, int, int, int, bool, bool, int, CyPlot, CyUnit)
did not match C++ signature:
    pushMission(class CySelectionGroup {lvalue}, enum MissionTypes, int, int, int, bool, bool, enum MissionAITypes, class CyPlot *, class CyUnit *)

I tried using the CyUnit.NotifyEntity(MissionType) method, but that causes the unit to do nothing.

How do I get my units to "do stuff"??? Help!
 
Padmewan said:
Hold on, let me back up a second here. My main question here is: how do you get units to do things? Is this the right (or only) way?

First of all, I am calling this from the AI_unitUpdate function of the CvGameInterface. Is that the right place to override the default AI? (From what I could figure out in the SDK, it should be).

Second, turns out it's SelectionGroups that can pushMission, not Units. I changed my call to:

Code:
pUnit.getGroup().pushMission(gc.getInfoTypeForString('MISSION_PILLAGE'), -1, -1, 0, False, False, 0, pUnit.plot(), pUnit)

but I still get this error:
Code:
ArgumentError: Python argument types in
    CySelectionGroup.pushMission(CySelectionGroup, int, int, int, int, bool, bool, int, CyPlot, CyUnit)
did not match C++ signature:
    pushMission(class CySelectionGroup {lvalue}, enum MissionTypes, int, int, int, bool, bool, enum MissionAITypes, class CyPlot *, class CyUnit *)

I tried using the CyUnit.NotifyEntity(MissionType) method, but that causes the unit to do nothing.

How do I get my units to "do stuff"??? Help!

Yes, you're correct in that using pushMission is the correct way to make them "do stuff". As for making the AI do stuff, as long as you keep setting bManual to False, the unt should always be automated until you make it not so, either in code (using setAutomateType(NO_AUTOMATE) or until the user cancels the automation. Second, you're also correct, the mission gets pushed to groups, not units (I've fixed my code above). Sorry about that :P

The error you're getting is because the first argument needs to be an enumerated type. You need to use MissionTypes.MISSION_PILLAGE for this argument. getInfoTypeForString will return the CvMissionInfo class for the pillage mission, not the enumerated value that the function is looking for.
 
Gerikes said:
The error you're getting is because the first argument needs to be an enumerated type. You need to use MissionTypes.MISSION_PILLAGE for this argument. getInfoTypeForString will return the CvMissionInfo class for the pillage mission, not the enumerated value that the function is looking for.
Aha! Thanks Gerikes. I thought that the interface would treat an integer as an ENUM but now I am set straight. Do I need a new INCLUDE file to reference the MissionTypes ENUM?

I'll set bManual to TRUE though I guess it doesn't matter as the Python code should take care of all possibilities.

###

btw, Having investigated the SDK further, "NotifyEntity" tells the unit to perform a particular animation. I spent half an hour searching for where NotifyEntity was defined and couldn't; after seeing that NotifyEntity is called AFTER the actual thing to be done, it makes sense that it's a graphics engine thing beyond our reach.

Thanks again Gerikes. Back on track...
 
Padmewan said:
Aha! Thanks Gerikes. I thought that the interface would treat an integer as an ENUM but now I am set straight. Do I need a new INCLUDE file to reference the MissionTypes ENUM?

Do you mean a new import in python? I think that's covered for you in CvPythonExtensions, which is imported in from what I've seen every python file anyway.
 
In case it's not readily obvious to others trying to unravel the secrets of making units move around, you order an attack by ordering the unit to move into an occupied space.

Also, if you order a unit to move to space but there is no viable path in between, the unit will just do nothing. This is true if, for example, there are enemy units between here and there -- the unit won't auto-attack between here and there (unless there's a command I'm missing).
 
Back
Top Bottom