civ editor11
Ruler
Is the land transport able to load up onto a sea transport. I believe you could fix this by adding a new special unit type called transport or something so they can't load into transports.
As an aside, I don't like having Gunships carry units. They are powerful because they are small and nimble and all teeth. I would prefer to see a weaker Transport Chopper that must be defended by Gunships or other more powerful units.
So, how do you all feel about the potential additions? Let me know if you want them and (if there is enough demand) I'll do it. I'm thinking that the UNITAI_MISSILE_CARRIER_LAND would be the easier of the two.
Regarding the unload/attack/load problem...
The collateral damage issue must be specifically addressed for sea transports because some vessels cause it but probably don't damage the units inside Transports (I haven't tested this, but it makes sense). I would think the transport vehicle is the one that takes the damage, and if it dies so does its cargo.
As an aside, I don't like having Gunships carry units. They are powerful because they are small and nimble and all teeth. I would prefer to see a weaker Transport Chopper that must be defended by Gunships or other more powerful units.
I would also not like to see units onboard a land transport be able to take actions outside the vehicle without disembarking and becoming vulnerable.
...I do not imagine that this logic will apply to land transports. So new code will be needed to help the AI decide to build land transports.
I guess it is clear from all the questions that this is not "done, just need to merge into other mods", but rather, "an interesting starting point".
What I get from your first point is that I need to make a second assault mission and attach it to UNITAI_ASSAULT_LAND the way that the original assault mission is attached to UNITAI_ASSAULT_SEA.
void CvUnitAI::AI_assaultLandMove()
{
PROFILE_FUNC();
FAAssert(AI_getUnitAIType() == UNITAI_ASSAULT_LAND);
bool bEmpty = !getGroup()->hasCargo();
if (bEmpty)
{
if (AI_anyAttack(1, 65))
{
return;
}
if (AI_anyAttack(1, 40))
{
return;
}
}
bool bAttack = false;
bool bLandWar = false;
int iTargetStackSize = std::max(4, 1 + (AI_stackOfDoomExtra()));
int iCargo = getGroup()->getCargo();
bool bFull = getGroup()->AI_isFull();
AreaAITypes eAreaAIType = area()->getAreaAIType(getTeam());
bLandWar = !isBarbarian() && ((eAreaAIType == AREAAI_OFFENSIVE) || (eAreaAIType == AREAAI_DEFENSIVE) || (eAreaAIType == AREAAI_MASSING));
if (eAreaAIType == AREAAI_ASSAULT)
{
if (iCargo >= iTargetStackSize)
{
bAttack = true;
}
}
if (!bAttack)
{
if (eAreaAIType == AREAAI_ASSAULT && iCargo > 0)
{
int iAttackers = GET_PLAYER(getOwnerINLINE()).AI_enemyTargetMissionAIs(MISSIONAI_ASSAULT_LAND, getGroup());
if (iAttackers >= iTargetStackSize)
{
if (bFull)
{
//Join the Attack
bAttack = true;
}
}
}
else if (GET_PLAYER(getOwnerINLINE()).AI_getPlotDanger(plot(), 2))
{
if (getGroup()->hasCargo())
{
getGroup()->unloadAll();
getGroup()->pushMission(MISSION_SKIP);
return;
}
}
else if (bLandWar)
{
if (bFull && (eAreaAIType != AREAAI_DEFENSIVE))
{
if (AI_assaultLandTransport(false))
{
return;
}
}
else if (iCargo > 0)
{
getGroup()->pushMission(MISSION_SKIP);
return;
}
}
else if (GET_PLAYER(getOwnerINLINE()).AI_unitTargetMissionAIs(this, MISSIONAI_LOAD_ASSAULT_LAND) > 0)
{
if (!bFull)
{
getGroup()->pushMission(MISSION_SKIP);
return;
}
}
else
{
if (!bLandWar && iCargo > 0)
{
if (AI_group(UNITAI_ASSAULT_LAND))
{
return;
}
}
}
}
if (plot()->getTeam() == getTeam())
{
if ((iCargo == 0) && getGroup()->getNumUnits() > 1)
{
getGroup()->AI_makeForceSeparate();
}
}
if (plot()->isOwned() && isEnemy(plot()->getTeam()))
{
if (iCargo == 0)
{
//if we just made a dropoff, pillage the tile if we can
if ((getGroup()->countNumUnitAIType(UNITAI_ATTACK) + getGroup()->countNumUnitAIType(UNITAI_RESERVE)) > 0)
{
bool bMissionPushed = false;
if (AI_pillageRange(1))
{
bMissionPushed = true;
}
CvSelectionGroup* pOldGroup = getGroup();
//Release any support units to finish the job.
getGroup()->AI_seperateAI(UNITAI_ATTACK);
getGroup()->AI_seperateAI(UNITAI_RESERVE);
if (pOldGroup == getGroup() && getUnitType() == UNITAI_ASSAULT_LAND)
{
if (AI_retreatToCity(true))
{
bMissionPushed = true;
}
}
if (bMissionPushed)
{
return;
}
}
}
}
if ((iCargo > iTargetStackSize) || bFull)
{
bAttack = true;
}
if (isBarbarian())
{
if(getGroup()->isFull())
{
if (AI_assaultLandTransport(false))
{
return;
}
}
else
{
if (AI_pickup(UNITAI_ATTACK_CITY))
{
return;
}
if (AI_pickup(UNITAI_ATTACK))
{
return;
}
}
}
else
{
bool bAttackBarbarian = false;
if (GET_TEAM(getTeam()).getAtWarCount(true) == 0)
{
bAttackBarbarian = true;
}
if (bAttack)
{
FAssert(getGroup()->hasCargo());
if (AI_assaultLandTransport(bAttackBarbarian))
{
return;
}
}
}
if (bFull)
{
if(AI_group(UNITAI_ASSAULT_LAND, -1 /*iMaxOwnUnitAI*/ -1, -1, true))
{
return;
}
}
else
{
if (AI_pickup(UNITAI_ATTACK_CITY))
{
return;
}
if (AI_pickup(UNITAI_ATTACK))
{
return;
}
if (AI_pickup(UNITAI_COUNTER))
{
return;
}
}
if (AI_retreatToCity(true))
{
return;
}
if (AI_retreatToCity())
{
return;
}
if (AI_safety())
{
return;
}
getGroup()->pushMission(MISSION_SKIP);
return;
}
void CvUnitAI::AI_escortLandMove()
{
PROFILE_FUNC();
if (AI_heal(30, 1))
{
return;
}
if (AI_anyAttack(1, 55))
{
return;
}
if (AI_group(UNITAI_MISSILE_CARRIER_LAND, -1, /*iMaxOwnUnitAI*/ 0, -1, /*bIgnoreFaster*/ true))
{
return;
}
if (AI_group(UNITAI_ASSAULT_LAND, -1, /*iMaxOwnUnitAI*/ 0, -1, /*bIgnoreFaster*/ true, false, false, /*iMaxPath*/ 3))
{
return;
}
if (AI_heal(50, 3))
{
return;
}
if (AI_pillageRange(2))
{
return;
}
if (AI_group(UNITAI_MISSILE_CARRIER_LAND, 1, 1, true))
{
return;
}
if (AI_group(UNITAI_ASSAULT_LAND, 1, /*iMaxOwnUnitAI*/ 0, /*iMinUnitAI*/ -1, /*bIgnoreFaster*/ true))
{
return;
}
if (AI_group(UNITAI_ASSAULT_LAND, -1, /*iMaxOwnUnitAI*/ 2, /*iMinUnitAI*/ -1, /*bIgnoreFaster*/ true))
{
return;
}
if (AI_group(UNITAI_MISSILE_CARRIER_LAND, -1, /*iMaxOwnUnitAI*/ 2, /*iMinUnitAI*/ -1, /*bIgnoreFaster*/ true))
{
return;
}
if (AI_group(UNITAI_ASSAULT_LAND, -1, /*iMaxOwnUnitAI*/ 4, /*iMinUnitAI*/ -1, /*bIgnoreFaster*/ true))
{
return;
}
if (AI_heal())
{
return;
}
if (AI_travelToUpgradeCity())
{
return;
}
if (AI_retreatToCity())
{
return;
}
if (AI_safety())
{
return;
}
getGroup()->pushMission(MISSION_SKIP);
return;
}
void CvUnitAI::AI_raiderMove()
{
PROFILE_FUNC();
if (plot()->isCity())
{
if (AI_heal())
{
return;
}
}
if (plot()->isOwned() && (plot()->getTeam() == getTeam()))
{
AreaAITypes eAreaAIType = area()->getAreaAIType(getTeam());
bLandWar = !isBarbarian() && ((eAreaAIType == AREAAI_OFFENSIVE) || (eAreaAIType == AREAAI_DEFENSIVE) || (eAreaAIType == AREAAI_MASSING));
if ((((AI_getBirthmark() / 8) % 2) == 0) && (bLandWar))
{
bool bIsStealth = (getInvisibleType() != NO_INVISIBLE);
if (bIsStealth)
{
pForeignSoil = ((plot()->getOwnerINLINE() != getOwnerINLINE()) && (!plot->isImpassable())
if (pForeignSoil->getNumUnrevealedTiles() > 0)
{
if (GET_PLAYER(getOwnerINLINE()).AI_areaMissionAIs(pForeignSoil, MISSIONAI_EXPLORE, getGroup()) < (GET_PLAYER(getOwnerINLINE()).AI_neededExplorers(pForeignSoil)))
{
if (AI_exploreRange(2))
{
return;
}
}
}
}
if (AI_shadow(UNITAI_ASSAULT_LAND, 1, 50)
{
return;
}
}
}
if (plot()->isOwned() && (isEnemy(plot()->getTeam())))
{
if (bIsStealth)
{
if (AI_pillageRange(4))
{
return;
}
if (AI_pillageRange(3))
{
return;
}
if (AI_pillageRange(2))
{
return;
}
if (AI_pillageRange(1))
{
return;
}
else
{
if (AI_anyAttack(2, 25))
{
return;
}
if (AI_pillageRange(4))
{
return;
}
if (AI_pillageRange(3))
{
return;
}
if (AI_pillageRange(2))
{
return;
}
if (AI_pillageRange(1))
{
return;
}
}
}
if (AI_retreatToCity())
{
return;
}
if (AI_safety())
{
return;
}
getGroup()->pushMission(MISSION_SKIP)'
return;
}
void CvUnitAI::AI_missileCarrierLandMove()
{
bool bIsProtected = (getGroup()->countNumUnitAIType(UNITAI_ATTACK) + getGroup()->countNumUnitAIType(UNITAI_ESCORT_LAND)) > 0);
if ((plot()->isCity() && plot()->getTeam() == getTeam()) || (bIsProtected))
{
if (AI_heal())
{
return;
}
}
if (((plot()->getTeam() != getTeam()) && getGroup()->hasCargo()) || getGroup()->AI_isFull())
{
if (bIsProtected)
{
if (AI_carrierLandTransport())
{
return;
}
if (AI_shadow(UNITAI_ASSAULT_LAND, 1, 50))
{
return;
}
}
}
if (AI_retreatToCity())
{
return;
}
getGroup()->pushMission(MISSION_SKIP);
}
UNITAI_RAIDER <- can this be used for units which can attack without declaring war? or will they pillage only?