PushMission() in Python and SDK

Discussion in 'Civ4 - Creation & Customization' started by Padmewan, May 27, 2006.

  1. Padmewan

    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) ?
     
  2. Gerikes

    Gerikes User of Run-on Sentences.

    Joined:
    Jul 26, 2005
    Messages:
    1,753
    Location:
    Massachusetts
    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)
    
     
  3. Padmewan

    Padmewan King

    Joined:
    Nov 26, 2003
    Messages:
    748
    Location:
    Planet
    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!
     
  4. Gerikes

    Gerikes User of Run-on Sentences.

    Joined:
    Jul 26, 2005
    Messages:
    1,753
    Location:
    Massachusetts
    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.
     
  5. Padmewan

    Padmewan King

    Joined:
    Nov 26, 2003
    Messages:
    748
    Location:
    Planet
    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...
     
  6. Gerikes

    Gerikes User of Run-on Sentences.

    Joined:
    Jul 26, 2005
    Messages:
    1,753
    Location:
    Massachusetts
    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.
     
  7. Padmewan

    Padmewan King

    Joined:
    Nov 26, 2003
    Messages:
    748
    Location:
    Planet
    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).
     

Share This Page