Hey guys, I've just wasted several hours trying to fix a bug in K-Mod that's not in base BtS. Perhaps one of you might like to take a crack at it. Here's how to produce the symptom: Worldbuilder yourself a barbarian city, add a barbarian archer and a barbarian fighter, then attack the city with a gunship. Unless the archer wins, your gunship conquers the city, which it should never be able to do. (Tipp: Search for "isNoCapture()".)
What do you mean by fighter? I think this bug is triggered when captureable unit is in city, i.e. worker.
So the problem only happens when there is a uncapturable unit left in the city, and you attack with a unit which cannot capture units/cities?
(so it works if there is a capturable unit instead or no unit at all, and also works if you attack with a normal unit)
This seems to be the culprit:My best guess at the moment is that karadoc's changes to CvSelectionGroup::groupMove introduced the bug, but I've been at it so long, I can't think straight anymore.
if (isNoCapture()) {
if (!bAttack)
if (pPlot->isEnemyCity(*this))
return false;
}
void CvSelectionGroup::groupMove(CvPlot* pPlot, bool bCombat, CvUnit* pCombatUnit, bool bEndMove)
{ // ...
while (pUnitNode != NULL)
{ // ...
if (pLoopUnit->canMove() && (bCombat ? pLoopUnit->canMoveOrAttackInto(pPlot) : pLoopUnit->canMoveInto(pPlot))
[COLOR="Blue"]&& (!pLoopUnit->isNoCapture() || !pPlot->isEnemyCity(*pLoopUnit))[/COLOR]
)
{
pLoopUnit->move(pPlot, true);
} // ...
for(int stage = 0; stage < 2; stage++) {
pUnitNode = headUnitNode();
while (pUnitNode != NULL) {
pLoopUnit = ::getUnit(pUnitNode->m_data);
pUnitNode = nextUnitNode(pUnitNode);
if((bool)stage != pLoopUnit->isNoCapture())
continue;
// ...
}
}
Strangely, this crashed my game. The following worked however.The easiest fix would be to restore the isNoCapture check from v1.43:
Code:void CvSelectionGroup::groupMove(CvPlot* pPlot, bool bCombat, CvUnit* pCombatUnit, bool bEndMove) { // ... while (pUnitNode != NULL) { // ... if (pLoopUnit->canMove() && (bCombat ? pLoopUnit->canMoveOrAttackInto(pPlot) : pLoopUnit->canMoveInto(pPlot)) [COLOR="Blue"]&& (!pLoopUnit->isNoCapture() || !pPlot->isEnemyCity(*pLoopUnit))[/COLOR] ) { pLoopUnit->move(pPlot, true); } // ...
void CvSelectionGroup::groupMove(CvPlot* pPlot, bool bCombat, CvUnit* pCombatUnit, bool bEndMove)
{ // ...
while (pUnitNode != NULL)
{ // ...
if (pLoopUnit->canMove() && (bCombat [COLOR="Blue"]&& (!pLoopUnit->isNoCapture() || !pPlot->isEnemyCity(*pLoopUnit))[/COLOR] ? pLoopUnit->canMoveOrAttackInto(pPlot) : pLoopUnit->canMoveInto(pPlot)))
{
pLoopUnit->move(pPlot, true);
} // ...
The reason for that would appear to lie in CvUnit::updateCombat:If the Mech. Infantry would advance first, isEnemyCity would immediately become false, and the Gunship could also advance. Always moving noCapture units last seems to fix this problem, but the two attackers somehow still end up in separate groups (though both in the city tile). Upd.: Or rather - they're in the same group, but only the capturing unit is selected.
bool bAdvance = false;
if (isSuicide())
{
kill(true);
pDefender->kill(false);
pDefender = NULL;
}
else
{
bAdvance = canAdvance(pPlot, ((pDefender->canDefend()) ? 1 : 0));
if (bAdvance)
{
if (!isNoCapture())
{
pDefender->setCapturingPlayer(getOwnerINLINE());
}
}
pDefender->kill(false);
pDefender = NULL;
if (!bAdvance)
{
[COLOR="Blue"]changeMoves(std::max(GC.getMOVE_DENOMINATOR(), pPlot->movementCost(this, plot())));
checkRemoveSelectionAfterAttack();[/color]
}
}
I thought this would come down to the same thing (because canMoveInto returns false when isNoCapture and isEnemyCity) - apparently not.Strangely, this crashed my game. The following worked however. [...]
Ah, yes, looks like it. Good to know, but not so easy to fix. Oh well.The reason for that would appear to lie in CvUnit::updateCombat:[...]
I thought this would come down to the same thing (because canMoveInto returns false when isNoCapture and isEnemyCity) - apparently not.
Ah, yes, looks like it. Good to know, but not so easy to fix. Oh well.
I've been looking for to activate the sentry plus healed button, sentry land units, sentry sea units etc that normally come with BUG, but I've haven't found them. Aren't these included in K-Mod?
Would that be hard for someone who has no knowledge of DLL's?
It seems that there's an OOS bug which happens when someone on Windows 7 plays with someone on Windows 8/10. It starts happening approx after 200th turn on normal speed. I'll try to check what's happening.