Searching the Units after I Finish a Project in a City

topsecret

Believer
Supporter
Joined
Feb 11, 2010
Messages
5,972
Location
At the Foot of the Cross
Hope someone sees this. :)

I am trying to code <PromotionStrongestUnit> for ProjectInfos. I've got it reading the XML just fine, but I want to search the units in the city that completed it and give the promotion to that unit (it's a one time promotion). If I can't find a unit there, I give it to the closest one this player owns.

I'm completely at a loss. I thought BuildingInfos in CvCity would help but it changes the free promotion count and that's not the same.

Could someone give me some pointers or show me a post/guide that would help me? I don't know enough about the DLL to know what to do next.
 
You can do it in the CvCity:: popOrder() function. Insert your code at INSERT_YOUR_CODE_HERE.

Spoiler :
Code:
void CvCity::popOrder(int iNum, bool bFinish, bool bChoose)
{
    ...
    switch (pOrderNode->m_data.eOrderType)
    {
    case ORDER_TRAIN:
        ...
    case ORDER_CONSTRUCT:
        ...
    case ORDER_CREATE:
        eCreateProject = ((ProjectTypes)(pOrderNode->m_data.iData1));
        GET_TEAM(getTeam()).changeProjectMaking(eCreateProject, -1);
        if (bFinish)
        {
            // Event reported to Python before the project is built, so that we can show the movie before awarding free techs, for example
            CvEventReporter::getInstance().projectBuilt(this, eCreateProject);
            GET_TEAM(getTeam()).changeProjectCount(eCreateProject, 1);

            INSERT_YOUR_CODE_HERE

            if (GC.getProjectInfo(eCreateProject).isSpaceship())
            {
                bool needsArtType = true;
                VictoryTypes eVictory = (VictoryTypes)GC.getProjectInfo(eCreateProject).getVictoryPrereq();
                if (NO_VICTORY != eVictory && GET_TEAM(getTeam()).canLaunch(eVictory))
                {
                    if (isHuman())
                    {
                        CvPopupInfo* pInfo = NULL;
                        /*
                        if (GC.getGameINLINE().isNetworkMultiPlayer())
                        {
                            pInfo = new CvPopupInfo(BUTTONPOPUP_LAUNCH, GC.getProjectInfo(eCreateProject).getVictoryPrereq());
                        }
                        else
                        {
                            pInfo = new CvPopupInfo(BUTTONPOPUP_PYTHON_SCREEN, eCreateProject);
                            pInfo->setText(L"showSpaceShip");
                            needsArtType = false;
                        }
                        */
                        pInfo = new CvPopupInfo(BUTTONPOPUP_LAUNCH, GC.getProjectInfo(eCreateProject).getVictoryPrereq());
                        gDLL->getInterfaceIFace()->addPopup(pInfo, getOwnerINLINE());
                    }
                    else
                    {
                        GET_PLAYER(getOwnerINLINE()).AI_launch(eVictory);
                    }
                }
                /*
                else
                {
                    //show the spaceship progress
                    if(isHuman())
                    {
                        if(!GC.getGameINLINE().isNetworkMultiPlayer())
                        {
                            CvPopupInfo* pInfo = new CvPopupInfo(BUTTONPOPUP_PYTHON_SCREEN, eCreateProject);
                            pInfo->setText(L"showSpaceShip");
                            gDLL->getInterfaceIFace()->addPopup(pInfo, getOwnerINLINE());
                            needsArtType = false;
                        }
                    }
                }
                */
                if(needsArtType)
                {
                    int defaultArtType = GET_TEAM(getTeam()).getProjectDefaultArtType(eCreateProject);
                    int projectCount = GET_TEAM(getTeam()).getProjectCount(eCreateProject);
                    GET_TEAM(getTeam()).setProjectArtType(eCreateProject, projectCount - 1, defaultArtType);
                }
            }
            ...
        }
        break;
    ...
}


Here is some (unfinished) code you coud use as a template to determine the strongest unit in the city.

(The code I based this on had pUnit->getOwner() == getOwner(), which makes sure that only the units of the creator of the project are used. I assume that you also want this, so I kept it in.)

Spoiler :
Code:
    CvUnit* bestunit;
    CvUnit* pUnit;
    for (int i = 0; i < plot()->getNumUnits(); i++)
    {
        pUnit = plot()->getUnitByIndex(i);
        if (pUnit->getOwner() == getOwner() && pUnit->FUNCTION_TO_DETERMINE_STRENGTH > bestunit->FUNCTION_TO_DETERMINE_STRENGTH)
        {
            bestunit = pUnit;
        }
    }
    bestunit->promote();

If you want the closest unit, you could do something like this. (The code is not finished, but you can use it as a template)

Spoiler :
Code:
    CvUnit* closestunit;
    int mindistance;
    for (CvUnit* pLoopUnit = firstUnit(&iLoop); pLoopUnit != NULL; pLoopUnit = nextUnit(&iLoop)) // loop over the units of the player
        {
            iDistance = plotDistance(CvUnit->getX_INLINE(), CvUnit->getY_INLINE(), getX(), getY()))
        }
        if (distance < mindistance)
        {
            closestunit = pLoopUnit
            mindistance = distance
        }
        closestunit->promote();
    }
 
Last edited:
You can do it in the CvCity:: popOrder() function. Insert your code at INSERT_YOUR_CODE_HERE.

Spoiler :
Code:
void CvCity::popOrder(int iNum, bool bFinish, bool bChoose)
{
    ...
    switch (pOrderNode->m_data.eOrderType)
    {
    case ORDER_TRAIN:
        ...
    case ORDER_CONSTRUCT:
        ...
    case ORDER_CREATE:
        eCreateProject = ((ProjectTypes)(pOrderNode->m_data.iData1));
        GET_TEAM(getTeam()).changeProjectMaking(eCreateProject, -1);
        if (bFinish)
        {
            // Event reported to Python before the project is built, so that we can show the movie before awarding free techs, for example
            CvEventReporter::getInstance().projectBuilt(this, eCreateProject);
            GET_TEAM(getTeam()).changeProjectCount(eCreateProject, 1);

            INSERT_YOUR_CODE_HERE

            if (GC.getProjectInfo(eCreateProject).isSpaceship())
            {
                bool needsArtType = true;
                VictoryTypes eVictory = (VictoryTypes)GC.getProjectInfo(eCreateProject).getVictoryPrereq();
                if (NO_VICTORY != eVictory && GET_TEAM(getTeam()).canLaunch(eVictory))
                {
                    if (isHuman())
                    {
                        CvPopupInfo* pInfo = NULL;
                        /*
                        if (GC.getGameINLINE().isNetworkMultiPlayer())
                        {
                            pInfo = new CvPopupInfo(BUTTONPOPUP_LAUNCH, GC.getProjectInfo(eCreateProject).getVictoryPrereq());
                        }
                        else
                        {
                            pInfo = new CvPopupInfo(BUTTONPOPUP_PYTHON_SCREEN, eCreateProject);
                            pInfo->setText(L"showSpaceShip");
                            needsArtType = false;
                        }
                        */
                        pInfo = new CvPopupInfo(BUTTONPOPUP_LAUNCH, GC.getProjectInfo(eCreateProject).getVictoryPrereq());
                        gDLL->getInterfaceIFace()->addPopup(pInfo, getOwnerINLINE());
                    }
                    else
                    {
                        GET_PLAYER(getOwnerINLINE()).AI_launch(eVictory);
                    }
                }
                /*
                else
                {
                    //show the spaceship progress
                    if(isHuman())
                    {
                        if(!GC.getGameINLINE().isNetworkMultiPlayer())
                        {
                            CvPopupInfo* pInfo = new CvPopupInfo(BUTTONPOPUP_PYTHON_SCREEN, eCreateProject);
                            pInfo->setText(L"showSpaceShip");
                            gDLL->getInterfaceIFace()->addPopup(pInfo, getOwnerINLINE());
                            needsArtType = false;
                        }
                    }
                }
                */
                if(needsArtType)
                {
                    int defaultArtType = GET_TEAM(getTeam()).getProjectDefaultArtType(eCreateProject);
                    int projectCount = GET_TEAM(getTeam()).getProjectCount(eCreateProject);
                    GET_TEAM(getTeam()).setProjectArtType(eCreateProject, projectCount - 1, defaultArtType);
                }
            }
            ...
        }
        break;
    ...
}


Here is some (unfinished) code you coud use as a template to determine the strongest unit in the city.

(The code I based this on had pUnit->getOwner() == getOwner(), which makes sure that only the units of the creator of the project are used. I assume that you also want this, so I kept it in.)

Spoiler :
Code:
    CvUnit* bestunit;
    CvUnit* pUnit;
    for (int i = 0; i < plot()->getNumUnits(); i++)
    {
        pUnit = plot()->getUnitByIndex(i);
        if (pUnit->getOwner() == getOwner() && pUnit->FUNCTION_TO_DETERMINE_STRENGTH > bestunit->FUNCTION_TO_DETERMINE_STRENGTH)
        {
            bestunit = pUnit;
        }
    }
    bestunit->promote();

If you want the closest unit, you could do something like this. (The code is not finished, but you can use it as a template)

Spoiler :
Code:
    CvUnit* closestunit;
    int mindistance;
    for (CvUnit* pLoopUnit = firstUnit(&iLoop); pLoopUnit != NULL; pLoopUnit = nextUnit(&iLoop)) // loop over the units of the player
        {
            iDistance = plotDistance(CvUnit->getX_INLINE(), CvUnit->getY_INLINE(), getX(), getY()))
        }
        if (distance < mindistance)
        {
            closestunit = pLoopUnit
            mindistance = distance
        }
        closestunit->promote();
    }
Thanks! I will let you know if it works out. I just needed a push in the right direction.
 
I got the first part to work. I decided to get rid of using the second part - what if the closest unit is a warrior? :lol: So I switched to a different solution: if there isn't a valid unit in the city, it does a free "draft" with no anger or population cost and adds the promotion to that unit. Now the AI will use it without having to add complex code to get it to consider the strength of the units in. It won't be perfect for the AI, but it works.
 
Top Bottom