Well, to start with the beginning : I always wanted ranged siege instead of suicide sieges.
So I changed AirDamage and AirRange for the sieges, which gives them what is known in the dll as
canRangeStrike code starts here
CvUnit.cpp - > bool CvUnit::canRangeStrike() const
I added this so it couldnt shoot from cargohold in ships
Code:
// Vincentz range if cargo off
if (isCargo())
{
return false;
}
and later in -> bool CvUnit::canRangeStrikeAt(const CvPlot* pPlot, int iX, int iY) const
I removed this, because otherwise it couldnt shoot above a forest
Code:
// if (!pPlot->canSeePlot(pTargetPlot, getTeam(), airRange(), getFacingDirection(true)))
// {
// return false;
// }
In CvGameInterface.cpp -> else if(pHeadSelectedUnit->airRange() > 0) //other ranged units
I replaced the "show where attack is possible" with the airstrike, because it would otherwise only show visible/unblocked areas. Example after fix:
Code:
else if(pHeadSelectedUnit->airRange() > 0) //other ranged units
{
iMaxAirRange = 0;
pSelectedUnitNode = gDLL->getInterfaceIFace()->headSelectionListNode();
while (pSelectedUnitNode != NULL)
{
pSelectedUnit = ::getUnit(pSelectedUnitNode->m_data);
pSelectedUnitNode = gDLL->getInterfaceIFace()->nextSelectionListNode(pSelectedUnitNode);
if (pSelectedUnit != NULL)
{
iMaxAirRange = std::max(iMaxAirRange, pSelectedUnit->airRange());
}
}
if (iMaxAirRange > 0)
{
for (iDX = -(iMaxAirRange); iDX <= iMaxAirRange; iDX++)
{
for (iDY = -(iMaxAirRange); iDY <= iMaxAirRange; iDY++)
{
pLoopPlot = plotXY(pHeadSelectedUnit->getX_INLINE(), pHeadSelectedUnit->getY_INLINE(), iDX, iDY);
if (pLoopPlot != NULL)
{
if (plotDistance(pHeadSelectedUnit->getX_INLINE(), pHeadSelectedUnit->getY_INLINE(), pLoopPlot->getX_INLINE(), pLoopPlot->getY_INLINE()) <= iMaxAirRange)
{
NiColorA color(GC.getColorInfo((ColorTypes)GC.getInfoTypeForString("COLOR_RED")).getColor());
color.a = 0.5f;
gDLL->getEngineIFace()->fillAreaBorderPlot(pLoopPlot->getX_INLINE(), pLoopPlot->getY_INLINE(), color, AREA_BORDER_LAYER_RANGED);
}
}
}
}
}
// Vincentz off
// int iRange = pHeadSelectedUnit->airRange();
// for (iDX = -(iRange); iDX <= iRange; iDX++)
// {
// for (iDY = -(iRange); iDY <= iRange; iDY++)
// {
// CvPlot* pTargetPlot = plotXY(pHeadSelectedUnit->getX_INLINE(), pHeadSelectedUnit->getY_INLINE(), iDX, iDY);
//
// if (pTargetPlot != NULL && pTargetPlot->isVisible(pHeadSelectedUnit->getTeam(), false)) Vincentz
// if (pTargetPlot != NULL)
// {
// if (plotDistance(pHeadSelectedUnit->getX_INLINE(), pHeadSelectedUnit->getY_INLINE(), pTargetPlot->getX_INLINE(), pTargetPlot->getY_INLINE()) <= iRange)
// {
// if (pHeadSelectedUnit->plot()->canSeePlot(pTargetPlot, pHeadSelectedUnit->getTeam(), iRange, pHeadSelectedUnit->getFacingDirection(true)))
// {
// NiColorA color(GC.getColorInfo((ColorTypes)GC.getInfoTypeForString("COLOR_YELLOW")).getColor());
// color.a = 0.5f;
// gDLL->getEngineIFace()->fillAreaBorderPlot(pTargetPlot->getX_INLINE(), pTargetPlot->getY_INLINE(), color, AREA_BORDER_LAYER_RANGED);
// }
// }
// }
// }
// }
}
and that, iirc, was pretty much it. In the tests I made, if I place multiple sieges, they will fire ranged attacks except for one.
to be contiued... (have a tired 3 year old son
)
EDIT :
While the AI does use rangestrike as defense (when sieges are in city) it uses direct attack when offensive. I'd love for the AI to simply use Rangestrike before considering using direct attack
Dbl EDIT :
Thinking about it, maybe its as simple as putting a :
If unit(airdamage) > 0 AND unit!=AirUnit then ->pushMission(MISSION_RANGE_ATTACK, pBestPlot->getX_INLINE(), pBestPlot->getY_INLINE(), 0);
where the normal attack sequence is.
(I'm not a programmer and the above is of course not correct language)
Maybe somewhere here :
CvUnitAI.CPP
Code:
// Returns true if a mission was pushed...
bool CvUnitAI::AI_anyAttack(int iRange, int iOddsThreshold, int iMinStack, bool bFollow)
{
PROFILE_FUNC();
CvPlot* pLoopPlot;
CvPlot* pBestPlot;
int iSearchRange;
int iPathTurns;
int iValue;
int iBestValue;
int iDX, iDY;
FAssert(canMove());
if (AI_rangeAttack(iRange))
{
return true;
}
if (bFollow)
{
iSearchRange = 1;
}
else
{
iSearchRange = AI_searchRange(iRange);
}
iBestValue = 0;
pBestPlot = NULL;
for (iDX = -(iSearchRange); iDX <= iSearchRange; iDX++)
{
for (iDY = -(iSearchRange); iDY <= iSearchRange; iDY++)
{
pLoopPlot = plotXY(getX_INLINE(), getY_INLINE(), iDX, iDY);
if (pLoopPlot != NULL)
{
if (AI_plotValid(pLoopPlot))
{
if (pLoopPlot->isVisibleEnemyUnit(this) || (pLoopPlot->isCity() && AI_potentialEnemy(pLoopPlot->getTeam())))
{
if (!atPlot(pLoopPlot) && ((bFollow) ? canMoveInto(pLoopPlot, true) : (generatePath(pLoopPlot, 0, true, &iPathTurns) && (iPathTurns <= iRange))))
{
if (pLoopPlot->getNumVisibleEnemyDefenders(this) >= iMinStack)
{
iValue = getGroup()->AI_attackOdds(pLoopPlot, true);
if (iValue >= AI_finalOddsThreshold(pLoopPlot, iOddsThreshold))
{
if (iValue > iBestValue)
{
iBestValue = iValue;
pBestPlot = ((bFollow) ? pLoopPlot : getPathEndTurnPlot());
FAssert(!atPlot(pBestPlot));
}
}
}
}
}
}
}
}
}
if (pBestPlot != NULL)
{
FAssert(!atPlot(pBestPlot));
getGroup()->pushMission(MISSION_MOVE_TO, pBestPlot->getX_INLINE(), pBestPlot->getY_INLINE(), ((bFollow) ? MOVE_DIRECT_ATTACK : 0));
return true;
}
return false;
}
// Returns true if a mission was pushed...
bool CvUnitAI::AI_rangeAttack(int iRange)
{
PROFILE_FUNC();
FAssert(canMove());
if (!canRangeStrike())
{
return false;
}
int iSearchRange = AI_searchRange(iRange);
int iBestValue = 0;
CvPlot* pBestPlot = NULL;
for (int iDX = -(iSearchRange); iDX <= iSearchRange; iDX++)
{
for (int iDY = -(iSearchRange); iDY <= iSearchRange; iDY++)
{
CvPlot* pLoopPlot = plotXY(getX_INLINE(), getY_INLINE(), iDX, iDY);
if (pLoopPlot != NULL)
{
if (pLoopPlot->isVisibleEnemyUnit(this) || (pLoopPlot->isCity() && AI_potentialEnemy(pLoopPlot->getTeam())))
{
if (!atPlot(pLoopPlot) && canRangeStrikeAt(plot(), pLoopPlot->getX_INLINE(), pLoopPlot->getY_INLINE()))
{
int iValue = getGroup()->AI_attackOdds(pLoopPlot, true);
if (iValue > iBestValue)
{
iBestValue = iValue;
pBestPlot = pLoopPlot;
}
}
}
}
}
}
if (pBestPlot != NULL)
{
FAssert(!atPlot(pBestPlot));
getGroup()->pushMission(MISSION_RANGE_ATTACK, pBestPlot->getX_INLINE(), pBestPlot->getY_INLINE(), 0);
return true;
}
return false;
}