Allowing the AI to capture Units

deanej

Deity
Joined
Apr 8, 2006
Messages
4,859
Location
New York State
How can I make it so that the AI will capture units, rather than destroying them? I went into CvUnit.cpp and found some code that looks relevant, commented some stuff out, but the AI still won't capture units. What else do I need to do?
Code:
	//Star Trek - AI capture units?
	if ((eCapturingPlayer != NO_PLAYER) && (eCaptureUnitType != NO_UNIT))// && !(GET_PLAYER(eCapturingPlayer).isBarbarian()))
	{
		//if (GET_PLAYER(eCapturingPlayer).isHuman() || GET_PLAYER(eCapturingPlayer).AI_captureUnit(eCaptureUnitType, pPlot) || 0 == GC.getDefineINT("AI_CAN_DISBAND_UNITS"))
		//{
			CvUnit* pkCapturedUnit = GET_PLAYER(eCapturingPlayer).initUnit(eCaptureUnitType, pPlot->getX_INLINE(), pPlot->getY_INLINE());

			if (pkCapturedUnit != NULL)
			{
				szBuffer = gDLL->getText("TXT_KEY_MISC_YOU_CAPTURED_UNIT", GC.getUnitInfo(eCaptureUnitType).getTextKeyWide());
				gDLL->getInterfaceIFace()->addMessage(eCapturingPlayer, true, GC.getEVENT_MESSAGE_TIME(), szBuffer, "AS2D_UNITCAPTURE", MESSAGE_TYPE_INFO, pkCapturedUnit->getButton(), (ColorTypes)GC.getInfoTypeForString("COLOR_GREEN"), pPlot->getX_INLINE(), pPlot->getY_INLINE());

				// Add a captured mission
				CvMissionDefinition kMission;
				kMission.setMissionTime(GC.getMissionInfo(MISSION_CAPTURED).getTime() * gDLL->getSecsPerTurn());
				kMission.setUnit(BATTLE_UNIT_ATTACKER, pkCapturedUnit);
				kMission.setUnit(BATTLE_UNIT_DEFENDER, NULL);
				kMission.setPlot(pPlot);
				kMission.setMissionType(MISSION_CAPTURED);
				gDLL->getEntityIFace()->AddMission(&kMission);

				pkCapturedUnit->finishMoves();

				if (!GET_PLAYER(eCapturingPlayer).isHuman())
				{
					CvPlot* pPlot = pkCapturedUnit->plot();
					if (pPlot && !pPlot->isCity(false))
					{
						if (GET_PLAYER(eCapturingPlayer).AI_getPlotDanger(pPlot) && GC.getDefineINT("AI_CAN_DISBAND_UNITS"))
						{
							pkCapturedUnit->kill(false);
						}
					}
				}
			}
		//}
	}
 
A number of people have used the onCombatResult python hook to write routines which generate a slave unit upon a combat loss. You could use the same approach to make a copy of the losing unit (including all the promotions, using pUnit.convert()) and give it to the victor. What if the losing unit is a UU which is not available to the winner civ?
 
Is eCaptureUnitType being set to a valid unit (not NO_UNIT) in the code before this block when it's an AI?

Try adding some logging or building a Debug DLL and stepping through the code.
 
I'm afraid I don't know anything about logging and debugging the SDK. Is there some other way I can tell if it's been assigned to NO_UNIT? This line might mean something:
Code:
eCaptureUnitType = ((eCapturingPlayer != NO_PLAYER) ? getCaptureUnitType(GET_PLAYER(eCapturingPlayer).getCivilizationType()) : NO_UNIT);
but I have no idea what it actually does.

@davidlallen: I'm just trying to make it so that the AI can capture units like the player can - currently, the AI will destroy any units it kills, even if they have a capture unitclass set in the XML. Since Starbase capturing is a feature of my mod, I need to change this behavior (which was implemented to prevent the player from recapturing workers they lost to an enemy). I don't see why I should have to expand the python bloat on my mod just to do something that should just take changing one or two lines of the DLL, tops (I'm assuming that there is simply a block that I can remove; is this not the case?).
 
Two things. The second is related to the probem you have now that you commented out that if statement.

1) In the if statment you commented out is the condition "0 == GC.getDefineINT("AI_CAN_DISBAND_UNITS")".

If you set AI_CAN_DISBAND_UNITS to 0 instead of the default value of 1 it should run the code in the if block. It's in GlobalDefines.xml so put it in the mods version of that (or AltGlobalDefines.xml, if you're using that to do the global define overrides). This may not be the best plan - it might never disband a unit if you do this.

The other option (well, other than commenting out the if like you did) is to find out how AI_captureUnit works and see why it would be returning false, if it is.

But this may not be a problem.

2) Note the other if statement near the end of the statement block for the first one. It is checking to see if the player is not human and, if not, then checking various other things (including the already mentioned AI_CAN_DISBAND_UNITS). If all that works out to be true then the captured unit is just killed.

This is presumably always running in the "commented out if statement" version you posted.

The key to changing the "kill the captured unit" behavior is aparently the AI_getPlotDanger function, unless you just comment out this entire if block...
 
Top Bottom