CvUnit* CvUnit::airStrikeTarget(const CvPlot* pPlot) const
{
CvUnit* pDefender;
pDefender = pPlot->getBestDefender(NO_PLAYER, getOwnerINLINE(), this, true);
if (pDefender != NULL)
{
if (!pDefender->isDead())
{
if (pDefender->canDefend())
{
return pDefender;
}
}
}
return NULL;
}
bool CvUnit::canAirStrike(const CvPlot* pPlot) const
{
if (getDomainType() != DOMAIN_AIR)
{
return false;
}
if (!canAirAttack())
{
return false;
}
if (pPlot == plot())
{
return false;
}
if (!pPlot->isVisible(getTeam(), false))
{
return false;
}
if (plotDistance(getX_INLINE(), getY_INLINE(), pPlot->getX_INLINE(), pPlot->getY_INLINE()) > airRange())
{
return false;
}
if (airStrikeTarget(pPlot) == NULL)
{
return false;
}
return true;
}
bool CvUnit::airStrike(CvPlot* pPlot)
{
if (!canAirStrike(pPlot))
{
return false;
}
if (interceptTest(pPlot))
{
return false;
}
CvUnit* pDefender = airStrikeTarget(pPlot);
FAssert(pDefender != NULL);
FAssert(pDefender->canDefend());
setReconPlot(pPlot);
setMadeAttack(true);
changeMoves(GC.getMOVE_DENOMINATOR());
int iDamage = airCombatDamage(pDefender);
int iUnitDamage = std::max(pDefender->getDamage(), std::min((pDefender->getDamage() + iDamage), airCombatLimit()));
CvWString szBuffer = gDLL->getText("TXT_KEY_MISC_YOU_ARE_ATTACKED_BY_AIR", pDefender->getNameKey(), getNameKey(), -(((iUnitDamage - pDefender->getDamage()) * 100) / pDefender->maxHitPoints()));
gDLL->getInterfaceIFace()->addMessage(pDefender->getOwnerINLINE(), false, GC.getEVENT_MESSAGE_TIME(), szBuffer, "AS2D_AIR_ATTACK", MESSAGE_TYPE_INFO, getButton(), (ColorTypes)GC.getInfoTypeForString("COLOR_RED"), pPlot->getX_INLINE(), pPlot->getY_INLINE(), true, true);
szBuffer = gDLL->getText("TXT_KEY_MISC_YOU_ATTACK_BY_AIR", getNameKey(), pDefender->getNameKey(), -(((iUnitDamage - pDefender->getDamage()) * 100) / pDefender->maxHitPoints()));
gDLL->getInterfaceIFace()->addMessage(getOwnerINLINE(), true, GC.getEVENT_MESSAGE_TIME(), szBuffer, "AS2D_AIR_ATTACKED", MESSAGE_TYPE_INFO, pDefender->getButton(), (ColorTypes)GC.getInfoTypeForString("COLOR_GREEN"), pPlot->getX_INLINE(), pPlot->getY_INLINE());
collateralCombat(pPlot, pDefender);
pDefender->setDamage(iUnitDamage, getOwnerINLINE());
return true;
}
bool CvUnit::canRangeStrike() const
{
if (getDomainType() == DOMAIN_AIR)
{
return false;
}
if (airRange() <= 0)
{
return false;
}
if (airBaseCombatStr() <= 0)
{
return false;
}
if (!canFight())
{
return false;
}
if (isMadeAttack() && !isBlitz())
{
return false;
}
if (!canMove() && getMoves() > 0)
{
return false;
}
return true;
}
bool CvUnit::canRangeStrikeAt(const CvPlot* pPlot, int iX, int iY) const
{
if (!canRangeStrike())
{
return false;
}
CvPlot* pTargetPlot = GC.getMapINLINE().plotINLINE(iX, iY);
if (NULL == pTargetPlot)
{
return false;
}
if (!pPlot->isVisible(getTeam(), false))
{
return false;
}
if (plotDistance(pPlot->getX_INLINE(), pPlot->getY_INLINE(), pTargetPlot->getX_INLINE(), pTargetPlot->getY_INLINE()) > airRange())
{
return false;
}
CvUnit* pDefender = airStrikeTarget(pTargetPlot);
if (NULL == pDefender)
{
return false;
}
if (!pPlot->canSeePlot(pTargetPlot, getTeam(), airRange(), getFacingDirection(true)))
{
return false;
}
return true;
}
bool CvUnit::rangeStrike(int iX, int iY)
{
CvUnit* pDefender;
CvWString szBuffer;
int iUnitDamage;
int iDamage;
CvPlot* pPlot = GC.getMapINLINE().plot(iX, iY);
if (NULL == pPlot)
{
return false;
}
if (!canRangeStrikeAt(pPlot, iX, iY))
{
return false;
}
pDefender = airStrikeTarget(pPlot);
FAssert(pDefender != NULL);
FAssert(pDefender->canDefend());
if (GC.getDefineINT("RANGED_ATTACKS_USE_MOVES") == 0)
{
setMadeAttack(true);
}
changeMoves(GC.getMOVE_DENOMINATOR());
iDamage = rangeCombatDamage(pDefender);
iUnitDamage = std::max(pDefender->getDamage(), std::min((pDefender->getDamage() + iDamage), airCombatLimit()));
szBuffer = gDLL->getText("TXT_KEY_MISC_YOU_ARE_ATTACKED_BY_AIR", pDefender->getNameKey(), getNameKey(), -(((iUnitDamage - pDefender->getDamage()) * 100) / pDefender->maxHitPoints()));
//red icon over attacking unit
gDLL->getInterfaceIFace()->addMessage(pDefender->getOwnerINLINE(), false, GC.getEVENT_MESSAGE_TIME(), szBuffer, "AS2D_COMBAT", MESSAGE_TYPE_INFO, getButton(), (ColorTypes)GC.getInfoTypeForString("COLOR_RED"), this->getX_INLINE(), this->getY_INLINE(), true, true);
//white icon over defending unit
gDLL->getInterfaceIFace()->addMessage(pDefender->getOwnerINLINE(), false, 0, L"", "AS2D_COMBAT", MESSAGE_TYPE_DISPLAY_ONLY, pDefender->getButton(), (ColorTypes)GC.getInfoTypeForString("COLOR_WHITE"), pDefender->getX_INLINE(), pDefender->getY_INLINE(), true, true);
szBuffer = gDLL->getText("TXT_KEY_MISC_YOU_ATTACK_BY_AIR", getNameKey(), pDefender->getNameKey(), -(((iUnitDamage - pDefender->getDamage()) * 100) / pDefender->maxHitPoints()));
gDLL->getInterfaceIFace()->addMessage(getOwnerINLINE(), true, GC.getEVENT_MESSAGE_TIME(), szBuffer, "AS2D_COMBAT", MESSAGE_TYPE_INFO, pDefender->getButton(), (ColorTypes)GC.getInfoTypeForString("COLOR_GREEN"), pPlot->getX_INLINE(), pPlot->getY_INLINE());
collateralCombat(pPlot, pDefender);
//set damage but don't update entity damage visibility
pDefender->setDamage(iUnitDamage, getOwnerINLINE(), false);
if (pPlot->isActiveVisible(false))
{
// Range strike entity mission
CvMissionDefinition kDefiniton;
kDefiniton.setMissionTime(GC.getMissionInfo(MISSION_RANGE_ATTACK).getTime() * gDLL->getSecsPerTurn());
kDefiniton.setMissionType(MISSION_RANGE_ATTACK);
kDefiniton.setPlot(pDefender->plot());
kDefiniton.setUnit(BATTLE_UNIT_ATTACKER, this);
kDefiniton.setUnit(BATTLE_UNIT_DEFENDER, pDefender);
gDLL->getEntityIFace()->AddMission(&kDefiniton);
//delay death
pDefender->getGroup()->setMissionTimer(GC.getMissionInfo(MISSION_RANGE_ATTACK).getTime());
}
return true;
}